Osmium
0.1
|
00001 #ifndef OSMIUM_GEOMETRY_MULTIPOLYGON_HPP 00002 #define OSMIUM_GEOMETRY_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 #ifdef OSMIUM_WITH_GEOS 00026 # include <geos/io/WKBWriter.h> 00027 #endif // OSMIUM_WITH_GEOS 00028 00029 #include <osmium/osm/area.hpp> 00030 #include <osmium/geometry.hpp> 00031 00032 namespace Osmium { 00033 00034 namespace Geometry { 00035 00036 class MultiPolygon : public Geometry { 00037 00038 public: 00039 00040 MultiPolygon(const Osmium::OSM::Area& area) : Geometry(area.id()), m_area(&area) { 00041 #ifdef OSMIUM_WITH_GEOS 00042 if (!m_area->get_geometry()) { 00043 throw Osmium::Exception::IllegalGeometry(); 00044 } 00045 #endif // OSMIUM_WITH_GEOS 00046 } 00047 00048 #ifdef OSMIUM_WITH_GEOS 00049 # ifdef OSMIUM_WITH_SHPLIB 00050 00051 private: 00052 00053 void dump_geometry(const geos::geom::Geometry* g, std::vector<int>& part_start_list, std::vector<double>& x_list, std::vector<double>& y_list) const { 00054 switch (g->getGeometryTypeId()) { 00055 case geos::geom::GEOS_MULTIPOLYGON: 00056 case geos::geom::GEOS_MULTILINESTRING: { 00057 for (geos::geom::GeometryCollection::const_iterator it = static_cast<const geos::geom::GeometryCollection*>(g)->begin(); 00058 it != static_cast<const geos::geom::GeometryCollection*>(g)->end(); ++it) { 00059 dump_geometry(*it, part_start_list, x_list, y_list); 00060 } 00061 break; 00062 } 00063 case geos::geom::GEOS_POLYGON: { 00064 const geos::geom::Polygon* polygon = static_cast<const geos::geom::Polygon*>(g); 00065 dump_geometry(polygon->getExteriorRing(), part_start_list, x_list, y_list); 00066 for (size_t i=0; i < polygon->getNumInteriorRing(); ++i) { 00067 dump_geometry(polygon->getInteriorRingN(i), part_start_list, x_list, y_list); 00068 } 00069 break; 00070 } 00071 case geos::geom::GEOS_LINESTRING: 00072 case geos::geom::GEOS_LINEARRING: { 00073 part_start_list.push_back(x_list.size()); 00074 const geos::geom::CoordinateSequence* cs = static_cast<const geos::geom::LineString*>(g)->getCoordinatesRO(); 00075 for (size_t i = 0; i < cs->getSize(); ++i) { 00076 x_list.push_back(cs->getX(i)); 00077 y_list.push_back(cs->getY(i)); 00078 } 00079 break; 00080 } 00081 default: 00082 throw std::runtime_error("invalid geometry type encountered"); 00083 } 00084 } 00085 00086 public: 00087 00094 SHPObject* create_shp_object() const { 00095 if (!m_area->get_geometry()) { 00096 throw Osmium::Exception::IllegalGeometry(); 00097 } 00098 00099 std::vector<double> x_list; 00100 std::vector<double> y_list; 00101 std::vector<int> part_start_list; 00102 00103 dump_geometry(m_area->get_geometry(), part_start_list, x_list, y_list); 00104 00105 return SHPCreateObject( 00106 SHPT_POLYGON, // nSHPType 00107 -1, // iShape 00108 part_start_list.size(), // nParts 00109 &part_start_list[0], // panPartStart 00110 NULL, // panPartType 00111 x_list.size(), // nVertices, 00112 &x_list[0], // padfX 00113 &y_list[0], // padfY 00114 NULL, // padfZ 00115 NULL); // padfM 00116 } 00117 # endif // OSMIUM_WITH_SHPLIB 00118 00119 std::ostream& write_to_stream(std::ostream& out, AsWKT, bool with_srid=false) const { 00120 if (with_srid) { 00121 out << "SRID=4326;"; 00122 } 00123 geos::io::WKTWriter writer; 00124 return out << writer.write(m_area->get_geometry()); 00125 } 00126 00127 std::ostream& write_to_stream(std::ostream& out, AsWKB, bool with_srid=false) const { 00128 geos::io::WKBWriter writer; 00129 writer.setIncludeSRID(with_srid); 00130 writer.write(*(m_area->get_geometry()), out); 00131 return out; 00132 } 00133 00134 std::ostream& write_to_stream(std::ostream& out, AsHexWKB, bool with_srid=false) const { 00135 geos::io::WKBWriter writer; 00136 writer.setIncludeSRID(with_srid); 00137 writer.writeHEX(*(m_area->get_geometry()), out); 00138 return out; 00139 } 00140 00141 # ifdef OSMIUM_WITH_JAVASCRIPT 00142 v8::Local<v8::Object> js_instance() const { 00143 return JavascriptTemplate::get<JavascriptTemplate>().create_instance((void*)this); 00144 } 00145 00146 v8::Handle<v8::Array> js_ring_as_array(const geos::geom::LineString* ring) const { 00147 v8::HandleScope scope; 00148 const geos::geom::CoordinateSequence* cs = ring->getCoordinatesRO(); 00149 v8::Local<v8::Array> ring_array = v8::Array::New(cs->getSize()); 00150 for (size_t i = 0; i < cs->getSize(); ++i) { 00151 v8::Local<v8::Array> coord = v8::Array::New(2); 00152 coord->Set(0, v8::Number::New(cs->getX(i))); 00153 coord->Set(1, v8::Number::New(cs->getY(i))); 00154 ring_array->Set(i, coord); 00155 } 00156 00157 return scope.Close(ring_array); 00158 } 00159 00160 v8::Handle<v8::Value> js_to_array(const v8::Arguments& /*args*/) { 00161 v8::HandleScope scope; 00162 geos::geom::Geometry* geometry = m_area->get_geometry(); 00163 00164 if (geometry->getGeometryTypeId() == geos::geom::GEOS_MULTIPOLYGON) { 00165 v8::Local<v8::Array> multipolygon_array = v8::Array::New(geometry->getNumGeometries()); 00166 00167 for (size_t i=0; i < geometry->getNumGeometries(); ++i) { 00168 geos::geom::Polygon* polygon = (geos::geom::Polygon*) geometry->getGeometryN(i); 00169 v8::Local<v8::Array> polygon_array = v8::Array::New(polygon->getNumInteriorRing()); 00170 multipolygon_array->Set(i, polygon_array); 00171 polygon_array->Set(0, js_ring_as_array(polygon->getExteriorRing())); 00172 for (size_t j=0; j < polygon->getNumInteriorRing(); ++j) { 00173 polygon_array->Set(j+1, js_ring_as_array(polygon->getInteriorRingN(j))); 00174 } 00175 } 00176 return scope.Close(multipolygon_array); 00177 } else if (geometry->getGeometryTypeId() == geos::geom::GEOS_POLYGON) { 00178 const Osmium::OSM::AreaFromWay* area_from_way = dynamic_cast<const Osmium::OSM::AreaFromWay*>(m_area); 00179 if (area_from_way) { 00180 v8::Local<v8::Array> polygon = v8::Array::New(1); 00181 v8::Local<v8::Array> ring = v8::Array::New(area_from_way->nodes().size()); 00182 int n = 0; 00183 for (Osmium::OSM::WayNodeList::const_iterator it = area_from_way->nodes().begin(); it != area_from_way->nodes().end(); ++it) { 00184 v8::Local<v8::Array> coord = v8::Array::New(2); 00185 coord->Set(0, v8::Number::New(it->lon())); 00186 coord->Set(1, v8::Number::New(it->lat())); 00187 ring->Set(n++, coord); 00188 } 00189 polygon->Set(0, ring); 00190 return scope.Close(polygon); 00191 } 00192 } 00193 00194 return scope.Close(v8::Undefined()); 00195 } 00196 00197 struct JavascriptTemplate : public Osmium::Geometry::Geometry::JavascriptTemplate { 00198 00199 JavascriptTemplate() : Osmium::Geometry::Geometry::JavascriptTemplate() { 00200 js_template->Set("toArray", v8::FunctionTemplate::New(function_template<MultiPolygon, &MultiPolygon::js_to_array>)); 00201 } 00202 00203 }; 00204 # endif // OSMIUM_WITH_JAVASCRIPT 00205 00206 # ifdef OSMIUM_WITH_OGR 00207 private: 00208 00209 void add_ring(OGRPolygon* ogrpolygon, const geos::geom::LineString* geosring) const { 00210 OGRLinearRing* ogrring = new OGRLinearRing; 00211 00212 const geos::geom::CoordinateSequence* cs = geosring->getCoordinatesRO(); 00213 ogrring->setNumPoints(cs->getSize()); 00214 00215 for (size_t i = 0; i < cs->getSize(); ++i) { 00216 ogrring->setPoint(i, cs->getX(i), cs->getY(i), 0); 00217 } 00218 00219 ogrpolygon->addRingDirectly(ogrring); 00220 }; 00221 00222 OGRPolygon* make_polygon(const geos::geom::Polygon* geospolygon) const { 00223 OGRPolygon* ogrpolygon = new OGRPolygon; 00224 00225 add_ring(ogrpolygon, geospolygon->getExteriorRing()); 00226 for (size_t i=0; i < geospolygon->getNumInteriorRing(); ++i) { 00227 add_ring(ogrpolygon, geospolygon->getInteriorRingN(i)); 00228 } 00229 00230 return ogrpolygon; 00231 } 00232 00233 public: 00234 00240 OGRMultiPolygon* create_ogr_geometry() const { 00241 OGRMultiPolygon* ogrmp = new OGRMultiPolygon; 00242 00243 if (m_area->get_geometry()->getGeometryTypeId() == geos::geom::GEOS_POLYGON) { 00244 OGRPolygon* ogrpolygon = make_polygon(dynamic_cast<const geos::geom::Polygon*>(m_area->get_geometry())); 00245 00246 OGRErr result = ogrmp->addGeometryDirectly(ogrpolygon); 00247 if (result != OGRERR_NONE) { 00248 throw Osmium::Exception::IllegalGeometry(); 00249 } 00250 return ogrmp; 00251 } 00252 00253 if (m_area->get_geometry()->getGeometryTypeId() != geos::geom::GEOS_MULTIPOLYGON) { 00254 throw Osmium::Exception::IllegalGeometry(); 00255 } 00256 00257 const geos::geom::GeometryCollection* geosgeom = dynamic_cast<const geos::geom::GeometryCollection*>(m_area->get_geometry()); 00258 for (geos::geom::GeometryCollection::const_iterator it = geosgeom->begin(); it != geosgeom->end(); ++it) { 00259 00260 OGRPolygon* ogrpolygon = make_polygon(dynamic_cast<const geos::geom::Polygon*>(*it)); 00261 00262 OGRErr result = ogrmp->addGeometryDirectly(ogrpolygon); 00263 if (result != OGRERR_NONE) { 00264 throw Osmium::Exception::IllegalGeometry(); 00265 } 00266 } 00267 00268 return ogrmp; 00269 } 00270 # endif // OSMIUM_WITH_OGR 00271 #endif // OSMIUM_WITH_GEOS 00272 00273 private: 00274 00275 const Osmium::OSM::Area* m_area; 00276 00277 }; // class MultiPolygon 00278 00279 } // namespace Geometry 00280 00281 } // namespace Osmium 00282 00283 #ifdef OSMIUM_WITH_JAVASCRIPT 00284 v8::Handle<v8::Value> Osmium::OSM::Area::js_geom() const { 00285 if (get_geometry()) { 00286 Osmium::Geometry::MultiPolygon* geom = new Osmium::Geometry::MultiPolygon(*this); 00287 return Osmium::Javascript::Template::get<Osmium::Geometry::MultiPolygon::JavascriptTemplate>().create_persistent_instance<Osmium::Geometry::MultiPolygon>(geom); 00288 } else { 00289 Osmium::Geometry::Null* geom = new Osmium::Geometry::Null(); 00290 return Osmium::Javascript::Template::get<Osmium::Geometry::Null::JavascriptTemplate>().create_persistent_instance<Osmium::Geometry::Null>(geom); 00291 } 00292 } 00293 #endif // OSMIUM_WITH_JAVASCRIPT 00294 00295 #endif // OSMIUM_GEOMETRY_MULTIPOLYGON_HPP