DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarth/ElevationPool

331 lines
12 KiB
Plaintext
Raw Normal View History

2024-12-24 23:49:36 +00:00
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2008-2016 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 <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_ELEVATION_POOL_H
#define OSGEARTH_ELEVATION_POOL_H
#include <osgEarth/Common>
#include <osgEarth/Elevation>
#include <osgEarth/ElevationLayer>
#include <osgEarth/GeoData>
#include <osgEarth/TileKey>
#include <osgEarth/Threading>
#include <osgEarth/Containers>
#include <osgEarth/MapCallback>
#include <osg/Timer>
#include <unordered_map>
#include <queue>
#include <atomic>
namespace osgEarth
{
/**
* Stores pointers to elevation data wherever it might exist
* so we can quickly access it for queries.
*/
class OSGEARTH_EXPORT ElevationPool : public osg::Referenced
{
public:
using WeakPointer = osg::observer_ptr<ElevationTexture>;
using Pointer = osg::ref_ptr<ElevationTexture>;
using WeakLUT = std::unordered_map<Internal::RevElevationKey, WeakPointer>;
private:
struct OSGEARTH_EXPORT StrongLRU {
StrongLRU(unsigned maxSize=64u);
Mutexed<std::queue<Pointer>> _lru;
unsigned _maxSize;
void push(Pointer& p);
void clear();
};
public:
//! User data that a client can use to speed up queries in
//! a local geographic area or sample a custom set of layers.
class OSGEARTH_EXPORT WorkingSet
{
public:
//! Construct a new local working set cache.
//! @param size Cache size
WorkingSet(unsigned size =32u);
//! Assign a specific set of elevation layer to use
//! for sampling. Usually this is unnecessary as the Pool
//! will synchronize with the map set by setMap, but you
//! may want to use a custom Pool with a specific subset
//! of query layers.
//! @param layers Set of elevation layers to use
void setElevationLayers(const ElevationLayerVector& layers) {
_elevationLayers = layers;
}
//! Invalidate the cache.
void clear();
private:
StrongLRU _lru;
ElevationLayerVector _elevationLayers;
friend class ElevationPool;
};
/**
* Object for doing lots of queries in a localized area.
* Call prepareEnvelope to initialize one.
*/
class OSGEARTH_EXPORT Envelope
{
public:
//! For each point in an array of points, sample the elevation and store
//! the result in the Z coordinate. Input points must be in the map's SRS.
//! @param begin Iterator pointing to beginning of point array
//! @param end Iterator pointing to end of point array
//! @param progress Optional progress callback (can be nullptr)
//! @param failValue Value to store in Z if the sampling fails
//! @return Number of valid elevations sampled, or -1 if there was an error
int sampleMapCoords(
std::vector<osg::Vec3d>::iterator begin,
std::vector<osg::Vec3d>::iterator end,
ProgressCallback* progress,
float failValue = NO_DATA_VALUE);
public:
// internal
using QuickCache = vector_map<
Internal::RevElevationKey,
osg::ref_ptr<ElevationTexture>>;
// internal
struct QuickSampleVars {
double sizeS, sizeT;
double s, t;
double s0, s1, smix;
double t0, t1, tmix;
osg::Vec4f UL, UR, LL, LR, TOP, BOT;
};
private:
Internal::RevElevationKey _key;
QuickCache _cache;
QuickSampleVars _vars;
double _pw, _ph, _pxmin, _pymin;
osg::ref_ptr<ElevationTexture> _raster;
int _lod;
unsigned _tw, _th;
WorkingSet* _ws;
WorkingSet _default_ws;
osg::ref_ptr<const Map> _map;
osg::ref_ptr<const Profile> _profile;
ElevationPool* _pool;
friend class ElevationPool;
};
public:
//! Construct the elevation pool
ElevationPool();
//! Assign map to the pool. Required.
void setMap(const Map* map);
//! Sample the map's elevation at a point.
//! @param p Point at which to sample
//! @param ws Optional working set (can be NULL)
//! @param progress Optional progress callback
ElevationSample getSample(
const GeoPoint& p,
WorkingSet* ws,
ProgressCallback* progress =nullptr);
//! Sample the map's elevation at a point.
//! @param p Point at which to sample
//! @param resolution Resolution at which to attempt to sample (in point srs)
//! @param ws Optional working set (can be NULL)
//! @param progress Optional progress callback
ElevationSample getSample(
const GeoPoint& p,
const Distance& resolution,
WorkingSet* ws,
ProgressCallback* progress =nullptr);
//! Extract a complete tile of elevation data
//! @param key TileKey or data to extact
//! @param acceptLowerRes Return a lower resolution tile if the requested one isn't available
//! @param out_elev Output elevation texture tile
//! @param ws Optional working set (can be nullptr)
//! @param progress Optional progress callback (can be nullptr)
//! @return true upon success, false upon failure
bool getTile(
const TileKey& key,
bool acceptLowerRes,
osg::ref_ptr<ElevationTexture>& out_elev,
WorkingSet* ws,
ProgressCallback* progress);
//! For each point in an array of points, sample the elevation and store
//! the result in the Z coordinate. Input points must be in the map's SRS,
//! and the sampling resolution is taken from the W coordinate.
//! @param begin Iterator pointing to beginning of point array
//! @param end Iterator pointing to end of point array
//! @param ws Optional working set (local cache, can be nullptr)
//! @param progress Optional progress callback (can be nullptr)
//! @param failValue Value to store in Z if the sampling fails
//! @return Number of valid elevations sampled, or -1 if there was an error
int sampleMapCoords(
std::vector<osg::Vec4d>::iterator begin,
std::vector<osg::Vec4d>::iterator end,
WorkingSet* ws,
ProgressCallback* progress,
float failValue =NO_DATA_VALUE);
//! For each point in an array of points, sample the elevation and store
//! the result in the Z coordinate. Input points must be in the map's SRS.
//! @param begin Iterator pointing to beginning of point array
//! @param end Iterator pointing to end of point array
//! @param resolution Resolution at which to sample the points
//! @param ws Optional working set (local cache, can be nullptr)
//! @param progress Optional progress callback (can be nullptr)
//! @param failValue Value to store in Z if the sampling fails
//! @return Number of valid elevations sampled, or -1 if there was an error
int sampleMapCoords(
std::vector<osg::Vec3d>::iterator begin,
std::vector<osg::Vec3d>::iterator end,
const Distance& resolution,
WorkingSet* ws,
ProgressCallback* progress,
float failValue = NO_DATA_VALUE);
//! Creates an envelope for sampling lots of points in a localized region
//! @param out Created envelope (output)
//! @param refPoint Reference point near which you intend to sample points
//! @param resolution Resolution at which to intend to sample points
//! @param ws Optional working set (can be nullptr)
bool prepareEnvelope(
Envelope& out,
const GeoPoint& refPoint,
const Distance& resolution,
WorkingSet* ws =nullptr);
protected:
//! Destructor
virtual ~ElevationPool();
private:
bool needsRefresh();
// weak pointer to the map from whence this pool came
osg::observer_ptr<const Map> _map;
// stores weak pointers to elevation textures wherever they may exist
// elsewhere in the system, including the local L2 LRU.
WeakLUT _globalLUT;
Threading::ReadWriteMutex _globalLUTMutex;
// LRU container that stores the last N strong references to accessed tiles.
// Not used directly - just used to hold ref_ptrs to things so they stay
// alive in the global LUT (see above).
StrongLRU _L2;
// internal: spatial index of data extents
void* _index;
// elevation tile size
unsigned _tileSize;
//WorkingSet* _L2;
size_t _elevationHash;
int _mapRevision;
Threading::ReadWriteMutex _mutex;
ElevationLayerVector _elevationLayers;
size_t getElevationHash(WorkingSet*) const;
void sync(const Map*, WorkingSet*);
void refresh(const Map*);
ElevationSample getSample(
const GeoPoint& p,
unsigned maxLOD,
const Map* map,
WorkingSet* ws,
ProgressCallback* progress);
//! Best LOD this a point, or -1 if no data in index
int getLOD(double x, double y) const;
osg::ref_ptr<ElevationTexture> getOrCreateRaster(
const Internal::RevElevationKey& key,
const Map* map,
bool acceptLowerRes,
WorkingSet* ws,
ProgressCallback* progress);
bool findExistingRaster(
const Internal::RevElevationKey& key,
WorkingSet* ws,
osg::ref_ptr<ElevationTexture>& result,
bool* fromWorkingSet,
bool* fromL2Cache,
bool* fromGlobalWeakLUT);
};
/**
* Utility to run elevation queries in the background.
*/
class OSGEARTH_EXPORT AsyncElevationSampler
{
public:
//! Construct a new sampler
//! @param map Map the sampler will use to sample elevation data
//! @param threads Number of threads the sampler should use
AsyncElevationSampler(
const Map* map,
unsigned threads =0u);
//! Destructor
virtual ~AsyncElevationSampler() { }
//! Sample elevation at a point at highest available resolution
//! @param p Point at which to sample terrain elevation
//! @return Future result of the sample
jobs::future<ElevationSample> getSample(
const GeoPoint& p);
//! Sample elevation at a point and a target resolution
//! @param p Point at which to sample terrain elevation
//! @param resolution Resolution at which to sample terrain
//! @return Future result of the sample
jobs::future<ElevationSample> getSample(
const GeoPoint& p,
const Distance& resolution);
protected:
osg::observer_ptr<const Map> _map;
ElevationPool::WorkingSet _ws;
jobs::jobpool* _arena;
};
} // namespace
#endif // OSGEARTH_ELEVATION_POOL_H