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 #include "EarthFileSerializer" 00020 #include <osgEarth/Map> 00021 #include <osgEarth/MapNode> 00022 #include <osgEarth/Registry> 00023 #include <osgEarth/XmlUtils> 00024 #include <osgEarth/HTTPClient> 00025 #include <osgDB/FileNameUtils> 00026 #include <osgDB/FileUtils> 00027 #include <osgDB/Registry> 00028 #include <string> 00029 #include <sstream> 00030 00031 using namespace osgEarth; 00032 00033 #define LC "[ReaderWriterEarth] " 00034 00035 class ReaderWriterEarth : public osgDB::ReaderWriter 00036 { 00037 public: 00038 ReaderWriterEarth() {} 00039 00040 virtual const char* className() 00041 { 00042 return "OSG Earth ReaderWriter"; 00043 } 00044 00045 virtual bool acceptsExtension(const std::string& extension) const 00046 { 00047 return osgDB::equalCaseInsensitive( extension, "earth" ); 00048 } 00049 00050 virtual ReadResult readObject(const std::string& file_name, const Options* options) const 00051 { 00052 return readNode( file_name, options ); 00053 } 00054 00055 virtual WriteResult writeNode(const osg::Node& node, const std::string& fileName, const Options* options ) const 00056 { 00057 if ( !acceptsExtension( osgDB::getFileExtension(fileName) ) ) 00058 return WriteResult::FILE_NOT_HANDLED; 00059 00060 std::ofstream out( fileName.c_str()); 00061 if ( out.is_open() ) 00062 return writeNode( node, out, options ); 00063 00064 return WriteResult::ERROR_IN_WRITING_FILE; 00065 } 00066 00067 virtual WriteResult writeNode(const osg::Node& node, std::ostream& out, const Options* options ) const 00068 { 00069 osg::Node* searchNode = const_cast<osg::Node*>( &node ); 00070 MapNode* mapNode = MapNode::findMapNode( searchNode ); 00071 if ( !mapNode ) 00072 return WriteResult::ERROR_IN_WRITING_FILE; // i.e., no MapNode found in the graph. 00073 00074 // serialize the map node to a generic Config object: 00075 EarthFileSerializer2 ser; 00076 Config conf = ser.serialize( mapNode ); 00077 00078 // dump that Config out as XML. 00079 osg::ref_ptr<XmlDocument> xml = new XmlDocument( conf ); 00080 xml->store( out ); 00081 00082 return WriteResult::FILE_SAVED; 00083 } 00084 00085 virtual ReadResult readNode(const std::string& fileName, const Options* options) const 00086 { 00087 std::string ext = osgDB::getFileExtension( fileName ); 00088 if ( !acceptsExtension( ext ) ) 00089 return ReadResult::FILE_NOT_HANDLED; 00090 00091 // See if the filename starts with server: and strip it off. This will trick OSG into 00092 // passing in the filename to our plugin instead of using the CURL plugin if the filename 00093 // contains a URL. So, if you want to read a URL, you can use the following format 00094 // osgDB::readNodeFile("server:http://myserver/myearth.earth"). This should only be 00095 // necessary for the first level as the other files will have a tilekey prepended to them. 00096 if ((fileName.length() > 7) && (fileName.substr(0, 7) == "server:")) 00097 return readNode(fileName.substr(7), options); 00098 00099 if ( fileName == "__globe.earth" ) 00100 { 00101 return ReadResult( new MapNode() ); 00102 } 00103 00104 else if ( fileName == "__cube.earth" ) 00105 { 00106 MapOptions options; 00107 options.coordSysType() = MapOptions::CSTYPE_GEOCENTRIC_CUBE; 00108 return ReadResult( new MapNode( new Map(options) ) ); 00109 } 00110 00111 else 00112 { 00113 std::string buf; 00114 if ( HTTPClient::readString( fileName, buf ) != HTTPClient::RESULT_OK ) 00115 return ReadResult::ERROR_IN_READING_FILE; 00116 00117 // Since we're now passing off control to the stream, we have to pass along the 00118 // reference URI as well.. 00119 osg::ref_ptr<Options> myOptions = options ? 00120 static_cast<Options*>(options->clone(osg::CopyOp::DEEP_COPY_ALL)) : 00121 new Options(); 00122 00123 URIContext( fileName ).store( myOptions.get() ); 00124 //myOptions->setPluginData( "__ReaderWriterOsgEarth::ref_uri", (void*)&fileName ); 00125 00126 std::stringstream in( buf ); 00127 return readNode( in, myOptions.get() ); 00128 } 00129 } 00130 00131 virtual ReadResult readNode(std::istream& in, const Options* options ) const 00132 { 00133 // pull the URI context from the options structure (since we're reading 00134 // from an "anonymous" stream here) 00135 URIContext uriContext( options ); 00136 00137 osg::ref_ptr<XmlDocument> doc = XmlDocument::load( in, uriContext ); 00138 if ( !doc.valid() ) 00139 return ReadResult::ERROR_IN_READING_FILE; 00140 00141 Config docConf = doc->getConfig(); 00142 00143 // support both "map" and "earth" tag names at the top level 00144 Config conf; 00145 if ( docConf.hasChild( "map" ) ) 00146 conf = docConf.child( "map" ); 00147 else if ( docConf.hasChild( "earth" ) ) 00148 conf = docConf.child( "earth" ); 00149 00150 MapNode* mapNode =0L; 00151 if ( !conf.empty() ) 00152 { 00153 // see if we were given a reference URI to use: 00154 std::string refURI = uriContext.referrer(); 00155 00156 if ( conf.value("version") == "2" ) 00157 { 00158 OE_INFO << LC << "Detected a version 2.x earth file" << std::endl; 00159 EarthFileSerializer2 ser; 00160 mapNode = ser.deserialize( conf, refURI ); 00161 } 00162 else 00163 { 00164 OE_INFO << LC << "Detected a version 1.x earth file" << std::endl; 00165 EarthFileSerializer1 ser; 00166 mapNode = ser.deserialize( conf, refURI ); 00167 } 00168 } 00169 00170 return ReadResult(mapNode); 00171 } 00172 }; 00173 00174 REGISTER_OSGPLUGIN(earth, ReaderWriterEarth)