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/VirtualFeatureSource> 00020 00021 #define LC "[VirtualFeatureSource] " 00022 00023 using namespace osgEarth; 00024 using namespace osgEarth::Util; 00025 using namespace osgEarth::Features; 00026 00027 //------------------------------------------------------------------------ 00028 00029 namespace 00030 { 00034 struct VirtualFeatureCursor : public FeatureCursor 00035 { 00036 VirtualFeatureCursor( const FeatureSourceMappingVector& sources, const Query& query ) : 00037 _sources(sources), _query(query) 00038 { 00039 _si = _sources.begin(); 00040 advance(); 00041 } 00042 00043 bool hasMore() const 00044 { 00045 return _nextFeature.valid(); 00046 } 00047 00048 Feature* nextFeature() 00049 { 00050 _lastFeatureReturned = _nextFeature.get(); 00051 _nextFeature = 0L; 00052 if ( _lastFeatureReturned.valid() ) 00053 advance(); 00054 return _lastFeatureReturned.get(); 00055 } 00056 00057 private: 00058 // pulls the next feature (in advance) in preparation for the next 00059 // call to nextFeature. 00060 void advance() 00061 { 00062 _nextFeature = 0L; 00063 00064 while ( !_nextFeature.valid() ) 00065 { 00066 // check to see if we are completely done: 00067 if ( _si == _sources.end() ) 00068 return; 00069 00070 // if we're at the beginning, create the first cursor: 00071 if ( _si == _sources.begin() && !_si_cursor.valid() ) 00072 { 00073 _si_cursor = _si->_source->createFeatureCursor( _query ); 00074 } 00075 00076 while ( !_si_cursor.valid() || !_si_cursor->hasMore() ) 00077 { 00078 // if the current cursor is done, advance to the next source. 00079 // if there is no next source, we are done. 00080 if ( ++_si == _sources.end() ) 00081 return; 00082 00083 // make a cursor for the next source 00084 _si_cursor = _si->_source->createFeatureCursor( _query ); 00085 } 00086 00087 // here, we have a valid cursor with pending data: 00088 Feature* f = _si_cursor->nextFeature(); 00089 00090 // test against the predicate. (a NULL predicate always accepts the feature) 00091 if ( !_si->_predicate.valid() || _si->_predicate->acceptFeature( f ) ) 00092 _nextFeature = f; 00093 } 00094 } 00095 00096 private: 00097 FeatureSourceMappingVector _sources; 00098 Query _query; 00099 FeatureSourceMappingVector::iterator _si; // points to current source 00100 osg::ref_ptr<FeatureCursor> _si_cursor; // cursor into current source 00101 osg::ref_ptr<Feature> _nextFeature; 00102 osg::ref_ptr<Feature> _lastFeatureReturned; // to manage references during iteration 00103 }; 00104 } 00105 00106 //------------------------------------------------------------------------ 00107 00108 void 00109 VirtualFeatureSource::add( FeatureSource* source, FeaturePredicate* predicate ) 00110 { 00111 _sources.push_back( FeatureSourceMapping(source, predicate) ); 00112 dirty(); 00113 } 00114 00115 FeatureCursor* 00116 VirtualFeatureSource::createFeatureCursor( const Query& query ) 00117 { 00118 return new VirtualFeatureCursor( _sources, query ); 00119 } 00120 00121 void 00122 VirtualFeatureSource::initialize( const std::string& referenceURI ) 00123 { 00124 for( FeatureSourceMappingVector::iterator i = _sources.begin(); i != _sources.end(); ++i ) 00125 { 00126 i->_source->initialize( referenceURI ); 00127 } 00128 } 00129 00130 const FeatureProfile* 00131 VirtualFeatureSource::createFeatureProfile() 00132 { 00133 if ( _sources.size() > 0 ) 00134 return _sources.front()._source->getFeatureProfile(); 00135 else 00136 return 0L; 00137 } 00138 00139 const FeatureSchema& 00140 VirtualFeatureSource::getSchema() const 00141 { 00142 static FeatureSchema s_emptySchema; 00143 00144 return _sources.size() > 0 ?_sources.front()._source->getSchema() : s_emptySchema; 00145 }