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 <osgEarthSymbology/ResourceLibrary> 00020 #include <osgEarth/ThreadingUtils> 00021 #include <osgEarth/XmlUtils> 00022 #include <osgEarth/HTTPClient> 00023 #include <osgEarth/Random> 00024 #include <iterator> 00025 #include <algorithm> 00026 #include <fstream> 00027 00028 #define LC "[ResourceLibrary] " 00029 00030 using namespace osgEarth; 00031 using namespace osgEarth::Symbology; 00032 using namespace OpenThreads; 00033 00034 //------------------------------------------------------------------------ 00035 00036 ResourceLibrary* 00037 ResourceLibrary::create( const URI& uri ) 00038 { 00039 osg::ref_ptr<XmlDocument> xml = XmlDocument::load( uri ); // buf, uri.full() ); 00040 if ( !xml.valid() ) 00041 { 00042 OE_WARN << LC << "Failed to parse XML for resource library \"" << uri.full() << "\"" << std::endl; 00043 return 0L; 00044 } 00045 00046 Config conf = xml->getConfig(); 00047 00048 if ( conf.key() == "resources" ) 00049 { 00050 return new ResourceLibrary( conf ); 00051 } 00052 else 00053 { 00054 const Config& child = conf.child("resources"); 00055 if ( !child.empty() ) 00056 return new ResourceLibrary( child ); 00057 } 00058 00059 OE_WARN << LC << "Could not find top level 'resources' entry in resource library \"" 00060 << uri.full() << "\"; load failed." << std::endl; 00061 return 0L; 00062 } 00063 00064 //------------------------------------------------------------------------ 00065 00066 ResourceLibrary::ResourceLibrary( const Config& conf ) 00067 { 00068 mergeConfig( conf ); 00069 } 00070 00071 void 00072 ResourceLibrary::mergeConfig( const Config& conf ) 00073 { 00074 // read skins 00075 const ConfigSet skins = conf.children( "skin" ); 00076 for( ConfigSet::const_iterator i = skins.begin(); i != skins.end(); ++i ) 00077 { 00078 addResource( new SkinResource(*i) ); 00079 } 00080 00081 //todo: other types later.. 00082 } 00083 00084 void 00085 ResourceLibrary::addResource( Resource* resource ) 00086 { 00087 if ( dynamic_cast<SkinResource*>( resource ) ) 00088 { 00089 Threading::ScopedWriteLock exclusive(_mutex); 00090 _skins[resource->name()] = static_cast<SkinResource*>(resource); 00091 } 00092 else 00093 { 00094 OE_WARN << LC << "Added a resource type that is not supported; ignoring." << std::endl; 00095 } 00096 } 00097 00098 void 00099 ResourceLibrary::removeResource( Resource* resource ) 00100 { 00101 if ( dynamic_cast<SkinResource*>( resource ) ) 00102 { 00103 Threading::ScopedWriteLock exclusive(_mutex); 00104 _skins.erase( resource->name() ); 00105 } 00106 } 00107 00108 SkinResource* 00109 ResourceLibrary::getSkin( const std::string& name ) const 00110 { 00111 Threading::ScopedReadLock shared( const_cast<ResourceLibrary*>(this)->_mutex ); 00112 SkinResourceMap::const_iterator i = _skins.find( name ); 00113 return i != _skins.end() ? i->second.get() : 0L; 00114 } 00115 00116 void 00117 ResourceLibrary::getSkins( SkinResourceVector& output ) const 00118 { 00119 Threading::ScopedReadLock shared( const_cast<ResourceLibrary*>(this)->_mutex ); 00120 output.reserve( _skins.size() ); 00121 for( SkinResourceMap::const_iterator i = _skins.begin(); i != _skins.end(); ++i ) 00122 output.push_back( i->second.get() ); 00123 } 00124 00125 void 00126 ResourceLibrary::getSkins( const SkinSymbol* symbol, SkinResourceVector& output ) const 00127 { 00128 Threading::ScopedReadLock shared( const_cast<ResourceLibrary*>(this)->_mutex ); 00129 00130 for( SkinResourceMap::const_iterator i = _skins.begin(); i != _skins.end(); ++i ) 00131 { 00132 SkinResource* skin = i->second.get(); 00133 if ( matches(symbol, skin) ) 00134 { 00135 output.push_back( skin ); 00136 } 00137 } 00138 } 00139 00140 SkinResource* 00141 ResourceLibrary::getSkin( const SkinSymbol* symbol, Random& prng ) const 00142 { 00143 SkinResourceVector candidates; 00144 getSkins( symbol, candidates ); 00145 unsigned size = candidates.size(); 00146 if ( size == 0 ) 00147 { 00148 return 0L; 00149 } 00150 else if ( size == 1 ) 00151 { 00152 return candidates[0].get(); 00153 } 00154 else 00155 { 00156 return candidates[ prng.next(size) ].get(); 00157 } 00158 } 00159 00160 bool 00161 ResourceLibrary::matches( const SkinSymbol* q, SkinResource* s ) const 00162 { 00163 if (q->objectHeight().isSet()) 00164 { 00165 if (s->minObjectHeight().isSet() && 00166 q->objectHeight().value() < s->minObjectHeight().value() ) 00167 { 00168 return false; 00169 } 00170 if (s->maxObjectHeight().isSet() && 00171 q->objectHeight().value() > s->maxObjectHeight().value() ) 00172 { 00173 return false; 00174 } 00175 } 00176 00177 if (q->minObjectHeight().isSet() && 00178 s->maxObjectHeight().isSet() && 00179 q->minObjectHeight().value() > s->maxObjectHeight().value() ) 00180 { 00181 return false; 00182 } 00183 00184 if (q->maxObjectHeight().isSet() && 00185 s->minObjectHeight().isSet() && 00186 q->maxObjectHeight().value() < s->minObjectHeight().value() ) 00187 { 00188 return false; 00189 } 00190 00191 if (q->isTiled().isSet() && 00192 q->isTiled().value() != s->isTiled().value() ) 00193 { 00194 return false; 00195 } 00196 00197 if (q->tags().size() > 0 && !s->containsTags(q->tags()) ) 00198 { 00199 return false; 00200 } 00201 00202 return true; 00203 }