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/TileSource> 00021 #include <osgEarth/TMS> 00022 #include <osgEarth/FileUtils> 00023 #include <osgEarth/ImageUtils> 00024 #include <osgEarth/HTTPClient> 00025 00026 #include <osg/Notify> 00027 #include <osgDB/FileNameUtils> 00028 #include <osgDB/FileUtils> 00029 #include <osgDB/Registry> 00030 #include <osgDB/ReadFile> 00031 #include <osgDB/WriteFile> 00032 00033 #include <sstream> 00034 #include <iomanip> 00035 #include <string.h> 00036 00037 #include "TMSOptions" 00038 00039 using namespace osgEarth; 00040 using namespace osgEarth::Drivers; 00041 00042 #define LC "[TMS driver] " 00043 00044 00045 class TMSSource : public TileSource 00046 { 00047 public: 00048 TMSSource(const TileSourceOptions& options) : TileSource(options), _options(options) 00049 { 00050 _invertY = _options.tmsType() == "google"; 00051 } 00052 00053 00054 void initialize( const std::string& referenceURI, const Profile* overrideProfile) 00055 { 00056 const Profile* result = NULL; 00057 00058 URI tmsURI = _options.url().value(); 00059 if ( tmsURI.empty() ) 00060 { 00061 OE_WARN << LC << "Fail: TMS driver requires a valid \"url\" property" << std::endl; 00062 return; 00063 } 00064 00065 //Find the full path to the URL 00066 //If we have a relative path and the map file contains a server address, just concat the server path and the url together 00067 if (osgEarth::isRelativePath(tmsURI.full()) && osgDB::containsServerAddress(referenceURI)) 00068 { 00069 tmsURI = URI( osgDB::getFilePath(referenceURI) + std::string("/") + tmsURI.full() ); 00070 } 00071 00072 //If the path doesn't contain a server address, get the full path to the file. 00073 if (!osgDB::containsServerAddress(tmsURI.full())) 00074 { 00075 tmsURI = URI( tmsURI.full(), referenceURI ); 00076 //tmsPath = osgEarth::getFullPath(referenceURI, tmsURI); 00077 } 00078 00079 // Attempt to read the tile map parameters from a TMS TileMap XML tile on the server: 00080 _tileMap = TileMapReaderWriter::read( tmsURI.full(), 0L ); //getOptions() ); 00081 00082 00083 //Take the override profile if one is given 00084 if (overrideProfile) 00085 { 00086 OE_INFO << LC << "Using override profile " << overrideProfile->toString() << std::endl; 00087 result = overrideProfile; 00088 _tileMap = TileMap::create( 00089 _options.url()->full(), 00090 overrideProfile, 00091 _options.format().value(), 00092 _options.tileSize().value(), 00093 _options.tileSize().value() ); 00094 } 00095 else 00096 { 00097 if (_tileMap.valid()) 00098 { 00099 result = _tileMap->createProfile(); 00100 } 00101 else 00102 { 00103 OE_WARN << LC << "Error reading TMS TileMap, and no overrides set (url=" << tmsURI.full() << ")" << std::endl; 00104 return; 00105 } 00106 } 00107 00108 //Automatically set the min and max level of the TileMap 00109 if (_tileMap.valid() && _tileMap->getTileSets().size() > 0) 00110 { 00111 OE_INFO << LC << "TileMap min/max " << _tileMap->getMinLevel() << ", " << _tileMap->getMaxLevel() << std::endl; 00112 if (_tileMap->getDataExtents().size() > 0) 00113 { 00114 for (DataExtentList::iterator itr = _tileMap->getDataExtents().begin(); itr != _tileMap->getDataExtents().end(); ++itr) 00115 { 00116 this->getDataExtents().push_back(*itr); 00117 } 00118 } 00119 else 00120 { 00121 //Push back a single area that encompasses the whole profile going up to the max level 00122 this->getDataExtents().push_back(DataExtent(result->getExtent(), 0, _tileMap->getMaxLevel())); 00123 } 00124 } 00125 00126 setProfile( result ); 00127 } 00128 00129 00130 osg::Image* createImage(const osgEarth::TileKey& key, 00131 ProgressCallback* progress) 00132 { 00133 if (_tileMap.valid() && key.getLevelOfDetail() <= getMaxDataLevel() ) 00134 { 00135 std::string image_url = _tileMap->getURL( key, _invertY ); 00136 00137 //OE_NOTICE << "TMSSource: Key=" << key.str() << ", URL=" << image_url << std::endl; 00138 00139 00140 osg::ref_ptr<osg::Image> image; 00141 00142 if (!image_url.empty()) 00143 { 00144 HTTPClient::readImageFile( image_url, image, 0L, progress ); //getOptions(), progress ); 00145 } 00146 00147 if (!image.valid()) 00148 { 00149 if (image_url.empty() || !_tileMap->intersectsKey(key)) 00150 { 00151 //We couldn't read the image from the URL or the cache, so check to see if the given key is less than the max level 00152 //of the tilemap and create a transparent image. 00153 if (key.getLevelOfDetail() <= _tileMap->getMaxLevel()) 00154 { 00155 OE_INFO << LC << "Returning empty image " << std::endl; 00156 return ImageUtils::createEmptyImage(); 00157 } 00158 } 00159 } 00160 return image.release(); 00161 } 00162 return 0; 00163 } 00164 00165 virtual int getPixelsPerTile() const 00166 { 00167 return _tileMap->getFormat().getWidth(); 00168 } 00169 00170 virtual std::string getExtension() const 00171 { 00172 return _tileMap->getFormat().getExtension(); 00173 } 00174 00175 private: 00176 00177 osg::ref_ptr<TileMap> _tileMap; 00178 bool _invertY; 00179 const TMSOptions _options; 00180 }; 00181 00182 00183 00184 00185 class ReaderWriterTMS : public TileSourceDriver 00186 { 00187 private: 00188 typedef std::map< std::string,osg::ref_ptr<TileMap> > TileMapCache; 00189 TileMapCache _tileMapCache; 00190 00191 public: 00192 ReaderWriterTMS() 00193 { 00194 supportsExtension( "osgearth_tms", "Tile Map Service" ); 00195 } 00196 00197 virtual const char* className() 00198 { 00199 return "Tile Map Service ReaderWriter"; 00200 } 00201 00202 virtual ReadResult readObject(const std::string& file_name, const Options* options) const 00203 { 00204 if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name ))) 00205 return ReadResult::FILE_NOT_HANDLED; 00206 00207 return new TMSSource( getTileSourceOptions(options) ); 00208 } 00209 }; 00210 00211 REGISTER_OSGPLUGIN(osgearth_tms, ReaderWriterTMS) 00212