osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthSymbology/ResourceLibrary.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 <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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines