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 <osgEarthFeatures/FeatureSource> 00020 #include <osgEarthFeatures/ResampleFilter> 00021 #include <osgEarthFeatures/BufferFilter> 00022 #include <osgEarthFeatures/ConvertTypeFilter> 00023 #include <osg/Notify> 00024 #include <osgDB/ReadFile> 00025 #include <OpenThreads/ScopedLock> 00026 00027 #define LC "[FeatureSource] " 00028 00029 using namespace osgEarth::Features; 00030 using namespace osgEarth::Symbology; 00031 using namespace OpenThreads; 00032 00033 FeatureSourceOptions::FeatureSourceOptions( const ConfigOptions& options ) : 00034 DriverConfigOptions( options ) 00035 { 00036 fromConfig( _conf ); 00037 } 00038 00039 void 00040 FeatureSourceOptions::fromConfig( const Config& conf ) 00041 { 00042 unsigned numResamples = 0; 00043 00044 conf.getIfSet ( "open_write", _openWrite ); 00045 conf.getIfSet ( "name", _name ); 00046 conf.getObjIfSet( "profile", _profile ); 00047 00048 const ConfigSet& children = conf.children(); 00049 for( ConfigSet::const_iterator i = children.begin(); i != children.end(); ++i ) 00050 { 00051 const Config& child = *i; 00052 00053 if ( child.key() == "buffer" && !child.empty() ) 00054 { 00055 BufferFilter* buffer = new BufferFilter(); 00056 child.getIfSet( "distance", buffer->distance() ); 00057 _filters.push_back( buffer ); 00058 00059 if ( numResamples > 0 ) 00060 { 00061 OE_WARN << LC 00062 << "Warning: Resampling should be applied before buffering, as buffering" 00063 << " will remove colinear segments created by the buffer operation." 00064 << std::endl; 00065 } 00066 00067 OE_DEBUG << LC << "Added buffer filter" << std::endl; 00068 } 00069 00070 else if ( child.key() == "resample" && !child.empty() ) 00071 { 00072 ResampleFilter* resample = new ResampleFilter(); 00073 child.getIfSet( "min_length", resample->minLength() ); 00074 child.getIfSet( "max_length", resample->maxLength() ); 00075 _filters.push_back( resample ); 00076 numResamples++; 00077 00078 OE_DEBUG << LC << "Added resample filter" << std::endl; 00079 } 00080 00081 else if ( child.key() == "convert" && !child.empty() ) 00082 { 00083 ConvertTypeFilter* convert = new ConvertTypeFilter(); 00084 optional<Geometry::Type> type = Geometry::TYPE_POINTSET; 00085 child.getIfSet( "type", "point", type, Geometry::TYPE_POINTSET ); 00086 child.getIfSet( "type", "line", type, Geometry::TYPE_LINESTRING ); 00087 child.getIfSet( "type", "polygon", type, Geometry::TYPE_POLYGON ); 00088 convert->toType() = *type; 00089 _filters.push_back( convert ); 00090 00091 OE_DEBUG << LC << "Added convert filter" << std::endl; 00092 } 00093 } 00094 } 00095 00096 Config 00097 FeatureSourceOptions::getConfig() const 00098 { 00099 Config conf = DriverConfigOptions::getConfig(); 00100 00101 conf.updateIfSet ( "open_write", _openWrite ); 00102 conf.updateIfSet ( "name", _name ); 00103 conf.updateObjIfSet( "profile", _profile ); 00104 00105 //TODO: make each of these filters Configurable. 00106 for( FeatureFilterList::const_iterator i = _filters.begin(); i != _filters.end(); ++i ) 00107 { 00108 BufferFilter* buffer = dynamic_cast<BufferFilter*>( i->get() ); 00109 if ( buffer ) { 00110 Config bufferConf( "buffer" ); 00111 bufferConf.addIfSet( "distance", buffer->distance() ); 00112 conf.update( bufferConf ); 00113 } 00114 00115 ResampleFilter* resample = dynamic_cast<ResampleFilter*>( i->get() ); 00116 if ( resample ) { 00117 Config resampleConf( "resample" ); 00118 resampleConf.addIfSet( "min_length", resample->minLength() ); 00119 resampleConf.addIfSet( "max_length", resample->maxLength() ); 00120 conf.update( resampleConf ); 00121 } 00122 00123 ConvertTypeFilter* convert = dynamic_cast<ConvertTypeFilter*>( i->get() ); 00124 if ( convert ) { 00125 Config convertConf( "convert" ); 00126 optional<Geometry::Type> type( convert->toType(), convert->toType() ); // weird optional ctor :) 00127 convertConf.addIfSet( "type", "point", type, Geometry::TYPE_POINTSET ); 00128 convertConf.addIfSet( "type", "line", type, Geometry::TYPE_LINESTRING ); 00129 convertConf.addIfSet( "type", "polygon", type, Geometry::TYPE_POLYGON ); 00130 conf.update( convertConf ); 00131 } 00132 } 00133 00134 return conf; 00135 } 00136 00137 //------------------------------------------------------------------------ 00138 00139 FeatureSource::FeatureSource( const ConfigOptions& options ) : 00140 _options( options ) 00141 { 00142 //nop 00143 } 00144 00145 const FeatureProfile* 00146 FeatureSource::getFeatureProfile() const 00147 { 00148 if ( !_featureProfile.valid() ) 00149 { 00150 FeatureSource* nonConstThis = const_cast<FeatureSource*>(this); 00151 00152 ScopedLock<Mutex> doubleCheckLock( nonConstThis->_createMutex ); 00153 { 00154 if ( !_featureProfile.valid() ) 00155 { 00156 // caching pattern 00157 nonConstThis->_featureProfile = nonConstThis->createFeatureProfile(); 00158 } 00159 } 00160 } 00161 return _featureProfile.get(); 00162 } 00163 00164 const FeatureFilterList& 00165 FeatureSource::getFilters() const 00166 { 00167 return _options.filters(); 00168 } 00169 00170 const FeatureSchema& 00171 FeatureSource::getSchema() const 00172 { 00173 static FeatureSchema s_emptySchema; 00174 return s_emptySchema; 00175 } 00176 00177 //------------------------------------------------------------------------ 00178 00179 #undef LC 00180 #define LC "[FeatureSourceFactory] " 00181 #define FEATURE_SOURCE_OPTIONS_TAG "__osgEarth::FeatureSourceOptions" 00182 00183 FeatureSource* 00184 FeatureSourceFactory::create( const FeatureSourceOptions& options ) 00185 { 00186 FeatureSource* featureSource = 0L; 00187 00188 if ( !options.getDriver().empty() ) 00189 { 00190 std::string driverExt = std::string(".osgearth_feature_") + options.getDriver(); 00191 00192 osg::ref_ptr<osgDB::ReaderWriter::Options> rwopts = new osgDB::ReaderWriter::Options(); 00193 rwopts->setPluginData( FEATURE_SOURCE_OPTIONS_TAG, (void*)&options ); 00194 00195 featureSource = dynamic_cast<FeatureSource*>( osgDB::readObjectFile( driverExt, rwopts.get() ) ); 00196 if ( featureSource ) 00197 { 00198 if ( options.name().isSet() ) 00199 featureSource->setName( *options.name() ); 00200 else 00201 featureSource->setName( options.getDriver() ); 00202 } 00203 else 00204 { 00205 OE_WARN << LC << "FAILED to load feature driver \"" << options.getDriver() << "\"" << std::endl; 00206 } 00207 } 00208 else 00209 { 00210 OE_WARN << LC << "ILLEGAL null feature driver name" << std::endl; 00211 } 00212 00213 return featureSource; 00214 } 00215 00216 //------------------------------------------------------------------------ 00217 00218 const FeatureSourceOptions& 00219 FeatureSourceDriver::getFeatureSourceOptions( const osgDB::ReaderWriter::Options* rwopt ) const 00220 { 00221 return *static_cast<const FeatureSourceOptions*>( rwopt->getPluginData( FEATURE_SOURCE_OPTIONS_TAG ) ); 00222 }