/* -*-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_ELEVATION_TERRAIN_LAYER_H #define OSGEARTH_ELEVATION_TERRAIN_LAYER_H 1 #include #include namespace osgEarth { /** * A map terrain layer containing elevation grid heightfields. */ class OSGEARTH_EXPORT ElevationLayer : public TileLayer { public: class OSGEARTH_EXPORT Options : public TileLayer::Options { public: META_LayerOptions(osgEarth, Options, TileLayer::Options); OE_OPTION(std::string, verticalDatum); OE_OPTION(bool, offset, false); OE_OPTION(ElevationNoDataPolicy, noDataPolicy, NODATA_INTERPOLATE); virtual Config getConfig() const; private: void fromConfig( const Config& conf ); }; public: META_Layer_Abstract(osgEarth, ElevationLayer, Options, TileLayer); //! Layer callbacks class OSGEARTH_EXPORT Callback : public osg::Referenced { public: //! Called when new data is created. This callback fires //! before the data is cached, and does NOT fire if the data //! was read from a cache. //! NOTE: This may be invoked from a worker thread. Use caution. virtual void onCreate(const TileKey&, GeoHeightField&) { } }; //! Vertical data identifier (options) void setVerticalDatum(const std::string& value); const std::string& getVerticalDatum() const; //! Whether this layer contains offsets instead of absolute elevation heights void setOffset(bool value); bool getOffset() const; bool isOffset() const { return getOffset(); } //! Poly for handling "no-data" elevation values void setNoDataPolicy(const ElevationNoDataPolicy& value); const ElevationNoDataPolicy& getNoDataPolicy() const; //! Override from VisibleLayer //virtual void setVisible(bool value); public: // methods /** * Creates a GeoHeightField for this layer that corresponds to the extents and LOD * in the specified TileKey. The returned HeightField will always match the geospatial * extents of that TileKey. * * @param key TileKey for which to create a heightfield. */ GeoHeightField createHeightField(const TileKey& key); /** * Creates a GeoHeightField for this layer that corresponds to the extents and LOD * in the specified TileKey. The returned HeightField will always match the geospatial * extents of that TileKey. * * @param key TileKey for which to create a heightfield. * @param progress Callback for tracking progress and cancelation */ GeoHeightField createHeightField(const TileKey& key, ProgressCallback* progress); /** * Writes a height field for the specified key, if writing is * supported and the layer was opened with openForWriting. */ Status writeHeightField(const TileKey& key, const osg::HeightField* hf, ProgressCallback* progress) const; //! Install a user callback void addCallback(Callback* callback); //! Remove a user callback void removeCallback(Callback* callback); protected: // Layer virtual void init() override; protected: // TileLayer //! Override aspects of the layer Profile as needed virtual void applyProfileOverrides(osg::ref_ptr& inOutProfile) const override; protected: // ElevationLayer //! Entry point for createHeightField GeoHeightField createHeightFieldInKeyProfile(const TileKey& key, ProgressCallback* progress); //! Subclass overrides this to generate image data for the key. //! The key will always be in the same profile as the layer. virtual GeoHeightField createHeightFieldImplementation(const TileKey&, ProgressCallback* progress) const { return GeoHeightField::INVALID; } //! Subalss can override this to enable writing heightfields. virtual Status writeHeightFieldImplementation( const TileKey& key, const osg::HeightField* hf, ProgressCallback* progress) const; virtual ~ElevationLayer() { } private: void assembleHeightField( const TileKey& key, osg::ref_ptr& out_hf, ProgressCallback* progress) const; void normalizeNoDataValues(osg::HeightField* hf) const; void invoke_onCreate(const TileKey&, GeoHeightField&); typedef std::vector< osg::ref_ptr > Callbacks; Threading::Mutexed _callbacks; Gate _sentry; }; /** * Vector of elevation layers, with added methods. */ class OSGEARTH_EXPORT ElevationLayerVector : public osg::MixinVector< osg::ref_ptr > { public: /** * Populates an existing height field (hf must already exist) with height * values from the elevation layers. * * @param hf Heightfield object to populate; must be pre-allocated * @param resolutions If non-null, populate with resolution of each sample * @param key Tilekey for which to populate * @param haeProfile Optional geodetic (no vdatum) tiling profile to use * @param interpolation Elevation interpolation technique * @param progress Optional progress callback for cancelation * @return True if "hf" was populated, false if no real data was available for key */ bool populateHeightField( osg::HeightField* hf, std::vector* resolutions, const TileKey& key, const Profile* haeProfile, RasterInterpolation interpolation, ProgressCallback* progress ) const; public: /** Default ctor */ ElevationLayerVector(); /** Copy ctor */ ElevationLayerVector(const ElevationLayerVector& rhs); }; } // namespace osgEarth OSGEARTH_SPECIALIZE_CONFIG(osgEarth::ElevationLayer::Options); #endif // OSGEARTH_ELEVATION_TERRAIN_LAYER_H