osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/VerticalSpatialReference.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 
00020 #include <osgEarth/VerticalSpatialReference>
00021 #include <osgEarth/EGM>
00022 #include <osgEarth/StringUtils>
00023 #include <osgEarth/GeoData>
00024 
00025 using namespace osgEarth;
00026 
00027 #define LC "[VSRS] "
00028 
00029 // --------------------------------------------------------------------------
00030 
00031 //TODO: replace this with some kind of registry.
00032 VerticalSpatialReference*
00033 VerticalSpatialReference::create( const std::string& initString )
00034 {
00035     static OpenThreads::Mutex s_mutex;
00036     OpenThreads::ScopedLock<OpenThreads::Mutex> exclusiveLock(s_mutex);
00037 
00038     if ( !_geoidRegistry )
00039     {
00040         // initialize the registry the first time through.
00041         registerGeoid( new EGM96Geoid() );
00042     }
00043 
00044     std::string s = toLower( initString );
00045 
00046     GeoidRegistry::const_iterator i = (*_geoidRegistry).find( s );
00047     if ( i != (*_geoidRegistry).end() )
00048     {
00049         const Geoid* geoid = i->second.get();
00050         return new VerticalSpatialReference( geoid->getName(), initString, geoid );
00051     }
00052     else if ( s == "meters" || s == "metres" || s == "meter" || s == "metre" )
00053         return new VerticalSpatialReference( Units::METERS );
00054     else if ( startsWith( s, "feet" ) || startsWith( s, "foot" ) )
00055         return new VerticalSpatialReference( Units::FEET );
00056 
00057     return 0L;
00058 }
00059 
00060 void
00061 VerticalSpatialReference::registerGeoid( const Geoid* geoid )
00062 {
00063     if ( !_geoidRegistry )
00064         _geoidRegistry = new GeoidRegistry();
00065 
00066     if ( geoid )
00067         (*_geoidRegistry)[geoid->getName()] = geoid;
00068 }
00069 
00070 VerticalSpatialReference::GeoidRegistry*
00071 VerticalSpatialReference::_geoidRegistry = 0L;
00072 
00073 // --------------------------------------------------------------------------
00074 
00075 VerticalSpatialReference::VerticalSpatialReference(const std::string& name,
00076                                                    const std::string& initString,
00077                                                    const Geoid* geoid ) :
00078 _name( name ),
00079 _initString( initString ),
00080 _geoid( geoid ),
00081 _units( Units::METERS )
00082 {
00083     if ( _geoid.valid() )
00084         _units = _geoid->getUnits();
00085 }
00086 
00087 VerticalSpatialReference::VerticalSpatialReference( const Units& units ) :
00088 _name( units.getName() ),
00089 _initString( units.getName() ),
00090 _units( units )
00091 {
00092     //nop
00093 }
00094 
00095 bool
00096 VerticalSpatialReference::canTransform( const VerticalSpatialReference* toVSRS ) const
00097 {
00098     return toVSRS && !isEquivalentTo( toVSRS );
00099 }
00100 
00101 bool
00102 VerticalSpatialReference::canTransform(const VerticalSpatialReference* fromVSRS,
00103                                        const VerticalSpatialReference* toVSRS )
00104 {
00105     return fromVSRS && fromVSRS->canTransform( toVSRS );
00106 }
00107 
00108 bool 
00109 VerticalSpatialReference::transform(const VerticalSpatialReference* toSRS, 
00110                                     double lat_deg, double lon_deg, double in_z,
00111                                     double& out_z ) const
00112 {    
00113     if ( this->isEquivalentTo( toSRS ) )
00114     {
00115         out_z = in_z;
00116     }
00117     else
00118     {
00119         double workZ = in_z;
00120 
00121         // transform out of the source VSRS (this):
00122         if ( _geoid.valid() )
00123         {
00124             if ( !_geoid->isValid() )
00125                 return false;
00126 
00127             float offset = _geoid->getOffset( lat_deg, lon_deg, INTERP_BILINEAR );
00128             workZ -= offset;
00129         }
00130 
00131         // convert the value to output units:
00132         Units::convert( getUnits(), toSRS->getUnits(), workZ, workZ );
00133 
00134         // transform into the target VSRS:
00135         if ( toSRS->_geoid.valid() )
00136         {
00137             if ( !toSRS->_geoid->isValid() )
00138                 return false;
00139         
00140             float offset = toSRS->_geoid->getOffset( lat_deg, lon_deg, INTERP_BILINEAR );
00141             workZ += offset;
00142         }
00143 
00144         out_z = workZ;
00145     }
00146 
00147     return true;
00148 }
00149 
00150 osg::HeightField*
00151 VerticalSpatialReference::createReferenceHeightField( const GeoExtent& ex, int numCols, int numRows ) const
00152 {
00153     osg::HeightField* hf = new osg::HeightField();
00154     hf->allocate( numCols, numRows );
00155     hf->setOrigin( osg::Vec3d( ex.xMin(), ex.yMin(), 0.0 ) );
00156     hf->setXInterval( (ex.xMax() - ex.xMin())/(double)(numCols-1) );
00157     hf->setYInterval( (ex.yMax() - ex.yMin())/(double)(numRows-1) );
00158 
00159     if ( _geoid.valid() && _geoid->isValid() )
00160     {
00161         // need the lat/long extent for geoid queries:
00162         GeoExtent geodeticExtent = ex.getSRS()->isGeographic() ? ex : ex.transform( ex.getSRS()->getGeographicSRS() );
00163         double latMin = geodeticExtent.yMin();
00164         double lonMin = geodeticExtent.xMin();
00165         double lonInterval = geodeticExtent.width() / (double)(numCols-1);
00166         double latInterval = geodeticExtent.height() / (double)(numRows-1);
00167 
00168         for( int r=0; r<numRows; ++r )
00169         {            
00170             double lat = latMin + latInterval*(double)r;
00171             for( int c=0; c<numCols; ++c )
00172             {
00173                 double lon = lonMin + lonInterval*(double)c;
00174                 double offset = _geoid->getOffset( lat, lon );
00175                 hf->setHeight( c, r, offset );
00176             }
00177         }
00178     }
00179     else
00180     {
00181         for(unsigned int i=0; i<hf->getHeightList().size(); i++ )
00182             hf->getHeightList()[i] = 0.0;
00183     }
00184 
00185     hf->setBorderWidth( 0 );
00186     return hf;    
00187 }
00188 
00189 bool 
00190 VerticalSpatialReference::isEquivalentTo( const VerticalSpatialReference* rhs ) const
00191 {
00192     if ( this == rhs )
00193         return true;
00194 
00195     if ( _units != rhs->_units )
00196         return false;
00197 
00198     if ( _geoid.valid() != rhs->_geoid.valid() )
00199         return false;
00200     
00201     if ( _geoid.valid() && !_geoid->isEquivalentTo( *rhs->_geoid.get() ) )
00202         return false;
00203 
00204     //TODO - add comparisons as necessary
00205 
00206     return true;
00207 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines