osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/earth/ReaderWriterOsgEarth.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 #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)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines