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/TileKey> 00021 00022 using namespace osgEarth; 00023 00024 //------------------------------------------------------------------------ 00025 00026 TileKey TileKey::INVALID( 0, 0, 0, 0L ); 00027 00028 //------------------------------------------------------------------------ 00029 00030 TileKey::TileKey( unsigned int lod, unsigned int tile_x, unsigned int tile_y, const Profile* profile) 00031 { 00032 _x = tile_x; 00033 _y = tile_y; 00034 _lod = lod; 00035 _profile = profile; 00036 00037 double width, height; 00038 if ( _profile.valid() ) 00039 { 00040 _profile->getTileDimensions(lod, width, height); 00041 00042 double xmin = _profile->getExtent().xMin() + (width * (double)_x); 00043 double ymax = _profile->getExtent().yMax() - (height * (double)_y); 00044 double xmax = xmin + width; 00045 double ymin = ymax - height; 00046 00047 _extent = GeoExtent( _profile->getSRS(), xmin, ymin, xmax, ymax ); 00048 00049 std::stringstream buf; 00050 buf << _lod << "_" << _x << "_" << _y; 00051 _key = buf.str(); 00052 } 00053 else 00054 { 00055 _extent = GeoExtent::INVALID; 00056 _key = "invalid"; 00057 } 00058 } 00059 00060 TileKey::TileKey( const TileKey& rhs ) : 00061 _key( rhs._key ), 00062 _lod(rhs._lod), 00063 _x(rhs._x), 00064 _y(rhs._y), 00065 _profile( rhs._profile.get() ), 00066 _extent( rhs._extent ) 00067 { 00068 //NOP 00069 } 00070 00071 const Profile* 00072 TileKey::getProfile() const 00073 { 00074 return _profile.get(); 00075 } 00076 00077 void 00078 TileKey::getTileXY(unsigned int& out_tile_x, 00079 unsigned int& out_tile_y) const 00080 { 00081 out_tile_x = _x; 00082 out_tile_y = _y; 00083 } 00084 00085 osgTerrain::TileID 00086 TileKey::getTileId() const 00087 { 00088 //TODO: will this be an issue with multi-face? perhaps not since each face will 00089 // exist within its own scene graph.. ? 00090 return osgTerrain::TileID(_lod, _x, _y); 00091 } 00092 00093 unsigned int 00094 TileKey::getLevelOfDetail() const 00095 { 00096 return _lod; 00097 } 00098 00099 void 00100 TileKey::getPixelExtents(unsigned int& xmin, 00101 unsigned int& ymin, 00102 unsigned int& xmax, 00103 unsigned int& ymax, 00104 const unsigned int &tile_size) const 00105 { 00106 xmin = _x * tile_size; 00107 ymin = _y * tile_size; 00108 xmax = xmin + tile_size; 00109 ymax = ymin + tile_size; 00110 } 00111 00112 TileKey 00113 TileKey::createChildKey( unsigned int quadrant ) const 00114 { 00115 unsigned int lod = _lod + 1; 00116 unsigned int x = _x * 2; 00117 unsigned int y = _y * 2; 00118 00119 if (quadrant == 1) 00120 { 00121 x+=1; 00122 } 00123 else if (quadrant == 2) 00124 { 00125 y+=1; 00126 } 00127 else if (quadrant == 3) 00128 { 00129 x+=1; 00130 y+=1; 00131 } 00132 return TileKey( lod, x, y, _profile.get()); 00133 } 00134 00135 00136 TileKey 00137 TileKey::createParentKey() const 00138 { 00139 if (_lod == 0) return TileKey::INVALID; 00140 00141 unsigned int lod = _lod - 1; 00142 unsigned int x = _x / 2; 00143 unsigned int y = _y / 2; 00144 return TileKey( lod, x, y, _profile.get()); 00145 } 00146 00147 TileKey 00148 TileKey::createAncestorKey( int ancestorLod ) const 00149 { 00150 if ( ancestorLod > (int)_lod ) return TileKey::INVALID; 00151 00152 unsigned int x = _x, y = _y; 00153 for( int i=_lod; i > ancestorLod; i-- ) 00154 { 00155 x /= 2; 00156 y /= 2; 00157 } 00158 return TileKey( ancestorLod, x, y, _profile.get() ); 00159 } 00160 00161 TileKey 00162 TileKey::createNeighborKey( TileKey::Direction dir ) const 00163 { 00164 unsigned int tx, ty; 00165 getProfile()->getNumTiles( _lod, tx, ty ); 00166 00167 unsigned int x = 00168 dir == WEST ? _x > 0 ? _x-1 : tx-1 : 00169 dir == EAST ? _x+1 < tx ? _x+1 : 0 : 00170 _x; 00171 00172 unsigned int y = 00173 dir == SOUTH ? _y > 0 ? _y-1 : ty-1 : 00174 dir == NORTH ? _y+1 < ty ? _y+1 : 0 : 00175 _y; 00176 00177 return TileKey( _lod, x, y, _profile.get() ); 00178 }