Osmium
0.1
|
00001 #ifndef OSMIUM_HANDLER_MULTIPOLYGON_HPP 00002 #define OSMIUM_HANDLER_MULTIPOLYGON_HPP 00003 00004 /* 00005 00006 Copyright 2011 Jochen Topf <jochen@topf.org> and others (see README). 00007 00008 This file is part of Osmium (https://github.com/joto/osmium). 00009 00010 Osmium is free software: you can redistribute it and/or modify it under the 00011 terms of the GNU Lesser General Public License or (at your option) the GNU 00012 General Public License as published by the Free Software Foundation, either 00013 version 3 of the Licenses, or (at your option) any later version. 00014 00015 Osmium is distributed in the hope that it will be useful, but WITHOUT ANY 00016 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 00017 PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU 00018 General Public License for more details. 00019 00020 You should have received a copy of the Licenses along with Osmium. If not, see 00021 <http://www.gnu.org/licenses/>. 00022 00023 */ 00024 00025 #include <google/sparse_hash_map> 00026 00027 #include <osmium/handler.hpp> 00028 #include <osmium/osm/way.hpp> 00029 #include <osmium/osm/area.hpp> 00030 00031 namespace Osmium { 00032 00033 namespace Handler { 00034 00035 class Multipolygon : public Base { 00036 00038 std::vector<Osmium::OSM::AreaFromRelation*> m_areas; 00039 00040 // a map from way_id to a vector of indexes into the areas array 00041 // this is used to find in which multipolygon relations a way is 00042 typedef google::sparse_hash_map<osm_object_id_t, std::vector<osm_object_id_t> > way2areaidx_t; 00043 way2areaidx_t m_way2areaidx; 00044 00045 bool m_attempt_repair; 00046 void (*m_callback_area)(Osmium::OSM::Area*); 00047 00048 uint64_t m_count_ways_in_all_areas; 00049 00050 public: 00051 00052 Multipolygon(bool attempt_repair, 00053 void (*callback_area)(Osmium::OSM::Area*)) 00054 : Base(), 00055 m_areas(), 00056 m_way2areaidx(), 00057 m_attempt_repair(attempt_repair), 00058 m_callback_area(callback_area), 00059 m_count_ways_in_all_areas(0) { 00060 } 00061 00062 // in pass 1 00063 void relation(const shared_ptr<Osmium::OSM::Relation const>& relation) { 00064 const char* type = relation->tags().get_tag_by_key("type"); 00065 00066 // ignore relations without "type" tag 00067 if (!type) { 00068 return; 00069 } 00070 00071 bool is_boundary; 00072 if (strcmp(type, "multipolygon") == 0) { 00073 is_boundary = false; 00074 } else if (strcmp(type, "boundary") == 0) { 00075 is_boundary = true; 00076 } else { 00077 return; 00078 } 00079 00080 int num_ways = 0; 00081 for (osm_sequence_id_t i=0; i < relation->members().size(); i++) { 00082 const Osmium::OSM::RelationMember* member = relation->get_member(i); 00083 if (member->type() == 'w') { 00084 m_way2areaidx[member->ref()].push_back(m_areas.size()); 00085 num_ways++; 00086 } else { 00087 std::cerr << "warning: multipolygon/boundary relation " 00088 << relation->id() 00089 << " has a non-way member which was ignored\n"; 00090 } 00091 } 00092 00093 m_count_ways_in_all_areas += num_ways; 00094 00095 Osmium::OSM::AreaFromRelation* area = new Osmium::OSM::AreaFromRelation(new Osmium::OSM::Relation(*relation), is_boundary, num_ways, m_callback_area, m_attempt_repair); 00096 m_areas.push_back(area); 00097 } 00098 00099 // in pass 1 00100 void after_relations() { 00101 if (Osmium::debug()) { 00102 std::cerr << "found " << m_areas.size() << " areas (each needs " 00103 << sizeof(Osmium::OSM::Area) << " bytes, thats together about " 00104 << sizeof(Osmium::OSM::Area) * m_areas.size() / (1024 * 1024) << "MB)\n" 00105 << "they used " << m_count_ways_in_all_areas << " ways (each will need " 00106 << sizeof(Osmium::OSM::Way) << " bytes, thats in the worst case together about " 00107 << sizeof(Osmium::OSM::Way) * m_count_ways_in_all_areas / (1024 * 1024) << "MB)\n"; 00108 } 00109 } 00110 00111 // in pass 2 00112 void way(const shared_ptr<Osmium::OSM::Way>& way) { 00113 way2areaidx_t::const_iterator way2areaidx_iterator(m_way2areaidx.find(way->id())); 00114 00115 if (way2areaidx_iterator == m_way2areaidx.end()) { // not in any relation 00116 if (way->is_closed() && way->node_count() >= 4) { // way is closed and has enough nodes, build simple multipolygon 00117 #ifdef OSMIUM_WITH_GEOS 00118 Osmium::Geometry::Polygon polygon(*way); 00119 Osmium::OSM::AreaFromWay* area = new Osmium::OSM::AreaFromWay(way.get(), polygon.create_geos_geometry()); 00120 #else 00121 Osmium::OSM::AreaFromWay* area = new Osmium::OSM::AreaFromWay(way.get()); 00122 #endif // OSMIUM_WITH_GEOS 00123 if (Osmium::debug()) { 00124 std::cerr << "MP simple way_id=" << way->id() << "\n"; 00125 } 00126 m_callback_area(area); 00127 delete area; 00128 } 00129 return; 00130 } 00131 00132 // is in at least one multipolygon relation 00133 00134 std::vector<osm_object_id_t> v = way2areaidx_iterator->second; 00135 if (Osmium::debug()) std::cerr << "MP way_id=" << way->id() << " is in " << v.size() << " areas\n"; 00136 00137 // go through all the areas this way is in 00138 for (unsigned int i=0; i < v.size(); i++) { 00139 Osmium::OSM::AreaFromRelation* area = m_areas[v[i]]; 00140 if (!area) { 00141 throw std::runtime_error("Zero multipolygon. This should not happen. Reason can be a way appearing more than once in your input file."); 00142 } 00143 if (Osmium::debug()) { 00144 std::cerr << "MP multi way_id=" << way->id() << " is in relation_id=" << area->id() << "\n"; 00145 } 00146 00147 // store copy of current way in multipolygon 00148 area->add_member_way(way.get()); 00149 00150 if (area->is_complete()) { 00151 area->handle_complete_multipolygon(); 00152 m_areas[v[i]] = NULL; 00153 delete area; 00154 } 00155 } 00156 } 00157 00158 // in pass 2 00159 void after_ways() { 00160 m_way2areaidx.clear(); 00161 } 00162 00163 void init(Osmium::OSM::Meta&) { 00164 #ifdef OSMIUM_WITH_MULTIPOLYGON_PROFILING 00165 Osmium::OSM::AreaFromRelation::init_timings(); 00166 #endif // OSMIUM_WITH_MULTIPOLYGON_PROFILING 00167 } 00168 00169 void final() { 00170 #ifdef OSMIUM_WITH_MULTIPOLYGON_PROFILING 00171 Osmium::OSM::AreaFromRelation::print_timings(); 00172 #endif // OSMIUM_WITH_MULTIPOLYGON_PROFILING 00173 } 00174 00175 }; // class Multipolygon 00176 00177 } // namespace Handler 00178 00179 } // namespace Osmium 00180 00181 #endif // OSMIUM_HANDLER_MULTIPOLYGON_HPP