osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #ifdef OSGEARTH_HAVE_GEOS 00020 00021 #include <osgEarthSymbology/GEOS> 00022 #include <osg/Notify> 00023 00024 #include <geos/geom/PrecisionModel.h> 00025 #include <geos/geom/GeometryFactory.h> 00026 #include <geos/geom/Coordinate.h> 00027 #include <geos/geom/CoordinateSequence.h> 00028 #include <geos/geom/CoordinateArraySequenceFactory.h> 00029 #include <geos/geom/Geometry.h> 00030 #include <geos/geom/Point.h> 00031 #include <geos/geom/MultiPoint.h> 00032 #include <geos/geom/Polygon.h> 00033 #include <geos/geom/MultiPolygon.h> 00034 #include <geos/geom/LineString.h> 00035 #include <geos/geom/MultiLineString.h> 00036 #include <geos/geom/LinearRing.h> 00037 #include <geos/operation/valid/IsValidOp.h> 00038 #include <geos/util/IllegalArgumentException.h> 00039 00040 using namespace osgEarth; 00041 using namespace osgEarth::Symbology; 00042 using namespace geos; 00043 using namespace geos::operation; 00044 00045 00046 static 00047 geom::CoordinateSequence* 00048 vec3dArray2CoordSeq( const Symbology::Geometry* input, bool close, const geom::CoordinateSequenceFactory* factory ) 00049 { 00050 bool needToClose = close && input->size() > 2 && input->front() != input->back(); 00051 00052 std::vector<geos::geom::Coordinate>* coords = new std::vector<geom::Coordinate>(); 00053 coords->reserve( input->size() + (needToClose ? 1 : 0) ); 00054 for( osg::Vec3dArray::const_iterator i = input->begin(); i != input->end(); ++i ) 00055 { 00056 coords->push_back( geom::Coordinate( i->x(), i->y() ) ); //, i->z() )); 00057 } 00058 if ( needToClose ) 00059 { 00060 coords->push_back( coords->front() ); 00061 } 00062 geom::CoordinateSequence* seq = factory->create( coords ); 00063 00064 return seq; 00065 } 00066 00067 static geom::Geometry* 00068 import( const Symbology::Geometry* input, const geom::GeometryFactory* f ) 00069 { 00070 geom::Geometry* output = 0L; 00071 00072 if ( input->getType() == Symbology::Geometry::TYPE_UNKNOWN ) 00073 { 00074 output = 0L; 00075 } 00076 else if ( input->getType() == Symbology::Geometry::TYPE_MULTI ) 00077 { 00078 const Symbology::MultiGeometry* multi = static_cast<const Symbology::MultiGeometry*>( input ); 00079 00080 Symbology::Geometry::Type compType = multi->getComponentType(); 00081 00082 std::vector<geom::Geometry*>* children = new std::vector<geom::Geometry*>(); 00083 for( Symbology::GeometryCollection::const_iterator i = multi->getComponents().begin(); i != multi->getComponents().end(); ++i ) 00084 { 00085 geom::Geometry* child = import( i->get(), f ); 00086 if ( child ) 00087 children->push_back( child ); 00088 } 00089 if ( children->size() > 0 ) 00090 { 00091 if ( compType == Symbology::Geometry::TYPE_POLYGON ) 00092 output = f->createMultiPolygon( children ); 00093 else if ( compType == Symbology::Geometry::TYPE_LINESTRING ) 00094 output = f->createMultiLineString( children ); 00095 else if ( compType == Symbology::Geometry::TYPE_POINTSET ) 00096 output = f->createMultiPoint( children ); 00097 else 00098 output = f->createGeometryCollection( children ); 00099 } 00100 else 00101 delete children; 00102 } 00103 else 00104 { 00105 // any other type will at least contain points: 00106 geom::CoordinateSequence* seq = 0L; 00107 try 00108 { 00109 switch( input->getType() ) 00110 { 00111 case Symbology::Geometry::TYPE_POINTSET: 00112 seq = vec3dArray2CoordSeq( input, false, f->getCoordinateSequenceFactory() ); 00113 if ( seq ) output = f->createPoint( seq ); 00114 break; 00115 00116 case Symbology::Geometry::TYPE_LINESTRING: 00117 seq = vec3dArray2CoordSeq( input, false, f->getCoordinateSequenceFactory() ); 00118 if ( seq ) output = f->createLineString( seq ); 00119 break; 00120 00121 case Symbology::Geometry::TYPE_RING: 00122 seq = vec3dArray2CoordSeq( input, true, f->getCoordinateSequenceFactory() ); 00123 if ( seq ) output = f->createLinearRing( seq ); 00124 break; 00125 00126 case Symbology::Geometry::TYPE_POLYGON: 00127 seq = vec3dArray2CoordSeq( input, true, f->getCoordinateSequenceFactory() ); 00128 geom::LinearRing* shell = 0L; 00129 if ( seq ) 00130 shell = f->createLinearRing( seq ); 00131 00132 if ( shell ) 00133 { 00134 const Symbology::Polygon* poly = static_cast<const Symbology::Polygon*>(input); 00135 std::vector<geom::Geometry*>* holes = poly->getHoles().size() > 0 ? new std::vector<geom::Geometry*>() : 0L; 00136 for( Symbology::RingCollection::const_iterator r = poly->getHoles().begin(); r != poly->getHoles().end(); ++r ) 00137 { 00138 geom::Geometry* hole = import( r->get(), f ); 00139 if ( hole ) holes->push_back( hole ); 00140 } 00141 if ( holes && holes->size() == 0 ) 00142 { 00143 delete holes; 00144 holes = 0L; 00145 } 00146 output = f->createPolygon( shell, holes ); 00147 } 00148 00149 break; 00150 } 00151 } 00152 catch( util::IllegalArgumentException ) 00153 { 00154 // catch GEOS exceptions.. 00155 //if ( seq ) 00156 // delete seq; 00157 00158 OE_NOTICE << "GEOS::import: Removed degenerate geometry" << std::endl; 00159 } 00160 } 00161 00162 return output; 00163 } 00164 00165 geom::Geometry* 00166 GEOSUtils::importGeometry( const Symbology::Geometry* input ) 00167 { 00168 geom::Geometry* output = 0L; 00169 if ( input && input->isValid() ) 00170 { 00171 geom::PrecisionModel* pm = new geom::PrecisionModel( geom::PrecisionModel::FLOATING ); 00172 const geom::GeometryFactory* f = new geom::GeometryFactory( pm ); 00173 00174 output = import( input, f ); 00175 00176 // if output is ok, it will have a pointer to f. this is probably a leak. 00177 if ( !output ) 00178 delete f; 00179 } 00180 return output; 00181 } 00182 00183 static Symbology::Geometry* 00184 exportPolygon( const geom::Polygon* input ) 00185 { 00186 Symbology::Polygon* output = 0L; 00187 const geom::LineString* outerRing = input->getExteriorRing(); 00188 if ( outerRing ) 00189 { 00190 const geom::CoordinateSequence* s = outerRing->getCoordinates(); 00191 output = new Symbology::Polygon( s->getSize() ); 00192 for( unsigned int j=0; j<s->getSize(); j++ ) 00193 { 00194 const geom::Coordinate& c = s->getAt( j ); 00195 output->push_back( osg::Vec3d( c.x, c.y, 0 ) ); 00196 } 00197 output->rewind( Symbology::Ring::ORIENTATION_CCW ); 00198 00199 for( int k=0; k < input->getNumInteriorRing(); k++ ) 00200 { 00201 const geom::LineString* inner = input->getInteriorRingN( k ); 00202 const geom::CoordinateSequence* s = inner->getCoordinates(); 00203 Symbology::Ring* hole = new Symbology::Ring( s->getSize() ); 00204 for( unsigned int m = 0; m<s->getSize(); m++ ) 00205 { 00206 const geom::Coordinate& c = s->getAt( m ); 00207 hole->push_back( osg::Vec3d( c.x, c.y, 0 ) ); 00208 } 00209 hole->rewind( Symbology::Ring::ORIENTATION_CW ); 00210 output->getHoles().push_back( hole ); 00211 } 00212 } 00213 return output; 00214 } 00215 00216 Symbology::Geometry* 00217 GEOSUtils::exportGeometry( const geom::Geometry* input ) 00218 { 00220 //valid::IsValidOp validator( input ); 00221 //if ( !validator.isValid() ) 00222 //{ 00223 // OE_NOTICE << "GEOS: discarding invalid geometry" << std::endl; 00224 // return 0L; 00225 //} 00226 00227 Symbology::GeometryCollection parts; 00228 00229 if ( dynamic_cast<const geom::Point*>( input ) ) 00230 { 00231 OE_NOTICE << "GEOS 'Point' NYI" << std::endl; 00232 } 00233 else if ( dynamic_cast<const geom::MultiPoint*>( input ) ) 00234 { 00235 const geom::MultiPoint* mp = dynamic_cast<const geom::MultiPoint*>( input ); 00236 Symbology::PointSet* part = new Symbology::PointSet( mp->getNumPoints() ); 00237 for( unsigned int i=0; i < mp->getNumPoints(); i++ ) 00238 { 00239 const geom::Point* p = dynamic_cast<const geom::Point*>( mp->getGeometryN(i) ); 00240 if ( p ) 00241 part->push_back( osg::Vec3d( p->getX(), p->getY(), 0 ) ); 00242 } 00243 parts.push_back( part ); 00244 } 00245 else if ( dynamic_cast<const geom::LineString*>( input ) ) 00246 { 00247 const geom::LineString* line = dynamic_cast<const geom::LineString*>( input ); 00248 Symbology::LineString* part = new Symbology::LineString( line->getNumPoints() ); 00249 for( unsigned int i=0; i<line->getNumPoints(); i++ ) 00250 { 00251 const geom::Coordinate& c = line->getCoordinateN(i); 00252 part->push_back( osg::Vec3d( c.x, c.y, 0 ) ); 00253 } 00254 parts.push_back( part ); 00255 } 00256 else if ( dynamic_cast<const geom::MultiLineString*>( input ) ) 00257 { 00258 const geom::MultiLineString* m = dynamic_cast<const geom::MultiLineString*>( input ); 00259 for( unsigned int i=0; i<m->getNumGeometries(); i++ ) 00260 { 00261 Symbology::Geometry* part = exportGeometry( m->getGeometryN(i) ); 00262 if ( part ) parts.push_back( part ); 00263 } 00264 } 00265 else if ( dynamic_cast<const geom::Polygon*>( input ) ) 00266 { 00267 const geom::Polygon* poly = dynamic_cast<const geom::Polygon*>( input ); 00268 Symbology::Geometry* part = exportPolygon( poly ); 00269 if ( part ) parts.push_back( part ); 00270 } 00271 else if ( dynamic_cast<const geom::MultiPolygon*>( input ) ) 00272 { 00273 //OE_NOTICE << "Multipolygon" << std::endl; 00274 const geom::MultiPolygon* mpoly = dynamic_cast<const geom::MultiPolygon*>( input ); 00275 for( unsigned int i=0; i<mpoly->getNumGeometries(); i++ ) 00276 { 00277 Symbology::Geometry* part = exportPolygon( dynamic_cast<const geom::Polygon*>( mpoly->getGeometryN(i) ) ); 00278 if ( part ) parts.push_back( part ); 00279 } 00280 } 00281 00282 if ( parts.size() == 1 ) 00283 { 00284 osg::ref_ptr<Symbology::Geometry> part = parts.front(); 00285 parts.clear(); 00286 return part.release(); 00287 } 00288 else if ( parts.size() > 1 ) 00289 { 00290 return new Symbology::MultiGeometry( parts ); 00291 } 00292 else 00293 { 00294 return 0L; 00295 } 00296 } 00297 00298 #endif // OSGEARTH_HAVE_GEOS 00299