Osmium  0.1
include/osmium/geometry/multipolygon.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines