osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthFeatures/AltitudeFilter.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/AltitudeFilter>
00020 #include <osgEarth/ElevationQuery>
00021 #include <osgEarth/GeoData>
00022 
00023 #define LC "[AltitudeFilter] "
00024 
00025 using namespace osgEarth;
00026 using namespace osgEarth::Features;
00027 using namespace osgEarth::Symbology;
00028 
00029 //---------------------------------------------------------------------------
00030 
00031 AltitudeFilter::AltitudeFilter() :
00032 _maxRes ( 0.0f )
00033 {
00034     //NOP
00035 }
00036 
00037 void
00038 AltitudeFilter::setPropertiesFromStyle( const Style& style )
00039 {
00040     _altitude = style.get<AltitudeSymbol>();
00041     if ( _altitude )
00042     {
00043         setMaxResolution( *_altitude->clampingResolution() );
00044     }
00045 }
00046 
00047 FilterContext
00048 AltitudeFilter::push( FeatureList& features, FilterContext& cx )
00049 {
00050     const Session* session = cx.getSession();
00051     if ( !session ) {
00052         OE_WARN << LC << "No session - session is required for elevation clamping" << std::endl;
00053         return cx;
00054     }
00055 
00056     // the map against which we'll be doing elevation clamping
00057     MapFrame mapf = session->createMapFrame( Map::ELEVATION_LAYERS );
00058 
00059     const SpatialReference* mapSRS     = mapf.getProfile()->getSRS();
00060     const SpatialReference* featureSRS = cx.profile()->getSRS();
00061 
00062     // establish an elevation query interface based on the features' SRS.
00063     ElevationQuery eq( mapf );
00064 
00065     NumericExpression scaleExpr;
00066     if ( _altitude.valid() && _altitude->verticalScale().isSet() )
00067         scaleExpr = *_altitude->verticalScale();
00068 
00069     NumericExpression offsetExpr;
00070     if ( _altitude.valid() && _altitude->verticalOffset().isSet() )
00071         offsetExpr = *_altitude->verticalOffset();
00072 
00073     bool clamp =
00074         _altitude->clamping() != AltitudeSymbol::CLAMP_NONE;
00075 
00076     // whether to record a "minimum terrain" value
00077     bool collectHATs =
00078         _altitude->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN ||
00079         _altitude->clamping() == AltitudeSymbol::CLAMP_ABSOLUTE;
00080 
00081     for( FeatureList::iterator i = features.begin(); i != features.end(); ++i )
00082     {
00083         Feature* feature = i->get();
00084         double maxGeomZ     = -DBL_MAX;
00085         double minGeomZ     =  DBL_MAX;
00086         double maxTerrainZ  = -DBL_MAX;
00087         double minTerrainZ  =  DBL_MAX;
00088         double minHAT       =  DBL_MAX;
00089         double maxHAT       = -DBL_MAX;
00090 
00091         double scaleZ = 1.0;
00092         if ( _altitude.valid() && _altitude->verticalScale().isSet() )
00093             scaleZ = feature->eval( scaleExpr );
00094 
00095         double offsetZ = 0.0;
00096         if ( _altitude.valid() && _altitude->verticalOffset().isSet() )
00097             offsetZ = feature->eval( offsetExpr );
00098         
00099         GeometryIterator gi( feature->getGeometry() );
00100         while( gi.hasMore() )
00101         {
00102             Geometry* geom = gi.next();
00103 
00104             // clamps the entire array to the terrain using the specified resolution.
00105             if ( clamp )
00106             {
00107                 if ( collectHATs )
00108                 {
00109                     std::vector<double> elevations;
00110                     elevations.reserve( geom->size() );
00111                     eq.getElevations( geom->asVector(), featureSRS, elevations, _maxRes );
00112                     for( unsigned i=0; i<geom->size(); ++i )
00113                     {
00114                         double z = (*geom)[i].z() * scaleZ + offsetZ;
00115                         double hat =
00116                             _altitude->clamping() == AltitudeSymbol::CLAMP_ABSOLUTE ? z - elevations[i] :
00117                             z;
00118 
00119                         if ( hat > maxHAT )
00120                             maxHAT = hat;
00121                         if ( hat < minHAT )
00122                             minHAT = hat;
00123 
00124                         double elev = elevations[i];
00125                         if ( elev > maxTerrainZ )
00126                             maxTerrainZ = elev;
00127                         if ( elev < minTerrainZ )
00128                             minTerrainZ = elev;
00129 
00130                         (*geom)[i].z() =
00131                             _altitude->clamping() == AltitudeSymbol::CLAMP_ABSOLUTE ? z :
00132                             z + elevations[i];
00133                     }
00134                 }
00135                 else
00136                 {
00137                     eq.getElevations( geom->asVector(), featureSRS, true, _maxRes );
00138                 }
00139             }
00140 
00141             for( Geometry::iterator i = geom->begin(); i != geom->end(); ++i )
00142             {
00143                 if ( !collectHATs )
00144                 {
00145                     i->z() *= scaleZ;
00146                     i->z() += offsetZ;
00147                 }
00148 
00149                 if ( i->z() > maxGeomZ )
00150                     maxGeomZ = i->z();
00151                 if ( i->z() < minGeomZ )
00152                     minGeomZ = i->z();
00153             }
00154         }
00155 
00156         if ( minHAT != DBL_MAX )
00157         {
00158             feature->set( "__min_hat", minHAT );
00159             feature->set( "__max_hat", maxHAT );
00160         }
00161 
00162         if ( minGeomZ != DBL_MAX )
00163         {
00164             feature->set( "__min_geom_z", minGeomZ );
00165             feature->set( "__max_geom_z", maxGeomZ );
00166         }
00167 
00168         if ( minTerrainZ != DBL_MAX )
00169         {
00170             feature->set( "__min_terrain_z", minTerrainZ );
00171             feature->set( "__max_terrain_z", maxTerrainZ );
00172         }
00173     }
00174 
00175     return cx;
00176 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines