/* -*-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 OSGEARTHFEATURES_FEATURE_SOURCE_INDEX_NODE_H #define OSGEARTHFEATURES_FEATURE_SOURCE_INDEX_NODE_H 1 #include #include #include #include #include #include #include #include #include #include namespace osgEarth { /** * Options for a feature index */ class OSGEARTH_EXPORT FeatureSourceIndexOptions { public: FeatureSourceIndexOptions(const Config& conf =Config()); /** Whether indexing is enabled. */ optional& enabled() { return _enabled; } const optional& enabled() const { return _enabled; } /** Whether to embed the actual Feature objects in the index (instead of * just the FeatureID). This is useful for feature sources that cannot * be queried by ID (e.g., streaming data like TFS) */ optional& embedFeatures() { return _embedFeatures; } const optional& embedFeatures() const { return _embedFeatures; } public: Config getConfig() const; private: optional _enabled; optional _embedFeatures; }; struct RefIDPair : public osg::Referenced { RefIDPair(FeatureID fid, ObjectID oid) : _fid(fid), _oid(oid) { } FeatureID _fid; ObjectID _oid; }; /** * Internal class that maintains a feature index for a single feature source. * Internal - not exported! */ class OSGEARTH_EXPORT FeatureSourceIndex : public FeatureIndex { public: FeatureSourceIndex(FeatureSource* source, ObjectIndex* masterIndex, const FeatureSourceIndexOptions& options); /** FeatureSource behind this index */ FeatureSource* getFeatureSource() { return _featureSource.get(); } public: // FeatureIndex Feature* getFeature(ObjectID oid) const; ObjectID getObjectID(FeatureID fid) const; int size() const { return _fids.size(); } public: // Functions called by FeatureSourceIndexNode RefIDPair* tagDrawable (osg::Drawable* drawable, Feature* feature); RefIDPair* tagAllDrawables(osg::Node* node, Feature* feature); RefIDPair* tagNode (osg::Node* node, Feature* feature); RefIDPair* tagRange (osg::Drawable* drawable, Feature* feature, unsigned int start, unsigned int count); // removes a collection of FIDs from the index. If the refcount goes to zero, // remove it from the master index as well. template void removeFIDs(InputIter first, InputIter last) { std::lock_guard lock(_mutex); for(InputIter fid = first; fid != last; ++fid ) { FID_to_RefIDPair::iterator f = _fids.find( *fid ); if ( f != _fids.end() && f->second->referenceCount() == 1 ) { ObjectID oid = f->second->_oid; _oids.erase( oid ); _fids.erase( f ); _embeddedFeatures.erase( *fid ); if ( _masterIndex.valid() ) _masterIndex->remove( oid ); } } } public: // types using OID_to_OID = std::unordered_map; using OID_to_FID = std::unordered_map; // was OIDMap using FID_to_RefIDPair = std::unordered_map>; // was FIDMap using FID_to_Feature = std::unordered_map>; // was FeatureMap protected: virtual ~FeatureSourceIndex(); private: osg::ref_ptr _featureSource; osg::ref_ptr _masterIndex; FeatureSourceIndexOptions _options; bool _embed; mutable std::mutex _mutex; OID_to_FID _oids; FID_to_RefIDPair _fids; FID_to_Feature _embeddedFeatures; void update(osg::Drawable*, OID_to_OID&, const FID_to_RefIDPair&, FID_to_RefIDPair&); void update(osg::Node*, OID_to_OID&, const FID_to_RefIDPair&, FID_to_RefIDPair&); friend class FeatureSourceIndexNode; }; /** * Node that houses a FeatureSourceIndex, so that it can un-register index * entries when it pages out. */ class OSGEARTH_EXPORT FeatureSourceIndexNode : public osg::Group, public FeatureIndexBuilder { public: META_Node(osgEarth, FeatureSourceIndexNode); using OID_to_OID = std::unordered_map; using OID_to_FID = std::unordered_map; // was OIDMap using FID_to_RefIDPair = std::unordered_map>; // was FIDMap using FID_to_Feature = std::unordered_map>; // was FeatureMap /** default ctor */ FeatureSourceIndexNode(); /** Construct with an index */ FeatureSourceIndexNode(FeatureSourceIndex* index); /** Copy */ FeatureSourceIndexNode(const FeatureSourceIndexNode& rhs, const osg::CopyOp& copy); /** The index referenced by this node. */ void setIndex(FeatureSourceIndex* index) { _index = index; } FeatureSourceIndex* getIndex() { return _index.get(); } /** Fetches the entire set of FIDs registered with the index by this node. */ bool getAllFIDs(std::vector& output) const; /** Finds a FeatureSourceIndexNode in a scene graph. */ static FeatureSourceIndexNode* get(osg::Node* graph); public: // FeatureIndexBuilder ObjectID tagDrawable (osg::Drawable* drawable, Feature* feature); ObjectID tagAllDrawables(osg::Node* node, Feature* feature); ObjectID tagNode (osg::Node* node, Feature* feature); ObjectID tagRange (osg::Drawable* drawable, Feature* feature, unsigned int start, unsigned int count); public: // To support serialization only - do not use directly const FID_to_RefIDPair& getFIDMap() const { return _fids; } void setFIDMap(const FID_to_RefIDPair& fids); void reIndex(OID_to_OID&); void reIndexDrawable(osg::Drawable* drawable, OID_to_OID& oldNew, FID_to_RefIDPair& newFIDMap); void reIndexNode(osg::Node* node, OID_to_OID& oldNew, FID_to_RefIDPair& newFIDMap); /** * Call this after deserializing a scene graph that may contain FeatureSourceIndexNodes. * It will locate them, assign the index, and reconsistute the object IDs in the index. */ static void reconstitute(osg::Node* graph, FeatureSourceIndex* index); protected: /** dtor - unregisters any FIDs added by this node. */ virtual ~FeatureSourceIndexNode(); private: // serializable FID_to_RefIDPair _fids; private: // transient osg::ref_ptr _index; }; } // namespace osgEarth OSGEARTH_SPECIALIZE_CONFIG(osgEarth::FeatureSourceIndexOptions); #endif // OSGEARTHFEATURES_FEATURE_SOURCE_INDEX_NODE_H