osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthSymbology/GEOS.cpp

Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines