/* --*-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_MODEL_GRAPH_H #define OSGEARTHFEATURES_FEATURE_MODEL_GRAPH_H 1 #include #include #include #include #include #include #include #include #include #include namespace osgEarth { namespace Util { class Session; /** * A scene graph that renders feature data. * This class will handle all the internals of selecting features, gridding feature * data if required, and sorting features based on style. Then for each cell and each * style, it will invoke the FeatureNodeFactory to create the actual data for each set. */ class OSGEARTH_EXPORT FeatureModelGraph : public osg::Group { public: /** * Constructs a new model graph. * * @param session * Session under which to create elements in this graph * @param options * Model source options * @param factory * Node factory that will be invoked to compile feature data into nodes */ FeatureModelGraph(const FeatureModelOptions& options); //! Set a scene graph callback host for this FMG void setSceneGraphCallbacks(SceneGraphCallbacks* callbacks); //! Sets the object that creates geometry nodes. void setNodeFactory(FeatureNodeFactory* factory); FeatureNodeFactory* getNodeFactory() const { return _factory.get(); } //! Sets the style sheet to use to render features void setStyleSheet(StyleSheet* styles); //! Session associated with this feature graph. void setSession(Session* session); const Session* getSession() const; //! Min visible range void setMinRange(float value); //! Max visible range void setMaxRange(float value); //! Whether to attempt to use NVGL extensions void setUseNVGL(bool value); //! Initialized the graph after setting all parameters. Status open(); //! Shut down the service, notifying any active loading //! threads to stop working void shutdown(); void setDone() { shutdown(); } //! Returns true is open() was called, false if shutdown was called bool isActive() const { return _isActive; } /** * Loads and returns a subnode. Used internally for paging. */ osg::ref_ptr load( unsigned lod, unsigned tileX, unsigned tileY, const std::string& uri, const osgDB::Options* readOptions); /** * Access to the features levels */ const std::vector& getLevels() const { return _lodmap; }; //! Set the name of the object that owns this graph (for debugging) void setOwnerName(const std::string& name); const std::string& getOwnerName() const { return _ownerName; } std::shared_ptr loadedTiles; public: // osg::Node virtual void traverse(osg::NodeVisitor& nv); protected: virtual ~FeatureModelGraph(); osg::ref_ptr setupPaging(); osg::ref_ptr buildTile( const FeatureLevel& level, const GeoExtent& extent, const TileKey* key, const osgDB::Options* readOptions); osg::Group* build( const Style& baseStyle, const Query& baseQuery, const GeoExtent& extent, FeatureIndexBuilder* index, const osgDB::Options* readOptions, ProgressCallback* progress); private: //void ctor(); osg::Group* createStyleGroup( const Style& style, const Query& query, FeatureIndexBuilder* index, const osgDB::Options* readOptions, ProgressCallback* progress); osg::Group* createStyleGroup( const Style& style, FeatureList& workingSet, const FilterContext& contextPrototype, const osgDB::Options* readOptions, const Query& query); void buildStyleGroups( const StyleSelector* selector, const Query& baseQuery, FeatureIndexBuilder* index, osg::Group* parent, const osgDB::Options* readOptions, ProgressCallback* progress); void queryAndSortIntoStyleGroups( const Query& query, const StringExpression& styleExpr, FeatureIndexBuilder* index, osg::Group* parent, const osgDB::Options* readOptions, ProgressCallback* progress); osg::Group* getOrCreateStyleGroupFromFactory( const Style& style); osg::BoundingSphered getBoundInWorldCoords( const GeoExtent& extent, const Profile* tilingProfile =0L) const; void buildSubTilePagedLODs( unsigned lod, unsigned tileX, unsigned tileY, osg::Group* parent, const osgDB::Options* readOptions); osg::Group* readTileFromCache( const std::string& cacheKey, const osgDB::Options* readOptions); bool writeTileToCache( const std::string& cacheKey, osg::Group* tile, const osgDB::Options* readOptions); void redraw(); private: std::string _ownerName; bool _isActive; FeatureModelOptions _options; osg::ref_ptr _factory; osg::ref_ptr _session; osg::ref_ptr _styleSheet; std::set _blacklist; Threading::ReadWriteMutex _blacklistMutex; GeoExtent _usableFeatureExtent; bool _featureExtentClamped; GeoExtent _usableMapExtent; osg::BoundingSphered _fullWorldBound; bool _useTiledSource; std::vector _lodmap; RecursiveMutex _redrawMutex; optional _minRange; optional _maxRange; osg::ref_ptr _textures; mutable std::vector _texturesCache; mutable std::mutex _texturesCacheMutex; std::atomic_int _cacheReads; std::atomic_int _cacheHits; osg::ref_ptr _defaultFileLocationCallback; osg::observer_ptr _modelSource; osg::ref_ptr _featureIndex; osg::ref_ptr _sgCallbacks; osg::ref_ptr _nodeCachingImageCache; void runPreMergeOperations(osg::Node* node); void runPostMergeOperations(osg::Node* node); void applyRenderSymbology(const Style& style, osg::Node* node); bool createOrUpdateNode(FeatureCursor*, const Style&, FilterContext&, const osgDB::Options*, osg::ref_ptr& output, const Query& query); //osg::ref_ptr createCursor(FeatureSource* fs, FilterContext& cx, const Query& query, ProgressCallback* progress) const; FeatureFilterChain _filterChain; }; } } #endif // OSGEARTHFEATURES_FEATURE_MODEL_GRAPH_H