1/* -*-c++-*- */
2/* osgEarth - Geospatial SDK for OpenSceneGraph
3 * Copyright 2019 Pelican Mapping
4 * http://osgearth.org
5 *
6 * osgEarth is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>
18 */
19
20#ifndef OSGEARTH_MAP_H
21#define OSGEARTH_MAP_H 1
22
23#include <osgEarth/Common>
24#include <osgEarth/GeoData>
25#include <osgEarth/Profile>
26#include <osgEarth/MapOptions>
27#include <osgEarth/MapCallback>
28#include <osgEarth/Revisioning>
29#include <osgEarth/ThreadingUtils>
30#include <osgEarth/ElevationPool>
31#include <osgDB/Options>
32
33namespace osgEarth
34{
35    class MapInfo;
36
37    /**
38     * Map is the main data model that the MapNode will render. It is a
39     * container for all Layer objects (that contain the actual data) and
40     * the rendering options.
41     */
42    class OSGEARTH_EXPORT Map : public osg::Object
43    {
44    public:
45        META_Object(osgEarth, Map);
46
47        /** Construct a new, empty map. */
48        Map();
49
50        /** Construct a new empty map with options */
51        Map(const MapOptions& options);
52
53    public:
54        /**
55         * Gets this Map's unique ID
56         */
57        UID getUID() const { return _uid; }
58
59        /**
60         * Gets the options governing this map.
61         */
62        const MapOptions& getMapOptions() const { return _mapOptions; }
63
64        /**
65         * Gets the options with which this map was initially created.
66         */
67        const MapOptions& getInitialMapOptions() const { return _initMapOptions; }
68
69        /**
70         * Gets the map's master profile, which defines its SRS and tiling structure.
71         */
72        const Profile* getProfile() const;
73
74        /**
75         * Gets the SRS of the map's profile (convenience)
76         */
77        const SpatialReference* getSRS() const { return _profile.valid() ? _profile->getSRS() : 0L; }
78
79        /**
80         * Gets the SRS of the world (scene)
81         */
82        const SpatialReference* getWorldSRS() const;
83
84        /**
85         * Adds a Layer to the map.
86         */
87        void addLayer(Layer* layer);
88
89        /**
90         * Inserts a Layer at a specific index in the Map.
91         */
92        void insertLayer(Layer* layer, unsigned index);
93
94        /**
95         * Removes a layer from the map.
96         */
97        void removeLayer(Layer* layer);
98
99        /**
100         * Moves a layer to another position in the Map.
101         */
102        void moveLayer(Layer* layer, unsigned index);
103
104        /**
105         * Gets the index of the specified layer, or returns
106         * getNumLayers() if the layer is not found.
107         */
108        unsigned getIndexOfLayer(const Layer* layer) const;
109
110        /**
111         * Copies references of the map layers into the output list.
112         * This method is thread safe. It returns the map revision that was
113         * in effect when the data was copied.
114         */
115        Revision getLayers(LayerVector& out_layers) const;
116
117        /**
118         * Gets the number of layers in the map.
119         */
120        unsigned getNumLayers() const;
121
122        /**
123         * Gets a layer by name.
124         */
125        Layer* getLayerByName(const std::string& name) const;
126
127        template<typename T> T* getLayerByName(const std::string& name) const;
128
129        /**
130         * Gets an image layer by its unique ID.
131         */
132        Layer* getLayerByUID(UID layerUID) const;
133
134        template<typename T> T* getLayerByUID(UID layerUID) const;
135
136        /**
137         * Gets the layer at the specified index.
138         */
139        Layer* getLayerAt(unsigned index) const;
140
141        template<typename T> T* getLayerAt(unsigned index) const;
142
143        /**
144         * Fills the vector with references to all layers of the specified type.
145         */
146        template<typename T>
147        Revision getLayers(std::vector< osg::ref_ptr<T> >& output) const;
148
149        template<typename T>
150        Revision getLayers(osg::MixinVector< osg::ref_ptr<T> >& output) const;
151
152        /**
153         * Gets the first layer of the specified type. This is useful when you
154         * know there in only one layer of the type you are looking for.
155         */
156        template<typename T> T* getLayer() const;
157
158        /**
159         * Adds a map layer callback to this map. This will be notified whenever layers are
160         * added, removed, or re-ordered.
161         */
162        MapCallback* addMapCallback(MapCallback* callback) const;
163
164        /**
165         * Removes a callback previously added with addMapCallback.
166         */
167        void removeMapCallback(MapCallback* callback) const;
168
169        /**
170         * Begin a batch-update operation. Call this if you intend to add multiple
171         * layers at once; then call endUpdate() to complete the operation.
172         * Between calls to beginUpdate() and endUpdate(), Map will not invoke
173         * any callbacks you added wtih addMapCallback.
174         */
175        void beginUpdate();
176
177        /**
178         * Complete a batch update operation that started with a call to
179         * beginUpdate(). Fires all callbacks for operations that occurred
180         * since the call to beginUpdate().
181         */
182        void endUpdate();
183
184        /**
185         * Clear all layers from this map.
186         */
187        void clear();
188
189        /**
190         * Replaces the layers in this Map with layers from the specified Map
191         * (except for terrain mask layers)
192         */
193        void setLayersFromMap( const Map* map );
194
195        /**
196         * Gets the user-provided options structure stored in this map.
197         */
198        const osgDB::Options* getGlobalOptions() const;
199        void setGlobalOptions( const osgDB::Options* options );
200
201        /**
202         * Sets the readable name of this map.
203         */
204        void setMapName( const std::string& name );
205
206        /**
207         * Gets the readable name of this map.
208         */
209        const std::string& getMapName() const { return _name; }
210
211        /**
212         * Sets the Cache for this Map. Set to NULL for no cache.
213         */
214        void setCache( Cache* cache );
215
216        /**
217         * Gets the Cache for this Map
218         */
219        Cache* getCache() const;
220
221        /**
222         * Gets the revision # of the map. The revision # changes every time
223         * you add, remove, or move layers. You can use this to track changes
224         * in the map model (as a alternative to installing a MapCallback).
225         */
226        Revision getDataModelRevision() const;
227
228        /**
229         * Convenience function that returns TRUE if the map cs type is
230         * geocentric.
231         */
232        bool isGeocentric() const;
233
234        /**
235         * Gets the database options associated with this map.
236         */
237        const osgDB::Options* getReadOptions() const { return _readOptions.get(); }
238
239        /**
240         * Gets a version of the map profile without any vertical datum
241         */
242        const Profile* getProfileNoVDatum() const { return _profileNoVDatum.get(); }
243
244        /**
245         * Access to an elevation sampling pool tied to this map
246         */
247        ElevationPool* getElevationPool() const;
248
249        /**
250         * Returns true if data for the given tile key and layers is likely
251         * to generate data quickly. This is used for pager thread pool shunting.
252         */
253        bool isFast(const TileKey& key, const LayerVector& layers) const;
254
255        /**
256         * List of attribution strings to be displayed by the application
257         */
258        void getAttributions(StringSet& attributions) const;
259
260    protected:
261
262        virtual ~Map();
263
264        Map(const Map& rhs, const osg::CopyOp& copy) { }
265
266    private:
267
268        UID _uid;
269        MapOptions _mapOptions;
270        const MapOptions _initMapOptions;
271        std::string _name;
272        LayerVector _layers;
273        mutable MapCallbackList _mapCallbacks;
274        osg::ref_ptr<const osgDB::Options> _globalOptions;
275        mutable Threading::ReadWriteMutex _mapDataMutex;
276        osg::ref_ptr<const Profile> _profile;
277        osg::ref_ptr<const Profile> _profileNoVDatum;
278        Revision _dataModelRevision;
279        osg::ref_ptr<osgDB::Options> _readOptions;
280        osg::ref_ptr<ElevationPool> _elevationPool;
281
282        struct VisibleLayerCB : public VisibleLayerCallback {
283            osg::observer_ptr<Map> _map;
284            VisibleLayerCB(Map*);
285            void onVisibleChanged(VisibleLayer* layer);
286        };
287        osg::ref_ptr<VisibleLayerCB> _visibleLayerCB;
288        friend struct VisibleLayerCB;
289        void notifyLayerVisibleChanged(VisibleLayer*);
290
291        struct LayerCB : public LayerCallback {
292            LayerCB(Map*);
293            osg::observer_ptr<Map> _map;
294            void onEnabledChanged(Layer* layer);
295        };
296        osg::ref_ptr<LayerCallback> _layerCB;
297        friend struct LayerCB;
298        void notifyOnLayerEnabledChanged(Layer*);
299
300        void installLayerCallbacks(Layer*);
301        void uninstallLayerCallbacks(Layer*);
302        void openLayer(Layer*);
303        void closeLayer(Layer*);
304
305
306    private:
307        void ctor();
308        void calculateProfile();
309
310        friend class MapInfo;
311    };
312
313
314
315
316    // Templated inline methods
317
318    template<typename T> T* Map::getLayerByName(const std::string& name) const {
319        return dynamic_cast<T*>(getLayerByName(name));
320    }
321
322    template<typename T> T* Map::getLayerByUID(UID layerUID) const {
323        return dynamic_cast<T*>(getLayerByUID(layerUID));
324    }
325
326    template<typename T> T* Map::getLayerAt(unsigned index) const {
327        return dynamic_cast<T*>(getLayerAt(index));
328    }
329
330    template<typename T>
331    Revision Map::getLayers(std::vector< osg::ref_ptr<T> >& output) const {
332        Threading::ScopedReadLock lock(_mapDataMutex);
333        for (LayerVector::const_iterator i = _layers.begin(); i != _layers.end(); ++i) {
334            T* obj = dynamic_cast<T*>(i->get());
335            if (obj) output.push_back(obj);
336        }
337        return _dataModelRevision;
338    }
339
340    template<typename T>
341    Revision Map::getLayers(osg::MixinVector< osg::ref_ptr<T> >& output) const {
342        Threading::ScopedReadLock lock(_mapDataMutex);
343        for (LayerVector::const_iterator i = _layers.begin(); i != _layers.end(); ++i) {
344            T* obj = dynamic_cast<T*>(i->get());
345            if (obj) output.push_back(obj);
346        }
347        return _dataModelRevision;
348    }
349
350    template<typename T> T* Map::getLayer() const {
351        Threading::ScopedReadLock lock(_mapDataMutex);
352        for (LayerVector::const_iterator i = _layers.begin(); i != _layers.end(); ++i) {
353            T* obj = dynamic_cast<T*>(i->get());
354            if (obj) return obj;
355        }
356        return 0L;
357    }
358}
359
360#endif // OSGEARTH_MAP_H
361