/* -*-c++-*- */ /* osgEarth - Geospatial SDK for OpenSceneGraph * Copyright 2020 Pelican Mapping * http://osgearth.org * * osgEarth is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see */ #ifndef OSGEARTH_MAP_H #define OSGEARTH_MAP_H 1 #include #include #include #include #include #include #include #include #include #include namespace osgEarth { /** * Map is the main data model. A Map hold a collection of * Layers, each of which provides data of some kind to the * overall Map. Use a MapNode to render the contents of a * Map. */ class OSGEARTH_EXPORT Map : public osg::Object { public: META_Object(osgEarth, Map); //! Construct a new, empty map. Map(); //! Construct a new, empty map with custom read options. Map(const osgDB::Options* readOptions); //! This Map's unique ID UID getUID() const { return _uid; } //! The map's master tiling profile, which defines its SRS and tiling structure void setProfile(const Profile* value); const Profile* getProfile() const; //! Spatial reference system of the map's profile (convenience) const SpatialReference* getSRS() const; //! SRS of the world (scene) const SpatialReference* getWorldSRS() const; //! Elevation data interpolation method void setElevationInterpolation(const RasterInterpolation& value); const RasterInterpolation& getElevationInterpolation() const; //! Adds a Layer to the map. void addLayer(Layer* layer); //! Adds a collection of layers to the map. void addLayers(const LayerVector& layers); //! Inserts a Layer at a specific index in the Map. void insertLayer(Layer* layer, unsigned index); //! Removes a layer from the map. void removeLayer(Layer* layer); //! Moves a layer to another position in the Map. void moveLayer(Layer* layer, unsigned index); //! Index of the specified layer, or returns getNumLayers() if the layer is not found. unsigned getIndexOfLayer(const Layer* layer) const; //! Copies references of the map layers into the output list. //! This method is thread safe. It returns the map revision that was //! in effect when the data was copied. Revision getLayers(LayerVector& out_layers) const; //! Copies references of the map layers into the output list for which //! the predicate function returns true. //! This method is thread safe. It returns the map revision that was //! in effect when the data was copied. inline Revision getLayers( LayerVector& out_layers, const std::function& predicate) const; //! Number of layers in the map. unsigned getNumLayers() const; //! Gets a layer by name. Layer* getLayerByName(const std::string& name) const; template T* getLayerByName(const std::string& name) const; //! Gets an image layer by its unique ID. Layer* getLayerByUID(UID layerUID) const; template T* getLayerByUID(UID layerUID) const; //! Gets the layer at the specified index. Layer* getLayerAt(unsigned index) const; template T* getLayerAt(unsigned index) const; //! Fills the vector with references to all layers of the specified type //! and returns the corresponding revision number. template Revision getLayers(std::vector< osg::ref_ptr >& output) const; //! Fills the vector with references to all layers of the specified type //! and returns the corresponding revision number. template Revision getOpenLayers(std::vector< osg::ref_ptr >& output) const; //! Fills the vector with references to all layers satisflying the predicate //! and returns the corresponding revision number. template Revision getLayers( std::vector< osg::ref_ptr >& output, const std::function& predicate) const; //! Fills the vector with references to all layers of the specified type. //! and returns the corresponding revision number. template Revision getLayers(osg::MixinVector< osg::ref_ptr >& output) const; //! Fills the vector with references to all layers satisflying the predicate //! and returns the corresponding revision number. template Revision getLayers( osg::MixinVector>& output, const std::function& predicate) const; //! Fills the vector with references to all layers of the specified type. //! and returns the corresponding revision number. template Revision getOpenLayers(osg::MixinVector< osg::ref_ptr >& output) const; //! The first layer of the specified type. This is useful when you //! know there in only one layer of the type you are looking for. template T* getLayer() const; //! Adds a map layer callback to this map. This will be notified whenever layers are //! added, removed, or re-ordered. MapCallback* addMapCallback(MapCallback* callback) const; //! Removes a callback previously added with addMapCallback. void removeMapCallback(MapCallback* callback) const; //! Begins a batch-update operation. Call this if you intend to add multiple //! layers at once; then call endUpdate() to complete the operation. //! Between calls to beginUpdate() and endUpdate(), Map will not invoke //! any callbacks you added wtih addMapCallback. void beginUpdate(); //! Completes a batch update operation that started with a call to //! beginUpdate(). Fires all callbacks for operations that occurred //! since the call to beginUpdate(). void endUpdate(); //! Removes all layers from this map. void clear(); //! Sets the readable name of this map. void setMapName( const std::string& name ); const std::string& getMapName() const { return _name; } //! Cache for this Map. Set to NULL for no cache. //! Only call this during intiailization. void setCache( Cache* cache ); Cache* getCache() const; //! Caching policy (now the map should use the cache) void setCachePolicy(const CachePolicy& value); const CachePolicy& getCachePolicy() const; //! Gets the revision # of the map. The revision # changes every time //! you add, remove, or move layers. You can use this to track changes //! in the map model (as a alternative to installing a MapCallback). Revision getDataModelRevision() const; //! Gets the database options associated with this map. const osgDB::Options* getReadOptions() const { return _readOptions.get(); } //! Gets a version of the map profile without any vertical datum const Profile* getProfileNoVDatum() const { return _profileNoVDatum.get(); } //! Access to an elevation sampling service tied to this map ElevationPool* getElevationPool() const; //! Returns true if data for the given tile key and layers is likely //! to generate data quickly. This is used for pager thread pool shunting. //! Really just a best guess based on available information. bool isFast(const TileKey& key, const LayerVector& layers) const; //! List of attribution strings to be displayed by the application void getAttributions(StringSet& attributions) const; //! Number of layers marked as terrain pathes int getNumTerrainPatchLayers() const; protected: virtual ~Map(); // disables copy construction Map(const Map& rhs, const osg::CopyOp& copy) { } public: // serialization data class OSGEARTH_EXPORT Options : public ConfigOptions { public: META_ConfigOptions(osgEarth, Options, ConfigOptions); OE_OPTION(std::string, name); OE_OPTION(ProfileOptions, profile); OE_OPTION(CacheOptions, cache); OE_OPTION(CachePolicy, cachePolicy); OE_OPTION(RasterInterpolation, elevationInterpolation, INTERP_BILINEAR); OE_OPTION(std::string, profileLayer); OE_OPTION(std::string, osgOptionString); OE_OPTION(bool, disableElevationRanges, false); virtual Config getConfig() const; private: void fromConfig(const Config&); }; //! Internal - create from serialized options Map( const Map::Options& options, const osgDB::Options* readOptions); //! Ready-only access to the serialization options for this map const Options& options() const { return _optionsConcrete; } private: UID _uid; std::string _name; LayerVector _layers; mutable MapCallbackList _mapCallbacks; mutable Threading::ReadWriteMutex _mapDataMutex; osg::ref_ptr _profile; osg::ref_ptr _profileNoVDatum; Revision _dataModelRevision; osg::ref_ptr _readOptions; osg::ref_ptr _elevationPool; osg::ref_ptr _cacheSettings; int _numTerrainPatchLayers; struct LayerCB : public LayerCallback { LayerCB(Map*); osg::observer_ptr _map; void onOpen(Layer* layer); void onClose(Layer* layer); }; osg::ref_ptr _layerCB; friend struct LayerCB; void notifyOnLayerOpenOrClose(Layer*); void installLayerCallbacks(Layer*); void uninstallLayerCallbacks(Layer*); void init(); Options _optionsConcrete; Options& options() { return _optionsConcrete; } }; // Templated inline methods template T* Map::getLayerByName(const std::string& name) const { return dynamic_cast(getLayerByName(name)); } template T* Map::getLayerByUID(UID layerUID) const { return dynamic_cast(getLayerByUID(layerUID)); } template T* Map::getLayerAt(unsigned index) const { return dynamic_cast(getLayerAt(index)); } template Revision Map::getLayers(std::vector>& output) const { Threading::ScopedReadLock lock(_mapDataMutex); for (auto& i : _layers) { T* obj = dynamic_cast(i.get()); if (obj) output.push_back(obj); } return _dataModelRevision; } template Revision Map::getLayers(std::vector>& output, const std::function& predicate) const { Threading::ScopedReadLock lock(_mapDataMutex); for (auto& i : _layers) { T* obj = dynamic_cast(i.get()); if (obj != nullptr && predicate(obj)) output.push_back(obj); } return _dataModelRevision; } template Revision Map::getOpenLayers(std::vector>& output) const { Threading::ScopedReadLock lock(_mapDataMutex); for (auto& i : _layers) { if (i->isOpen()) { T* obj = dynamic_cast(i.get()); if (obj) output.push_back(obj); } } return _dataModelRevision; } template Revision Map::getLayers(osg::MixinVector>& output) const { Threading::ScopedReadLock lock(_mapDataMutex); for (auto& i : _layers) { T* obj = dynamic_cast(i.get()); if (obj) output.push_back(obj); } return _dataModelRevision; } template Revision Map::getLayers(osg::MixinVector>& output, const std::function& predicate) const { Threading::ScopedReadLock lock(_mapDataMutex); for (auto& i : _layers) { T* obj = dynamic_cast(i.get()); if (obj != nullptr && predicate(obj)) output.push_back(obj); } return _dataModelRevision; } template Revision Map::getOpenLayers(osg::MixinVector>& output) const { Threading::ScopedReadLock lock(_mapDataMutex); for (auto& i : _layers) { if (i->isOpen()) { T* obj = dynamic_cast(i.get()); if (obj) output.push_back(obj); } } return _dataModelRevision; } template T* Map::getLayer() const { Threading::ScopedReadLock lock(_mapDataMutex); for (auto& i : _layers) { T* obj = dynamic_cast(i.get()); if (obj) return obj; } return 0L; } Revision Map::getLayers(LayerVector& output, const std::function& predicate) const { Threading::ScopedReadLock lock(_mapDataMutex); for (auto& i : _layers) { if (predicate(i.get())) output.push_back(i.get()); } return _dataModelRevision; } } #endif // OSGEARTH_MAP_H