osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthFeatures/FeatureGridder.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 <osgEarthFeatures/FeatureGridder>
00020 #include <osgEarthSymbology/Geometry>
00021 #include <osg/Notify>
00022 #include <osg/Timer>
00023 
00024 #define LC "[FeatureGridder] "
00025 
00026 using namespace osgEarth;
00027 using namespace osgEarth::Features;
00028 
00029 /**************************************************************************/
00030 
00031 #define PROP_CELL_SIZE         "cell_size"
00032 #define PROP_CULLING_TECHNIQUE "culling_technique"
00033 #define PROP_SPATIALIZE_GROUPS "spatialize_groups"
00034 #define PROP_CLUSTER_CULLING   "cluster_culling"
00035 
00036 GriddingPolicy::GriddingPolicy( const Config& conf ) :
00037 _cellSize( DBL_MAX ),
00038 _cullingTechnique( GriddingPolicy::CULL_BY_CENTROID ),
00039 _spatializeGroups( true ),
00040 _clusterCulling( false )
00041 {
00042     fromConfig( conf );
00043 }
00044 
00045 Config
00046 GriddingPolicy::getConfig() const 
00047 {
00048     Config conf;
00049 
00050     conf.updateIfSet( PROP_CELL_SIZE, _cellSize );
00051 
00052     if ( _cullingTechnique.isSet() ) {
00053         if ( _cullingTechnique == CULL_BY_CROPPING )
00054             conf.update( PROP_CULLING_TECHNIQUE, "crop" );
00055         else if ( _cullingTechnique == CULL_BY_CENTROID )
00056             conf.update( PROP_CULLING_TECHNIQUE, "centroid" );
00057     }
00058 
00059     conf.updateIfSet( PROP_SPATIALIZE_GROUPS, _spatializeGroups );
00060     conf.updateIfSet( PROP_CLUSTER_CULLING, _clusterCulling );
00061 
00062     return conf;        
00063 }
00064 
00065 void
00066 GriddingPolicy::fromConfig( const Config& conf )
00067 {
00068     conf.getIfSet( PROP_CELL_SIZE, _cellSize );
00069 
00070     // read the culling technique
00071     if ( conf.hasValue( PROP_CULLING_TECHNIQUE ) ) {
00072         if ( conf.value( PROP_CULLING_TECHNIQUE ) == "crop" )
00073             _cullingTechnique = CULL_BY_CROPPING;
00074         else if ( conf.value( PROP_CULLING_TECHNIQUE ) == "centroid" )
00075             _cullingTechnique = CULL_BY_CENTROID;
00076     }
00077 
00078     // spatial optimization
00079     conf.getIfSet<bool>( PROP_SPATIALIZE_GROUPS, _spatializeGroups );
00080 
00081     // cluster culling
00082     conf.getIfSet<bool>( PROP_CLUSTER_CULLING, _clusterCulling );
00083 }
00084 
00085 /***************************************************************************/
00086 
00087 FeatureGridder::FeatureGridder(const Bounds& inputBounds,
00088                                const GriddingPolicy& policy ) :
00089 _inputBounds( inputBounds ),
00090 _policy( policy )
00091 {
00092     if ( _policy.enabled() ) //_policy.cellSize().isSet() && *_policy.cellSize() > 0.0 )
00093     {
00094         _cellsX = (int)::ceil(_inputBounds.width() / *_policy.cellSize() );
00095         _cellsY = (int)::ceil(_inputBounds.height() / *_policy.cellSize() );
00096     }
00097     else
00098     {
00099         _cellsX = 1;
00100         _cellsY = 1;
00101     }
00102 
00103     _cellsX = osg::clampAbove( _cellsX, 1 );
00104     _cellsY = osg::clampAbove( _cellsY, 1 );
00105 
00106 #ifndef OSGEARTH_HAVE_GEOS
00107 
00108     if ( _policy.cullingTechnique().isSetTo( GriddingPolicy::CULL_BY_CROPPING ) )
00109     {
00110         OE_WARN 
00111             << "Warning: Gridding policy 'cull by cropping' requires GEOS. Falling back on 'cull by centroid'." 
00112             << std::endl;
00113 
00114         _policy.cullingTechnique() = GriddingPolicy::CULL_BY_CENTROID;
00115     }
00116 
00117 #endif // !OSGEARTH_HAVE_GEOS
00118 }
00119 
00120 FeatureGridder::~FeatureGridder()
00121 {
00122     //nop
00123 }
00124 
00125 int
00126 FeatureGridder::getNumCells() const
00127 {
00128     return _cellsX * _cellsY;
00129 }
00130 
00131 bool
00132 FeatureGridder::getCellBounds( int i, Bounds& output ) const
00133 {
00134     if ( i >= 0 && i < (_cellsX*_cellsY) )
00135     {
00136         int x = i % _cellsX;
00137         int y = i / _cellsX;
00138 
00139         double xmin = _inputBounds.xMin() + _policy.cellSize().value()  * (double)x;
00140         double ymin = _inputBounds.yMin() + _policy.cellSize().value() * (double)y;
00141         double xmax = osg::clampBelow( _inputBounds.xMin() + *_policy.cellSize() * (double)(x+1), _inputBounds.xMax() );
00142         double ymax = osg::clampBelow( _inputBounds.yMin() + *_policy.cellSize() * (double)(y+1), _inputBounds.yMax() );
00143 
00144         output = Bounds( xmin, ymin, xmax, ymax );
00145         return true;
00146     }
00147     return false;
00148 }
00149 
00150 bool
00151 FeatureGridder::cullFeatureListToCell( int i, FeatureList& features ) const
00152 {
00153     bool success = true;
00154     int inCount = features.size();
00155 
00156     Bounds b;
00157     if ( getCellBounds( i, b ) )
00158     {
00159         if ( _policy.cullingTechnique() == GriddingPolicy::CULL_BY_CENTROID )
00160         {
00161             for( FeatureList::iterator f_i = features.begin(); f_i != features.end();  )
00162             {
00163                 bool keepFeature = false;
00164 
00165                 Feature* feature = f_i->get();
00166                 Symbology::Geometry* featureGeom = feature->getGeometry();
00167                 if ( featureGeom )
00168                 {
00169                     osg::Vec3d centroid = featureGeom->getBounds().center();
00170                     if ( b.contains( centroid.x(), centroid.y() ) )
00171                     {
00172                         keepFeature = true;
00173                     }
00174                 }
00175 
00176                 if ( keepFeature )
00177                     ++f_i;
00178                 else
00179                     f_i = features.erase( f_i );
00180             }
00181         }
00182 
00183         else // CULL_BY_CROPPING (requires GEOS)
00184         {
00185 
00186 #ifdef OSGEARTH_HAVE_GEOS
00187 
00188             // create the intersection polygon:
00189             osg::ref_ptr<Symbology::Polygon> poly = new Symbology::Polygon( 4 );
00190             poly->push_back( osg::Vec3d( b.xMin(), b.yMin(), 0 ));
00191             poly->push_back( osg::Vec3d( b.xMax(), b.yMin(), 0 ));
00192             poly->push_back( osg::Vec3d( b.xMax(), b.yMax(), 0 ));
00193             poly->push_back( osg::Vec3d( b.xMin(), b.yMax(), 0 ));
00194 
00195             for( FeatureList::iterator f_i = features.begin(); f_i != features.end();  )
00196             {
00197                 bool keepFeature = false;
00198 
00199                 Feature* feature = f_i->get();
00200                 Symbology::Geometry* featureGeom = feature->getGeometry();
00201                 if ( featureGeom )
00202                 {
00203                     osg::ref_ptr<Symbology::Geometry> croppedGeometry;
00204                     if ( featureGeom->crop( poly.get(), croppedGeometry ) )
00205                     {
00206                         feature->setGeometry( croppedGeometry.get() );
00207                         keepFeature = true;
00208                     }                   
00209                 }
00210 
00211                 if ( keepFeature )
00212                     ++f_i;
00213                 else
00214                     f_i = features.erase( f_i );
00215             }  
00216 
00217 #endif // OSGEARTH_HAVE_GEOS
00218 
00219         }
00220 
00221     }
00222 
00223     OE_INFO << LC
00224             << "Grid cell " << i << ": bounds="
00225             << b.xMin() << "," << b.yMin() << " => " << b.xMax() << "," << b.yMax()
00226             << "; in=" << inCount << "; out=" << features.size()
00227             << std::endl;
00228 
00229     return success;
00230 }
00231 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines