osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/Cube.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/Cube>
00021 #include <osg/Math>
00022 #include <osg/Notify>
00023 #include <sstream>
00024 #include <algorithm>
00025 
00026 using namespace osgEarth;
00027 
00028 #define LC "[Cube] "
00029 
00030 // --------------------------------------------------------------------------
00031 
00032 bool
00033 CubeUtils::latLonToFaceCoords(double lat_deg, double lon_deg,
00034                               double& out_x, double& out_y, int& out_face,
00035                               int faceHint )
00036 {
00037     // normalized latitude and longitude
00038     double nlat = (lat_deg+90.0)/180.0;
00039     double nlon = (lon_deg+180.0)/360.0;
00040 
00041     // check for out-of-range:
00042     if ( nlat < 0 || nlat > 1 || nlon < 0 || nlon > 1 )
00043         return false;
00044 
00045     int face_x;
00046 
00047     if ( faceHint >= 0 )
00048     {
00049         out_face = faceHint;
00050         if ( faceHint < 4 )
00051         {
00052             face_x = faceHint;
00053         }
00054         else
00055         {
00056             face_x = (int)(4 * nlon);
00057             if ( face_x == 4 ) 
00058                 face_x = 3;
00059         }        
00060     }
00061     else
00062     {
00063         face_x = (int)(4 * nlon);
00064         if ( face_x == 4 )
00065             face_x = 3;
00066 
00067         int face_y = (int)(2 * nlat + 0.5);
00068         if ( face_y == 1 )
00069             out_face = face_x;
00070         else
00071             out_face = face_y < 1 ? 5 : 4;
00072 
00073         //GW: not sure why this was here; but I think this issue is the cause of cracks when
00074         //    projecting CUBE source imagery onto a WGS84 globe.
00075         //
00076         //if ( osg::equivalent( lat_deg, -45 ) )
00077         //    out_face = 5;
00078     }
00079 
00080     out_x = 4 * nlon - face_x;
00081     out_y = 2 * nlat - 0.5;
00082 
00083     if(out_face < 4) // equatorial calculations done
00084         return true;
00085 
00086     double tmp;
00087     if(out_face == 4) // north polar face
00088     {
00089         out_y = 1.5 - out_y;
00090         out_x = 2 * (out_x - 0.5) * out_y + 0.5;
00091         switch(face_x)
00092         {
00093         case 0: // bottom
00094             out_y = 0.5 - out_y;
00095             break;
00096         case 1: // right side, swap and reverse lat
00097             tmp = out_x;
00098             out_x = 0.5 + out_y;
00099             out_y = tmp;
00100             break;
00101         case 2: // top; reverse lat and lon
00102             out_x = 1 - out_x;
00103             out_y = 0.5 + out_y;
00104             break;
00105         case 3: // left side; swap and reverse lon
00106             tmp = out_x;
00107             out_x = 0.5 - out_y;
00108             out_y = 1 - tmp;
00109             break;
00110         }
00111     }
00112     else // south polar face
00113     {
00114         out_y += 0.5;
00115         out_x = 2 * (out_x - 0.5) * out_y + 0.5;
00116         switch(face_x)
00117         {
00118         case 0: // left
00119             tmp = out_x;
00120             out_x = 0.5 - out_y;
00121             out_y = tmp;
00122             break;
00123         case 1: // top
00124             out_y = 0.5 + out_y;
00125             break;
00126         case 2: // right
00127             tmp = out_x;
00128             out_x = 0.5 + out_y;
00129             out_y = 1 - tmp;
00130             break;
00131         case 3: // bottom
00132             out_x = 1 - out_x;
00133             out_y = 0.5 - out_y;
00134             break;
00135         }
00136     }
00137     return true;
00138 }
00139 
00140 bool
00141 CubeUtils::faceCoordsToLatLon( double x, double y, int face, double& out_lat_deg, double& out_lon_deg )
00142 {
00143     double offset = 0.0;
00144     osg::Vec2d s( x, y );
00145 
00146     // validate coordinate range:
00147     if ( x < 0 || x > 1 || y < 0 || y > 1 )
00148     {
00149         OE_WARN << LC << "faceCoordToLatLon: input out of range" << std::endl;
00150         return false;
00151     }
00152 
00153     if ( face < 4 ) // equatorial faces
00154     {
00155         s.x() = (x + face) * 0.25;
00156         s.y() = (y + 0.5) * 0.5;
00157     }
00158     else if( face == 4 ) // north polar face
00159     {
00160         if ( x < y ) // left or top quadrant
00161         {
00162             if(x + y < 1.0) // left quadrant
00163             {
00164                 s.x() = 1.0 - y;
00165                 s.y() = x;
00166                 offset += 3;
00167             }
00168             else // top quadrant
00169             {
00170                 s.y() = 1.0 - y;
00171                 s.x() = 1.0 - x;
00172                 offset += 2;
00173             }
00174         }
00175         else if( x + y >= 1.0 ) // right quadrant
00176         {
00177             s.x() = y;
00178             s.y() = 1.0 - x;
00179             offset += 1.0;
00180         }
00181         s.x() -= s.y();
00182         if(s.y() != 0.5)
00183             s.x() *= 0.5 / (0.5 - s.y());
00184 
00185         s.x() = (s.x() + offset) * 0.25;
00186         s.y() = (s.y() + 1.5) * 0.5;
00187     }
00188     else if ( face == 5 ) // south polar face
00189     {
00190         offset = 1.0;
00191         if ( x > y ) // right or bottom quadrant
00192         {
00193             if( x + y >= 1.0) // right quadrant
00194             {
00195                 s.x() = 1.0 - y;
00196                 s.y() = x - 0.5;
00197                 offset += 1.0;
00198             }
00199             else // bottom quadrant
00200             {
00201                 s.x() = 1.0 - x;
00202                 s.y() = 0.5 - y;
00203                 offset += 2;
00204             }
00205         }
00206         else // left or top quadrant
00207         {
00208             if(x + y < 1.0) // left quadrant
00209             {
00210                 s.x() = y;
00211                 s.y() = 0.5 - x;
00212                 offset -= 1.0;
00213             }
00214             else // top quadrant
00215                 s.y() = y - 0.5;
00216         }
00217         if(s.y() != 0)
00218             s.x() = (s.x() - 0.5) * 0.5 / s.y() + 0.5;
00219         s.x() = (s.x() + offset) * 0.25;
00220         s.y() *= 0.5;
00221     }
00222     else 
00223     {
00224         return false; // invalid face specification
00225     }
00226 
00227     // convert to degrees
00228     out_lon_deg = s.x() * 360 - 180;
00229     out_lat_deg = s.y() * 180 - 90;
00230 
00231     return true;
00232 }
00233 
00234 bool
00235 CubeUtils::cubeToFace( double& in_out_x, double& in_out_y, int& out_face )
00236 {
00237     // convert from unicube space (0,0=>6,1) to face space (0,0=>1,1 + face#)
00238     // too tired to compute a formula right now
00239     out_face = 
00240         in_out_x <= 1.0 ? 0 :
00241         in_out_x <= 2.0 ? 1 :
00242         in_out_x <= 3.0 ? 2 :
00243         in_out_x <= 4.0 ? 3 :
00244         in_out_x <= 5.0 ? 4 : 5;
00245 
00246     in_out_x = in_out_x - (double)out_face;
00247     // y unchanged
00248     return true;
00249 }
00250 
00251 bool
00252 CubeUtils::cubeToFace(double& in_out_xmin, double& in_out_ymin,
00253                       double& in_out_xmax, double& in_out_ymax,
00254                       int& out_face)
00255 {
00256     int min_face = 
00257         in_out_xmin < 1.0 ? 0 :
00258         in_out_xmin < 2.0 ? 1 :
00259         in_out_xmin < 3.0 ? 2 :
00260         in_out_xmin < 4.0 ? 3 :
00261         in_out_xmin < 5.0 ? 4 : 5;
00262 
00263     int max_face =
00264         in_out_xmax <= 1.0 ? 0 :
00265         in_out_xmax <= 2.0 ? 1 :
00266         in_out_xmax <= 3.0 ? 2 :
00267         in_out_xmax <= 4.0 ? 3 :
00268         in_out_xmax <= 5.0 ? 4 : 5;
00269 
00270     if ( min_face != max_face )
00271     {
00272         OE_WARN << LC << "Min face <> Max face!" << std::endl;
00273         return false;
00274     }
00275 
00276     out_face = min_face;
00277 
00278     in_out_xmin -= (double)out_face;
00279     in_out_xmax -= (double)out_face;
00280 
00281     // y values are unchanged
00282     return true;
00283 }
00284 
00285 bool
00286 CubeUtils::faceToCube( double& in_out_x, double& in_out_y, int face )
00287 {
00288     // convert from face space (0,0=>1,1 + face#) to unicube space (0,0=>6,1)
00289     in_out_x = (double)face + in_out_x;
00290     // y unchanged
00291     return true;
00292 }
00293 
00294 // --------------------------------------------------------------------------
00295 
00296 CubeFaceLocator::CubeFaceLocator(unsigned int face):
00297 _face(face)
00298 {
00299     //NOP
00300 }
00301 
00302 
00303 bool
00304 CubeFaceLocator::convertLocalToModel( const osg::Vec3d& local, osg::Vec3d& world ) const
00305 {
00306 #if ((OPENSCENEGRAPH_MAJOR_VERSION <= 2) && (OPENSCENEGRAPH_MINOR_VERSION < 8))
00307     // OSG 2.7 bug workaround: bug fix in Locator submitted by GW
00308     const_cast<CubeFaceLocator*>(this)->_inverse.invert( _transform );
00309 #endif
00310 
00311     if ( _coordinateSystemType == GEOCENTRIC )
00312     {
00313         //Convert the NDC coordinate into face space
00314         osg::Vec3d faceCoord = local * _transform;
00315 
00316         double lat_deg, lon_deg;
00317         CubeUtils::faceCoordsToLatLon( faceCoord.x(), faceCoord.y(), _face, lat_deg, lon_deg );
00318 
00319         //OE_NOTICE << "LatLon=" << latLon <<  std::endl;
00320 
00321         // convert to geocentric:
00322         _ellipsoidModel->convertLatLongHeightToXYZ(
00323             osg::DegreesToRadians( lat_deg ),
00324             osg::DegreesToRadians( lon_deg ),
00325             local.z(),
00326             world.x(), world.y(), world.z() );
00327 
00328         return true;
00329     }    
00330     return true;
00331 }
00332 
00333 
00334 bool
00335 CubeFaceLocator::convertModelToLocal(const osg::Vec3d& world, osg::Vec3d& local) const
00336 {
00337 #if ((OPENSCENEGRAPH_MAJOR_VERSION <= 2) && (OPENSCENEGRAPH_MINOR_VERSION < 8))
00338     // OSG 2.7 bug workaround: bug fix in Locator submitted by GW
00339     const_cast<CubeFaceLocator*>(this)->_inverse.invert( _transform );
00340 #endif
00341 
00342     switch(_coordinateSystemType)
00343     {
00344     case(GEOCENTRIC):
00345         {         
00346             double longitude, latitude, height;
00347 
00348             _ellipsoidModel->convertXYZToLatLongHeight(world.x(), world.y(), world.z(), latitude, longitude, height );
00349 
00350             int face=-1;
00351             double x, y;
00352 
00353             double lat_deg = osg::RadiansToDegrees(latitude);
00354             double lon_deg = osg::RadiansToDegrees(longitude);
00355 
00356             bool success = CubeUtils::latLonToFaceCoords( lat_deg, lon_deg, x, y, face, _face );
00357 
00358             if (!success)
00359             {
00360                 OE_NOTICE << LC << "Couldn't convert to face coords " << std::endl;
00361             }
00362             if (face != _face)
00363             {
00364                 OE_NOTICE << LC
00365                     << "Face should be " << _face << " but is " << face
00366                     << ", lat = " << lat_deg
00367                     << ", lon = " << lon_deg
00368                     << std::endl;
00369             }
00370 
00371             local = osg::Vec3d( x, y, height ) * _inverse;
00372             return true;
00373         }
00374 
00375 
00376     case(GEOGRAPHIC):
00377     case(PROJECTED):
00378         // Neither of these is supported for this locator..
00379         {        
00380             local = world * _inverse;
00381             return true;      
00382         }
00383     }    
00384 
00385     return false;
00386 }
00387 
00388 // --------------------------------------------------------------------------
00389 
00390 CubeSpatialReference::CubeSpatialReference( void* handle ) :
00391 SpatialReference( handle, "OSGEARTH", "unified-cube", "Unified Cube" )
00392 {
00393     //nop
00394 }
00395 
00396 void
00397 CubeSpatialReference::_init()
00398 {
00399     SpatialReference::_init();
00400 
00401     _is_user_defined = true;
00402     _is_cube = true;
00403     _is_contiguous = false;
00404     _is_geographic = false;
00405     _name = "Unified Cube";
00406 }
00407 
00408 GeoLocator*
00409 CubeSpatialReference::createLocator(double xmin, double ymin, double xmax, double ymax,
00410                                     bool plate_carre) const
00411 {
00412     int face;
00413     CubeUtils::cubeToFace( xmin, ymin, xmax, ymax, face );
00414 
00415     GeoLocator* result = new CubeFaceLocator( face );
00416 
00417     osg::Matrixd transform;
00418     transform.set(
00419         xmax-xmin, 0.0,       0.0, 0.0,
00420         0.0,       ymax-ymin, 0.0, 0.0,
00421         0.0,       0.0,       1.0, 0.0,
00422         xmin,      ymin,      0.0, 1.0); 
00423     result->setTransform( transform );
00424 
00425     return result;
00426 }
00427 
00428 bool
00429 CubeSpatialReference::preTransform(double& x, double& y, double& z, void* context) const
00430 {
00431     // Convert the incoming points from cube => face => lat/long.
00432     int face;
00433     if ( !CubeUtils::cubeToFace( x, y, face ) )
00434     {
00435         OE_WARN << LC << "Failed to convert (" << x << "," << y << ") into face coordinates." << std::endl;
00436         return false;
00437     }
00438 
00439     double lat_deg, lon_deg;
00440     bool success = CubeUtils::faceCoordsToLatLon( x, y, face, lat_deg, lon_deg );
00441     if (!success)
00442     {
00443         OE_WARN << LC << "Could not transform face coordinates to lat lon" << std::endl;
00444         return false;
00445     }
00446     x = lon_deg;
00447     y = lat_deg;
00448     return true;
00449 }
00450 
00451 bool
00452 CubeSpatialReference::postTransform(double& x, double& y, double& z, void* context) const
00453 {
00454     //Convert the incoming points from lat/lon back to face coordinates
00455     int face;
00456     double out_x, out_y;
00457 
00458     // convert from lat/long to x/y/face
00459     bool success = CubeUtils::latLonToFaceCoords( y, x, out_x, out_y, face );
00460     if (!success)
00461     {
00462         OE_WARN << LC << "Could not transform face coordinates to lat lon" << std::endl;
00463         return false;
00464     }
00465 
00466     //TODO: what to do about boundary points?
00467 
00468     if ( !CubeUtils::faceToCube( out_x, out_y, face ) )
00469     {
00470         OE_WARN << LC << "fromFace(" << out_x << "," << out_y << "," << face << ") failed" << std::endl;
00471         return false;
00472     }
00473     
00474     x = out_x;
00475     y = out_y;
00476 
00477     return true;
00478 }
00479 
00480 #define LL 0
00481 #define LR 1
00482 #define UR 2
00483 #define UL 3
00484 #define SMALLEST( W,X,Y,Z ) osg::minimum(W, osg::minimum( X, osg::minimum( Y, Z ) ) )
00485 #define LARGEST( W,X,Y,Z ) osg::maximum(W, osg::maximum( X, osg::maximum( Y, Z ) ) )
00486 
00487 bool
00488 CubeSpatialReference::transformExtent(const SpatialReference* to_srs,
00489                                       double& in_out_xmin,
00490                                       double& in_out_ymin,
00491                                       double& in_out_xmax,
00492                                       double& in_out_ymax,
00493                                       void* context ) const
00494 {
00495     // note: this method only works when the extent is isolated to one face of the cube. If you
00496     // want to transform an artibrary extent, you need to break it up into separate extents for
00497     // each cube face.
00498     bool ok = true;
00499 
00500     double face_xmin = in_out_xmin, face_ymin = in_out_ymin;
00501     double face_xmax = in_out_xmax, face_ymax = in_out_ymax;
00502 
00503     int face;
00504     CubeUtils::cubeToFace( face_xmin, face_ymin, face_xmax, face_ymax, face );
00505 
00506     // for equatorial faces, the normal transformation process will suffice (since it will call into
00507     // pre/postTransform).
00508     if ( face < 4 )
00509     {
00510         ok = SpatialReference::transformExtent( to_srs, in_out_xmin, in_out_ymin, in_out_xmax, in_out_ymax );
00511     }
00512     else
00513     {
00514         // otherwise we are on one of the polar faces (4 or 5):    
00515 
00516         // four corners in face space:
00517         double fx[4] = { face_xmin, face_xmax, face_xmax, face_xmin };
00518         double fy[4] = { face_ymin, face_ymin, face_ymax, face_ymax };
00519 
00520         bool crosses_pole = fx[LL] < 0.5 && fx[UR] > 0.5 && fy[LL] < 0.5 && fy[UR] > 0.5;
00521 
00522         if ( crosses_pole ) // full x extent.
00523         {
00524             bool north = face == 4; // else south
00525             to_srs->getGeographicSRS()->transform2D( -180.0, north? 45.0 : -90.0, to_srs, in_out_xmin, in_out_ymin );
00526             to_srs->getGeographicSRS()->transform2D( 180.0, north? 90.0 : -45.0, to_srs, in_out_xmax, in_out_ymax );
00527         }
00528 
00529         else
00530         {
00531             double lat_deg[4];
00532             double lon_deg[4];
00533             double latmin, latmax, lonmin, lonmax;
00534 
00535             for( int i=0; i<4; ++i )
00536             {
00537                 CubeUtils::faceCoordsToLatLon( fx[i], fy[i], face, lat_deg[i], lon_deg[i] );
00538             }
00539 
00540             latmin = SMALLEST( lat_deg[0], lat_deg[1], lat_deg[2], lat_deg[3] );
00541             latmax = LARGEST( lat_deg[0], lat_deg[1], lat_deg[2], lat_deg[3] );
00542 
00543             // check to see whether the extent crosses the date line boundary. If so,
00544             // make the UL corner the southwest and the LR corner the east.
00545             bool crosses_date_line = fx[UL]+(1-fy[UL]) < 1.0 && (1-fx[LR])+fy[LR] < 1.0 && fx[LL]+fy[LL] < 1.0;
00546             if ( crosses_date_line )
00547             {
00548                 lonmin = lon_deg[UL];
00549                 lonmax = lon_deg[LR];
00550             }
00551             else
00552             {
00553                 lonmin = SMALLEST( lon_deg[0], lon_deg[1], lon_deg[2], lon_deg[3] );
00554                 lonmax = LARGEST( lon_deg[0], lon_deg[1], lon_deg[2], lon_deg[3] );
00555             }
00556 
00557             if ( to_srs->isGeographic() )
00558             {
00559                 in_out_xmin = lonmin;
00560                 in_out_xmax = lonmax;
00561                 in_out_ymin = latmin;
00562                 in_out_ymax = latmax;
00563             }
00564             else
00565             {
00566                 bool ok1 = transform2D( lonmin, latmin, to_srs, in_out_xmin, in_out_ymin, context );
00567                 bool ok2 = transform2D( lonmax, latmax, to_srs, in_out_xmax, in_out_ymax, context );
00568                 ok = ok1 && ok2;
00569             }
00570         }
00571     }
00572 
00573     return ok;
00574 }
00575 
00576 // --------------------------------------------------------------------------
00577 
00578 UnifiedCubeProfile::UnifiedCubeProfile() :
00579 Profile(SpatialReference::create( "unified-cube" ),
00580         0.0, 0.0, 6.0, 1.0,
00581         -180.0, -90.0, 180.0, 90.0,
00582         0L, // let it automatically create a VSRS
00583         6, 1 )
00584 
00585 {
00586     const SpatialReference* srs = getSRS()->getGeographicSRS();
00587 
00588     // set up some constant extents
00589     _faceExtent_gcs[0] = GeoExtent( srs, -180, -45, -90,  45 );
00590     _faceExtent_gcs[1] = GeoExtent( srs,  -90, -45,   0,  45 );
00591     _faceExtent_gcs[2] = GeoExtent( srs,    0, -45,  90,  45 );
00592     _faceExtent_gcs[3] = GeoExtent( srs,   90, -45, 180,  45 );
00593     _faceExtent_gcs[4] = GeoExtent( srs, -180,  45, 180,  90 ); // north polar
00594     _faceExtent_gcs[5] = GeoExtent( srs, -180, -90, 180, -45 ); // south polar
00595 }
00596 
00597 //UnifiedCubeProfile::UnifiedCubeProfile(double xmin, double ymin, double xmax, double ymax,
00598 //                                       double lonMin, double latMin, double lonMax, double latMax ) :
00599 //Profile(SpatialReference::create( "unified-cube" ),
00600 //        xmin, ymin, xmax, ymax,
00601 //        lonMin, latMin, lonMax, latMax,
00602 //        6, 1 )
00603 //{
00604 //    const SpatialReference* srs = getSRS()->getGeographicSRS();
00605 //
00606 //    // set up some faceextents
00607 //    _faceExtent_gcs[0] = GeoExtent( srs, osg::maximum(-180.,lonMin), osg::maximum(-45.,latMin), osg::minimum(-90.,lonMax), osg::minimum( 45.,latMax) );
00608 //    _faceExtent_gcs[1] = GeoExtent( srs, osg::maximum( -90.,lonMin), osg::maximum(-45.,latMin), osg::minimum(  0.,lonMax), osg::minimum( 45.,latMax) );
00609 //    _faceExtent_gcs[2] = GeoExtent( srs, osg::maximum(   0.,lonMin), osg::maximum(-45.,latMin), osg::minimum( 90.,lonMax), osg::minimum( 45.,latMax) );
00610 //    _faceExtent_gcs[3] = GeoExtent( srs, osg::maximum(  90.,lonMin), osg::maximum(-45.,latMin), osg::minimum(180.,lonMax), osg::minimum( 45.,latMax) );
00611 //    _faceExtent_gcs[4] = GeoExtent( srs, osg::maximum(-180.,lonMin), osg::maximum( 45.,latMin), osg::minimum(180.,lonMax), osg::minimum( 90.,latMax) ); // north polar
00612 //    _faceExtent_gcs[5] = GeoExtent( srs, osg::maximum(-180.,lonMin), osg::maximum(-90.,latMin), osg::minimum(180.,lonMax), osg::minimum(-45.,latMax) ); // south polar
00613 //}
00614 
00615 int
00616 UnifiedCubeProfile::getFace( const TileKey& key )
00617 {
00618     return key.getTileX() >> key.getLevelOfDetail();
00619 }
00620 
00621 GeoExtent
00622 UnifiedCubeProfile::transformGcsExtentOnFace( const GeoExtent& gcsExtent, int face ) const
00623 {
00624     if ( face < 4 )
00625     {
00626         const GeoExtent& fex = _faceExtent_gcs[face];
00627 
00628         return GeoExtent(
00629             getSRS(),
00630             (double)face + (gcsExtent.xMin()-fex.xMin()) / fex.width(),
00631             (gcsExtent.yMin()-fex.yMin()) / fex.height(),
00632             (double)face + (gcsExtent.xMax()-fex.xMin()) / fex.width(),
00633             (gcsExtent.yMax()-fex.yMin()) / fex.height() );
00634     }
00635     else
00636     {
00637         // transform all 4 corners; then do the min/max for x/y.
00638         double lon[4] = { gcsExtent.xMin(), gcsExtent.xMax(), gcsExtent.xMax(), gcsExtent.xMin() };
00639         double lat[4] = { gcsExtent.yMin(), gcsExtent.yMin(), gcsExtent.yMax(), gcsExtent.yMax() };
00640         double x[4], y[4];
00641 
00642         for( int i=0; i<4; ++i )
00643         {
00644             int dummy;
00645             if ( ! CubeUtils::latLonToFaceCoords( lat[i], lon[i], x[i], y[i], dummy, face ) )
00646             {
00647                 OE_WARN << LC << "transformGcsExtentOnFace, ll2fc failed" << std::endl;
00648             }
00649         }
00650 
00651         double xmin = SMALLEST( x[0], x[1], x[2], x[3] );
00652         double xmax = LARGEST( x[0], x[1], x[2], x[3] );
00653         double ymin = SMALLEST( y[0], y[1], y[2], y[3] );
00654         double ymax = LARGEST( y[0], y[1], y[2], y[3] );
00655 
00656         CubeUtils::faceToCube( xmin, ymin, face );
00657         CubeUtils::faceToCube( xmax, ymax, face );
00658 
00659         return GeoExtent( getSRS(), xmin, ymin, xmax, ymax );
00660     }
00661 }
00662 
00663 void
00664 UnifiedCubeProfile::getIntersectingTiles(
00665     const GeoExtent& remoteExtent,
00666     std::vector<TileKey>& out_intersectingKeys ) const
00667 {
00668     if ( getSRS()->isEquivalentTo( remoteExtent.getSRS() ) )
00669     {
00670         addIntersectingTiles( remoteExtent, out_intersectingKeys );
00671     }
00672     else
00673     {
00674         // the cube profile is non-contiguous. so there may be multiple local extents required
00675         // to fully intersect the remote extent.
00676 
00677         // first transform the remote extent to lat/long.
00678         GeoExtent remoteExtent_gcs = remoteExtent.getSRS()->isGeographic()
00679             ? remoteExtent
00680             : remoteExtent.transform( remoteExtent.getSRS()->getGeographicSRS() );
00681 
00682         // Chop the input extent into three separate extents: for the equatorial, north polar,
00683         // and south polar tile regions.
00684         for( int face=0; face<6; ++face )
00685         {
00686             GeoExtent partExtent_gcs = _faceExtent_gcs[face].intersectionSameSRS( remoteExtent_gcs.bounds() );
00687             if ( partExtent_gcs.isValid() )
00688             {
00689                 GeoExtent partExtent = transformGcsExtentOnFace( partExtent_gcs, face );
00690                 addIntersectingTiles( partExtent, out_intersectingKeys );
00691             }
00692         }
00693     }
00694 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines