osgEarth 2.1.1
|
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 }