osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthSymbology/Geometry.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 #include <osgEarthSymbology/Geometry>
00020 #include <osgEarthSymbology/GEOS>
00021 #include <algorithm>
00022 #include <iterator>
00023 
00024 using namespace osgEarth;
00025 using namespace osgEarth::Symbology;
00026 
00027 #ifdef OSGEARTH_HAVE_GEOS
00028 #  include <geos/geom/Geometry.h>
00029 #  include <geos/geom/GeometryFactory.h>
00030 #  include <geos/operation/buffer/BufferOp.h>
00031 #  include <geos/operation/buffer/BufferBuilder.h> 
00032 #  include <geos/operation/overlay/OverlayOp.h>
00033 using namespace geos;
00034 using namespace geos::operation;
00035 #endif
00036 
00037 #define LC "[Geometry] "
00038 
00039 
00040 Geometry::Geometry( const Geometry& rhs ) :
00041 osgEarth::MixinVector<osg::Vec3d,osg::Referenced>( rhs )
00042 {
00043     //nop
00044 }
00045 
00046 Geometry::Geometry( int capacity )
00047 {
00048     if ( capacity > 0 )
00049         reserve( capacity );
00050 }
00051 
00052 Geometry::Geometry( const Vec3dVector* data )
00053 {
00054     reserve( data->size() );
00055     insert( begin(), data->begin(), data->end() );
00056 }
00057 
00058 int
00059 Geometry::getTotalPointCount() const
00060 {
00061     return size();
00062 }
00063 
00064 Bounds
00065 Geometry::getBounds() const
00066 {
00067     Bounds bounds;
00068     for( const_iterator i = begin(); i != end(); ++i )
00069         bounds.expandBy( i->x(), i->y(), i->z() );
00070     return bounds;
00071 }
00072 
00073 Geometry*
00074 Geometry::cloneAs( const Geometry::Type& newType ) const
00075 {
00076     //if ( newType == getType() )        
00077     //    return static_cast<Geometry*>( clone() );
00078     
00079     switch( newType )
00080     {
00081     case TYPE_POINTSET:
00082         return new PointSet( &this->asVector() );
00083     case TYPE_LINESTRING:
00084         return new LineString( &this->asVector() );
00085     case TYPE_RING:
00086         return new Ring( &this->asVector() );
00087     case TYPE_POLYGON:
00088         if ( dynamic_cast<const Polygon*>(this) )
00089             return new Polygon( *static_cast<const Polygon*>(this) );
00090         else
00091             return new Polygon( &this->asVector() );
00092     default:
00093         break;
00094     }
00095     return 0L;
00096 }
00097 
00098 osg::Vec3Array*
00099 Geometry::toVec3Array() const 
00100 {
00101     osg::Vec3Array* result = new osg::Vec3Array( this->size() );
00102     std::copy( begin(), end(), result->begin() );
00103     return result;
00104 }
00105 
00106 osg::Vec3dArray*
00107 Geometry::toVec3dArray() const 
00108 {
00109     osg::Vec3dArray* result = new osg::Vec3dArray( this->size() );
00110     std::copy( begin(), end(), result->begin() );
00111     return result;
00112 }
00113 
00114 Geometry*
00115 Geometry::create( Type type, const Vec3dVector* toCopy )
00116 {
00117     Geometry* output = 0L;
00118     switch( type ) {
00119         case TYPE_POINTSET:
00120             output = new PointSet( toCopy ); break;
00121         case TYPE_LINESTRING:
00122             output = new LineString( toCopy ); break;
00123         case TYPE_RING:
00124             output = new Ring( toCopy ); break;
00125         case TYPE_POLYGON:
00126             output = new Polygon( toCopy ); break;
00127         default:
00128             break;
00129     }
00130     return output;
00131 }
00132 
00133 bool
00134 Geometry::hasBufferOperation()
00135 {
00136 #ifdef OSGEARTH_HAVE_GEOS
00137     return true;
00138 #else
00139     return false;
00140 #endif
00141 }
00142 
00143 bool
00144 Geometry::buffer(double distance,
00145                  osg::ref_ptr<Geometry>& output,
00146                  const BufferParameters& params ) const
00147 {
00148 #ifdef OSGEARTH_HAVE_GEOS   
00149 
00150     geom::Geometry* inGeom = GEOSUtils::importGeometry( this );
00151     if ( inGeom )
00152     {
00153         buffer::BufferParameters::EndCapStyle geosEndCap =
00154             params._capStyle == BufferParameters::CAP_ROUND  ? buffer::BufferParameters::CAP_ROUND :
00155             params._capStyle == BufferParameters::CAP_SQUARE ? buffer::BufferParameters::CAP_SQUARE :
00156             params._capStyle == BufferParameters::CAP_FLAT   ? buffer::BufferParameters::CAP_FLAT :
00157             buffer::BufferParameters::CAP_SQUARE;
00158 
00159         buffer::BufferParameters::JoinStyle geosJoinStyle =
00160             params._joinStyle == BufferParameters::JOIN_ROUND ? buffer::BufferParameters::JOIN_ROUND :
00161             params._joinStyle == BufferParameters::JOIN_MITRE ? buffer::BufferParameters::JOIN_MITRE :
00162             params._joinStyle == BufferParameters::JOIN_BEVEL ? buffer::BufferParameters::JOIN_BEVEL :
00163             buffer::BufferParameters::JOIN_ROUND;
00164 
00165         //JB:  Referencing buffer::BufferParameters::DEFAULT_QUADRANT_SEGMENTS causes link errors b/c it is defined as a static in the header of BufferParameters.h and not defined in the cpp anywhere.
00166         //     This seems to only effect the Linux build, Windows works fine
00167         int geosQuadSegs = params._cornerSegs > 0 
00168             ? params._cornerSegs
00169             : 8;//buffer::BufferParameters::DEFAULT_QUADRANT_SEGMENTS;
00170 
00171         geom::Geometry* outGeom = NULL;
00172 
00173         buffer::BufferParameters geosBufferParams;
00174         geosBufferParams.setQuadrantSegments( geosQuadSegs );
00175         geosBufferParams.setEndCapStyle( geosEndCap );
00176         geosBufferParams.setJoinStyle( geosJoinStyle );
00177         buffer::BufferBuilder bufBuilder( geosBufferParams );
00178 
00179         if (params._singleSided)
00180         {
00181             outGeom = bufBuilder.bufferLineSingleSided(inGeom, distance, params._leftSide );
00182         }
00183         else
00184         {
00185             outGeom = bufBuilder.buffer(inGeom, distance );
00186         }
00187 
00188         if ( outGeom )
00189         {
00190             output = GEOSUtils::exportGeometry( outGeom );
00191             outGeom->getFactory()->destroyGeometry( outGeom );
00192         }
00193         else
00194         {
00195             OE_INFO << LC << "Buffer: no output geometry" << std::endl;
00196         }
00197 
00198         inGeom->getFactory()->destroyGeometry( inGeom );
00199     }
00200     return output.valid();
00201 
00202 #else // OSGEARTH_HAVE_GEOS
00203 
00204     OE_WARN << LC << "Buffer failed - GEOS not available" << std::endl;
00205     return false;
00206 
00207 #endif // OSGEARTH_HAVE_GEOS
00208 }
00209 
00210 bool
00211 Geometry::crop( const Polygon* cropPoly, osg::ref_ptr<Geometry>& output ) const
00212 {
00213 #ifdef OSGEARTH_HAVE_GEOS
00214 
00215     geom::GeometryFactory* f = new geom::GeometryFactory();
00216 
00217     //Create the GEOS Geometries
00218     geom::Geometry* inGeom = GEOSUtils::importGeometry( this );
00219     geom::Geometry* cropGeom = GEOSUtils::importGeometry( cropPoly );
00220 
00221     if ( inGeom )
00222     {    
00223         geom::Geometry* outGeom = 0L;
00224         try {
00225             outGeom = overlay::OverlayOp::overlayOp(
00226                 inGeom, cropGeom,
00227                 overlay::OverlayOp::opINTERSECTION );
00228         }
00229         catch( ... ) {
00230             outGeom = 0L;
00231             OE_NOTICE << LC << "::crop, GEOS overlay op exception, skipping feature" << std::endl;
00232         }
00233 
00234         if ( outGeom )
00235         {
00236             output = GEOSUtils::exportGeometry( outGeom );
00237             f->destroyGeometry( outGeom );
00238             if ( output.valid() && !output->isValid() )
00239             {
00240                 output = 0L;
00241             }
00242         }
00243     }
00244 
00245     //Destroy the geometry
00246     f->destroyGeometry( cropGeom );
00247     f->destroyGeometry( inGeom );
00248 
00249     delete f;
00250     return output.valid();
00251 
00252 #else // OSGEARTH_HAVE_GEOS
00253 
00254     OE_WARN << LC << "Crop failed - GEOS not available" << std::endl;
00255     return false;
00256 
00257 #endif // OSGEARTH_HAVE_GEOS
00258 }
00259 
00260 bool
00261 Geometry::difference( const Polygon* diffPolygon, osg::ref_ptr<Geometry>& output ) const
00262 {
00263 #ifdef OSGEARTH_HAVE_GEOS
00264 
00265     geom::GeometryFactory* f = new geom::GeometryFactory();
00266 
00267     //Create the GEOS Geometries
00268     geom::Geometry* inGeom = GEOSUtils::importGeometry( this );
00269     geom::Geometry* diffGeom = GEOSUtils::importGeometry( diffPolygon );
00270 
00271     if ( inGeom )
00272     {    
00273         geom::Geometry* outGeom = 0L;
00274         try {
00275             outGeom = overlay::OverlayOp::overlayOp(
00276                 inGeom, diffGeom,
00277                 overlay::OverlayOp::opDIFFERENCE );
00278         }
00279         catch( ... ) {
00280             outGeom = 0L;
00281             OE_NOTICE << LC << "::difference, GEOS overlay op exception, skipping feature" << std::endl;
00282         }
00283 
00284         if ( outGeom )
00285         {
00286             output = GEOSUtils::exportGeometry( outGeom );
00287             f->destroyGeometry( outGeom );
00288             if ( output.valid() && !output->isValid() )
00289             {
00290                 output = 0L;
00291             }
00292         }
00293     }
00294 
00295     //Destroy the geometry
00296     f->destroyGeometry( diffGeom );
00297     f->destroyGeometry( inGeom );
00298 
00299     delete f;
00300     return output.valid();
00301 
00302 #else // OSGEARTH_HAVE_GEOS
00303 
00304     OE_WARN << LC << "Difference failed - GEOS not available" << std::endl;
00305     return false;
00306 
00307 #endif // OSGEARTH_HAVE_GEOS
00308 }
00309 
00310 osg::Vec3d
00311 Geometry::localize()
00312 {
00313     osg::Vec3d offset;
00314 
00315     Bounds bounds = getBounds();
00316     if ( bounds.isValid() )
00317     {      
00318         osg::Vec2d center = bounds.center2d();
00319         offset.set( center.x(), center.y(), 0 );
00320 
00321         GeometryIterator i( this );
00322         while( i.hasMore() )
00323         {
00324             Geometry* part = i.next();
00325             for( Geometry::iterator j = part->begin(); j != part->end(); ++j )
00326             {
00327                 *j = *j - offset;
00328             }
00329         }
00330     }
00331 
00332     return offset;
00333 }
00334 
00335 void
00336 Geometry::delocalize( const osg::Vec3d& offset )
00337 {
00338     GeometryIterator i( this );
00339     while( i.hasMore() )
00340     {
00341         Geometry* part = i.next();
00342         for( Geometry::iterator j = part->begin(); j != part->end(); ++j )
00343         {
00344             *j = *j + offset;
00345         }
00346     }
00347 }
00348 
00349 //----------------------------------------------------------------------------
00350 
00351 PointSet::PointSet( const PointSet& rhs ) :
00352 Geometry( rhs )
00353 {
00354     //nop
00355 }
00356 
00357 //----------------------------------------------------------------------------
00358 
00359 LineString::LineString( const LineString& rhs ) :
00360 Geometry( rhs )
00361 {
00362     //nop
00363 }
00364 
00365 LineString::LineString( const Vec3dVector* data ) :
00366 Geometry( data )
00367 {
00368     //nop
00369 }
00370 
00371 double
00372 LineString::getLength() const
00373 {
00374     double length = 0;
00375     for (unsigned int i = 0; i < size()-1; ++i)
00376     {
00377         osg::Vec3d current = (*this)[i];
00378         osg::Vec3d next    = (*this)[i+1];
00379         length += (next - current).length();
00380     }
00381     return length;
00382 }
00383 
00384 bool
00385 LineString::getSegment(double length, osg::Vec3d& start, osg::Vec3d& end)
00386 {
00387     double pos = 0;
00388     for (unsigned int i = 0; i < size()-1; ++i)
00389     {
00390         osg::Vec3d current = (*this)[i];
00391         osg::Vec3d next    = (*this)[i+1];
00392         pos += (next - current).length();
00393         if (pos > length)
00394         {
00395             start = current;
00396             end = next;
00397             return true;
00398         }
00399     }
00400     return false;
00401 }
00402 
00403 //----------------------------------------------------------------------------
00404 
00405 Ring::Ring( const Ring& rhs ) :
00406 Geometry( rhs )
00407 {
00408     //nop
00409 }
00410 
00411 Ring::Ring( const Vec3dVector* data ) :
00412 Geometry( data )
00413 {
00414     open();
00415 }
00416 
00417 Geometry*
00418 Ring::cloneAs( const Geometry::Type& newType ) const
00419 {
00420     if ( newType == TYPE_LINESTRING )
00421     {
00422         LineString* line = new LineString( &this->asVector() );
00423         if ( line->size() > 1 && line->front() != line->back() )
00424             line->push_back( front() );
00425         return line;
00426     }
00427     else return Geometry::cloneAs( newType );
00428 }
00429 
00430 Ring::Orientation 
00431 Ring::getOrientation() const
00432 {
00433     // adjust for a non-open ring:
00434     int n = size();
00435     while( n > 0 && front() == back() )
00436         n--;
00437 
00438     if ( n < 3 )
00439         return Ring::ORIENTATION_DEGENERATE;
00440 
00441     // copy the open vec:
00442     std::vector<osg::Vec3d> v;
00443     v.reserve( n );
00444     std::copy( begin(), begin()+n, std::back_inserter(v) );
00445 
00446     int rmin = 0;
00447     double xmin = v[0].x();
00448     double ymin = v[0].y();
00449     v[0].z() = 0;
00450     for( int i=1; i<n; ++i ) {
00451         double x = v[i].x();
00452         double y = v[i].y();
00453         v[i].z() = 0;
00454         if ( y > ymin )
00455             continue;
00456         if ( y == ymin ) {
00457             if (x  < xmin )
00458                 continue;
00459         }
00460         rmin = i;
00461         xmin = x;
00462         ymin = y;
00463     }
00464 
00465     int rmin_less_1 = rmin-1 >= 0 ? rmin-1 : n-1;
00466     int rmin_plus_1 = rmin+1 < n ? rmin+1 : 0;
00467 
00468     osg::Vec3 in = v[rmin] - v[rmin_less_1]; in.normalize();
00469     osg::Vec3 out = v[rmin_plus_1] - v[rmin]; out.normalize();
00470     osg::Vec3 cross = in ^ out;
00471 
00472     return
00473         cross.z() < 0.0 ? Ring::ORIENTATION_CW :
00474         cross.z() > 0.0 ? Ring::ORIENTATION_CCW :
00475         Ring::ORIENTATION_DEGENERATE;
00476 }
00477 
00478 // ensures that the first and last points are not idential.
00479 void 
00480 Ring::open()
00481 {            
00482     while( size() > 2 && front() == back() )
00483         erase( end()-1 );
00484 }
00485 
00486 // gets the signed area.
00487 double
00488 Ring::getSignedArea2D() const
00489 {
00490     const_cast<Ring*>(this)->open();
00491 
00492     double sum = 0.0;
00493 
00494     for( unsigned i=0; i<size(); ++i )
00495     {
00496         const osg::Vec3d& p0 = (*this)[0];
00497         const osg::Vec3d& p1 = i+1 < size() ? (*this)[i+1] : (*this)[0];
00498         sum += p0.x()*p1.y() - p1.x()*p0.y();
00499     }
00500     return .5*sum;
00501 }
00502 
00503 // opens and rewinds the polygon to the specified orientation.
00504 void 
00505 Ring::rewind( Orientation orientation )
00506 {
00507     open();
00508     Orientation current = getOrientation();
00509     if ( current != orientation && current != ORIENTATION_DEGENERATE && orientation != ORIENTATION_DEGENERATE )
00510     {
00511         std::reverse( begin(), end() );
00512     }
00513 }
00514 
00515 // point-in-polygon test
00516 bool
00517 Ring::contains2D( double x, double y ) const
00518 {
00519     bool result = false;
00520     const Ring& poly = *this;
00521     for( unsigned i=0, j=size()-1; i<size(); j = i++ )
00522     {
00523         if ((((poly[i].y() <= y) && (y < poly[j].y())) ||
00524             ((poly[j].y() <= y) && (y < poly[i].y()))) &&
00525             (x < (poly[j].x()-poly[i].x()) * (y-poly[i].y())/(poly[j].y()-poly[i].y())+poly[i].x()))
00526         {
00527             result = !result;
00528         }
00529     }
00530     return result;
00531 }
00532 
00533 //----------------------------------------------------------------------------
00534 
00535 Polygon::Polygon( const Polygon& rhs ) :
00536 Ring( rhs )
00537 {
00538     for( RingCollection::const_iterator r = rhs._holes.begin(); r != rhs._holes.end(); ++r )
00539         _holes.push_back( new Ring(*r->get()) );
00540 }
00541 
00542 Polygon::Polygon( const Vec3dVector* data ) :
00543 Ring( data )
00544 {
00545     //nop
00546 }
00547 
00548 int
00549 Polygon::getTotalPointCount() const
00550 {
00551     int total = Ring::getTotalPointCount();
00552     for( RingCollection::const_iterator i = _holes.begin(); i != _holes.end(); ++i )
00553         total += i->get()->getTotalPointCount();
00554     return total;
00555 }
00556 
00557 bool
00558 Polygon::contains2D( double x, double y ) const
00559 {
00560     // first check the outer ring
00561     if ( !Ring::contains2D(x, y) )
00562         return false;
00563 
00564     // then check each inner ring (holes). Point has to be inside the outer ring, 
00565     // but NOT inside any of the holes
00566     for( RingCollection::const_iterator i = _holes.begin(); i != _holes.end(); ++i )
00567     {
00568         if ( i->get()->contains2D(x, y) )
00569             return false;
00570     }
00571 
00572     return true;
00573 }
00574 
00575 void
00576 Polygon::open() 
00577 {
00578     Ring::open();
00579     for( RingCollection::const_iterator i = _holes.begin(); i != _holes.end(); ++i )
00580         (*i)->open();
00581 }
00582 
00583 //----------------------------------------------------------------------------
00584 
00585 MultiGeometry::MultiGeometry( const MultiGeometry& rhs ) :
00586 Geometry( rhs )
00587 {
00588     for( GeometryCollection::const_iterator i = rhs._parts.begin(); i != rhs._parts.end(); ++i )
00589         _parts.push_back( i->get()->clone() ); //i->clone() ); //osg::clone<Geometry>( i->get() ) );
00590 }
00591 
00592 MultiGeometry::MultiGeometry( const GeometryCollection& parts ) :
00593 _parts( parts )
00594 {
00595     //nop
00596 }
00597 
00598 Geometry::Type
00599 MultiGeometry::getComponentType() const
00600 {
00601     // dicey.
00602     return _parts.size() > 0 ? _parts.front()->getType() : TYPE_UNKNOWN;
00603 }
00604 
00605 int
00606 MultiGeometry::getTotalPointCount() const
00607 {
00608     int total = 0;
00609     for( GeometryCollection::const_iterator i = _parts.begin(); i != _parts.end(); ++i )
00610         total += i->get()->getTotalPointCount();
00611     return total;
00612 }
00613 
00614 unsigned
00615 MultiGeometry::getNumGeometries() const
00616 {
00617     unsigned total = 0;
00618     for( GeometryCollection::const_iterator i = _parts.begin(); i != _parts.end(); ++i )
00619         total += i->get()->getNumGeometries();
00620     return total;
00621 }
00622 
00623 Bounds
00624 MultiGeometry::getBounds() const
00625 {
00626     Bounds bounds;
00627     for( GeometryCollection::const_iterator i = _parts.begin(); i != _parts.end(); ++i )
00628     {
00629         bounds.expandBy( i->get()->getBounds() );
00630     }
00631     return bounds;
00632 }
00633 
00634 Geometry*
00635 MultiGeometry::cloneAs( const Geometry::Type& newType ) const
00636 {
00637     MultiGeometry* multi = new MultiGeometry();
00638     for( GeometryCollection::const_iterator i = _parts.begin(); i != _parts.end(); ++i )
00639     {
00640         Geometry* part = i->get()->cloneAs( i->get()->getType() );
00641         if ( part ) multi->getComponents().push_back( part );
00642     }
00643     return multi;
00644 }
00645 
00646 bool
00647 MultiGeometry::isValid() const
00648 {
00649     if ( _parts.size() == 0 )
00650         return false;
00651 
00652     bool valid = true;
00653     for( GeometryCollection::const_iterator i = _parts.begin(); i != _parts.end() && valid; ++i )
00654     {
00655         if ( !i->get()->isValid() )
00656             valid = false;
00657     }
00658     return valid;
00659 }
00660 
00661 //----------------------------------------------------------------------------
00662 
00663 GeometryIterator::GeometryIterator( Geometry* geom, bool holes ) :
00664 _next( 0L ),
00665 _traverseMulti( true ),
00666 _traversePolyHoles( holes )
00667 {
00668     if ( geom )
00669     {
00670         _stack.push( geom );
00671         fetchNext();
00672     }
00673 }
00674 
00675 bool
00676 GeometryIterator::hasMore() const
00677 {
00678     return _next != 0L;
00679 }
00680 
00681 Geometry*
00682 GeometryIterator::next()
00683 {
00684     Geometry* n = _next;
00685     fetchNext();
00686     return n;
00687 }
00688 
00689 void
00690 GeometryIterator::fetchNext()
00691 {
00692     _next = 0L;
00693     if ( _stack.size() == 0 )
00694         return;
00695 
00696     Geometry* current = _stack.top();
00697     _stack.pop();
00698 
00699     if ( current->getType() == Geometry::TYPE_MULTI && _traverseMulti )
00700     {
00701         MultiGeometry* m = static_cast<MultiGeometry*>(current);
00702         for( GeometryCollection::const_iterator i = m->getComponents().begin(); i != m->getComponents().end(); ++i )
00703             _stack.push( i->get() );
00704         fetchNext();
00705     }
00706     else if ( current->getType() == Geometry::TYPE_POLYGON && _traversePolyHoles )
00707     {
00708         Polygon* p = static_cast<Polygon*>(current);
00709         for( RingCollection::const_iterator i = p->getHoles().begin(); i != p->getHoles().end(); ++i )
00710             _stack.push( i->get() );
00711         _next = current;
00712     }
00713     else
00714     {
00715         _next = current;
00716     }    
00717 }
00718 
00719 //----------------------------------------------------------------------------
00720 
00721 ConstGeometryIterator::ConstGeometryIterator( const Geometry* geom, bool holes ) :
00722 _next( 0L ),
00723 _traverseMulti( true ),
00724 _traversePolyHoles( holes )
00725 {
00726     if ( geom )
00727     {
00728         _stack.push( geom );
00729         fetchNext();
00730     }
00731 }
00732 
00733 bool
00734 ConstGeometryIterator::hasMore() const
00735 {
00736     return _next != 0L;
00737 }
00738 
00739 const Geometry*
00740 ConstGeometryIterator::next()
00741 {
00742     const Geometry* n = _next;
00743     fetchNext();
00744     return n;
00745 }
00746 
00747 void
00748 ConstGeometryIterator::fetchNext()
00749 {
00750     _next = 0L;
00751     if ( _stack.size() == 0 )
00752         return;
00753 
00754     const Geometry* current = _stack.top();
00755     _stack.pop();
00756 
00757     if ( current->getType() == Geometry::TYPE_MULTI && _traverseMulti )
00758     {
00759         const MultiGeometry* m = static_cast<const MultiGeometry*>(current);
00760         for( GeometryCollection::const_iterator i = m->getComponents().begin(); i != m->getComponents().end(); ++i )
00761             _stack.push( i->get() );
00762         fetchNext();
00763     }
00764     else if ( current->getType() == Geometry::TYPE_POLYGON && _traversePolyHoles )
00765     {
00766         const Polygon* p = static_cast<const Polygon*>(current);
00767         for( RingCollection::const_iterator i = p->getHoles().begin(); i != p->getHoles().end(); ++i )
00768             _stack.push( i->get() );
00769         _next = current;
00770     }
00771     else
00772     {
00773         _next = current;
00774     }    
00775 }
00776 
00777 //----------------------------------------------------------------------------
00778 
00779 ConstSegmentIterator::ConstSegmentIterator( const Geometry* verts, bool closeLoop ) :
00780 _verts(&verts->asVector()),
00781 _closeLoop(closeLoop),
00782 _iter(verts->begin())
00783 {
00784     _done = _verts->size() < 2;
00785 }
00786 
00787 Segment
00788 ConstSegmentIterator::next()
00789 {
00790     osg::Vec3d p0 = *_iter++;
00791     if ( _iter == _verts->end() ) 
00792     {
00793         _iter = _verts->begin();
00794         _done = true;
00795     }
00796     else if ( _iter+1 == _verts->end() && !_closeLoop )
00797     {
00798         _done = true;
00799     }
00800 
00801     return Segment( p0, *_iter );
00802 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines