DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarth/GeoData
2024-12-25 07:49:36 +08:00

985 lines
32 KiB
C++

/* -*-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 <http://www.gnu.org/licenses/>
*/
#pragma once
#include <osgEarth/Common>
#include <osgEarth/GeoCommon>
#include <osgEarth/Bounds>
#include <osgEarth/SpatialReference>
#include <osgEarth/ImageUtils>
#include <osgEarth/Status>
#include <osgEarth/Threading>
#include <osg/Referenced>
#include <osg/Image>
#include <osg/Shape>
#include <unordered_map>
namespace osg
{
class Camera;
class Polytope;
}
namespace osgEarth
{
class TerrainResolver;
class GeoExtent;
/**
* A georeferenced 3D point.
*/
class OSGEARTH_EXPORT GeoPoint
{
public:
/**
* Constructs a GeoPoint.
*/
GeoPoint(
const SpatialReference* srs,
double x,
double y,
double z,
const AltitudeMode& mode );
/**
* Constructs a GeoPoint with an absolute Z.
*/
GeoPoint(
const SpatialReference* srs,
double x,
double y,
double z );
/**
* Constructs a GeoPoint with X and Y coordinates. The Z defaults
* to zero with an ALTMODE_RELATIVE altitude mode (i.e., 0 meters
* above the terrain).
*/
GeoPoint(
const SpatialReference* srs,
double x,
double y );
/**
* Constructs a GeoPoint from a vec3.
*/
GeoPoint(
const SpatialReference* srs,
const osg::Vec3d& xyz,
const AltitudeMode& mode );
/**
* Constructs a GeoPoint from a vec3 with absolute Z.
*/
GeoPoint(
const SpatialReference* srs,
const osg::Vec3d& xyz);
/**
* Constructs a new GeoPoint by transforming an existing GeoPoint into
* the specified spatial reference.
*/
GeoPoint(
const SpatialReference* srs,
const GeoPoint& rhs );
/**
* Copy constructor
*/
GeoPoint(const GeoPoint& rhs);
/**
* Constructs an empty (and invalid) geopoint.
*/
GeoPoint();
/**
* Constructs a GeoPoint at 0,0,0 absolute.
*/
GeoPoint(const SpatialReference* srs);
/**
* Constructs a geopoint from serialization
*/
GeoPoint( const Config& conf, const SpatialReference* srs =0L );
/** dtor */
virtual ~GeoPoint() { }
/**
* Sets the SRS and coords
*/
void set(
const SpatialReference* srs,
const osg::Vec3d& xyz,
const AltitudeMode& mode );
void set(
const SpatialReference* srs,
double x,
double y,
double z,
const AltitudeMode& mode );
// component getter/setters
double& x() { return _p.x(); }
double x() const { return _p.x(); }
double& y() { return _p.y(); }
double y() const { return _p.y(); }
double& z() { return _p.z(); }
double z() const { return _p.z(); }
double& alt() { return _p.z(); }
double alt() const { return _p.z(); }
osg::Vec3d& vec3d() { return _p; }
const osg::Vec3d& vec3d() const { return _p; }
const SpatialReference* getSRS() const { return _srs.get(); }
/**
* AltitudeMode reflects whether the Z coordinate is absolute with
* respect to MSL or relative to the terrain elevation at that
* point. When using relative points, GeoPoint usually requires
* access to a TerrainProvider in order to resolve the altitude.
*/
AltitudeMode& altitudeMode() { return _altMode; }
const AltitudeMode& altitudeMode() const { return _altMode; }
bool isRelative() const { return _altMode == ALTMODE_RELATIVE; }
bool isAbsolute() const { return _altMode == ALTMODE_ABSOLUTE; }
/**
* Returns a copy of this geopoint transformed into another SRS.
*/
GeoPoint transform(const SpatialReference* outSRS) const;
/**
* Transforms this geopoint into another SRS.
*/
bool transform(const SpatialReference* outSRS, GeoPoint& output) const;
/**
* Transforms this point in place to another SRS.
*/
bool transformInPlace(const SpatialReference* srs);
/**
* Transforms this geopoint's Z coordinate (in place)
*/
bool transformZ(const AltitudeMode& altMode, const TerrainResolver* t );
/**
* Transforms and returns the geopoints Z coordinate.
*/
bool transformZ(const AltitudeMode& altMode, const TerrainResolver* t, double& out_z) const;
//! Transforms a resolution distance to a cartesian value.
Distance transformResolution(const Distance& d, const UnitsType& outUnits) const;
/**
* Transforms this geopoint's Z to be absolute w.r.t. the vertical datum
*/
bool makeAbsolute(const TerrainResolver* t) { return transformZ(ALTMODE_ABSOLUTE, t); }
/**
* Transforms this geopoint's Z to be terrain-relative.
*/
bool makeRelative(const TerrainResolver* t) { return transformZ(ALTMODE_RELATIVE, t); }
/**
* Transforms this GeoPoint to geographic (lat/long) coords in place.
*/
bool makeGeographic();
/**
* Outputs world coordinates corresponding to this point. If the point
* is ALTMODE_RELATIVE, this will fail because there's no way to resolve
* the actual Z coordinate. Use the variant of toWorld that takes a
* Terrain* instead.
*/
bool toWorld( osg::Vec3d& out_world ) const;
/**
* Outputs world coordinates corresponding to this point, passing in a Terrain
* object that will be used if the point needs to be converted to absolute
* altitude
*/
bool toWorld( osg::Vec3d& out_world, const TerrainResolver* terrain ) const;
/**
* Converts world coordinates into a geopoint
*/
bool fromWorld(const SpatialReference* srs, const osg::Vec3d& world);
/**
* geopoint into absolute world coords.
*/
bool createLocalToWorld( osg::Matrixd& out_local2world ) const;
/**
* Outputs a matrix that will transform absolute world coordiantes so they are
* localized into a local tangent place around this geopoint.
*/
bool createWorldToLocal( osg::Matrixd& out_world2local ) const;
/**
* Converts this point to the same point in a local tangent plane.
*/
GeoPoint toLocalTangentPlane() const;
/**
* Outputs an "up" vector corresponding to the given point. The up vector
* is orthogonal to a local tangent plane at that point on the map.
*/
bool createWorldUpVector( osg::Vec3d& out_up ) const;
//! Geodesic distance from this point to another.
//! This is the distance along the real-world ellipsoidal surface
//! of the Earth (or other body), regardless of map projection.
//! It does not account for Z/altitude.
//! @param rhs Other point
//! @return Geodesic distance between the two points
Distance geodesicDistanceTo(const GeoPoint& rhs) const;
/**
* @deprecated - ambiguous, will be removed. Use geodesicDistanceTo() or toWorld()/length instead.
* Calculates the distance in meters from this geopoint to another.
*/
double distanceTo(const GeoPoint& rhs) const;
/**
* Interpolates a point between this point and another point
* using the parameter t [0..1].
*/
GeoPoint interpolate(const GeoPoint& rhs, double t) const;
//! Convert this point to screen coordinates.
osg::Vec2d toScreen(const osg::Camera* camera) const;
//! Convenience function to return xy units
const UnitsType& getXYUnits() const;
bool operator == (const GeoPoint& rhs) const;
bool operator != (const GeoPoint& rhs) const { return !operator==(rhs); }
bool isValid() const { return _srs.valid(); }
Config getConfig() const;
/**
* Represent this point as a string
*/
std::string toString() const;
public:
static GeoPoint INVALID;
protected:
osg::Vec3d _p;
osg::ref_ptr<const SpatialReference> _srs;
AltitudeMode _altMode;
};
/**
* A simple circular bounding area consiting of a GeoPoint and a linear radius.
*/
class OSGEARTH_EXPORT GeoCircle
{
public:
/** Construct an INVALID GeoCircle */
GeoCircle();
/** Copy another GoeCircle */
GeoCircle(const GeoCircle& rhs);
/** Construct a new GeoCircle */
GeoCircle(
const GeoPoint& center,
double radius );
virtual ~GeoCircle() { }
/** The center point of the circle */
const GeoPoint& getCenter() const { return _center; }
void setCenter( const GeoPoint& value ) { _center = value; }
/** Circle's radius, in linear map units (or meters for a geographic SRS) */
double getRadius() const { return _radius; }
void setRadius( double value ) { _radius = value; }
/** SRS of the center point */
const SpatialReference* getSRS() const { return _center.getSRS(); }
/** equality test */
bool operator == ( const GeoCircle& rhs ) const;
/** inequality test */
bool operator != ( const GeoCircle& rhs ) const { return !operator==(rhs); }
/** validity test */
bool isValid() const { return _center.isValid() && _radius > 0.0; }
/** transform the GeoCircle to another SRS */
GeoCircle transform( const SpatialReference* srs ) const;
/** transform the GeoCircle to another SRS */
bool transform( const SpatialReference* srs, GeoCircle& out_circle ) const;
/** does this GeoCircle intersect another? */
bool intersects( const GeoCircle& rhs ) const;
public:
static GeoCircle INVALID;
protected:
GeoPoint _center;
double _radius;
};
}
OSGEARTH_SPECIALIZE_CONFIG(osgEarth::GeoPoint);
namespace osgEarth
{
/**
* An axis-aligned geospatial extent. A bounding box that is aligned with a
* spatial reference's coordinate system.
*/
class OSGEARTH_EXPORT GeoExtent
{
public:
/** Default ctor creates an "invalid" extent */
GeoExtent();
/** Contructs a valid extent */
GeoExtent(
const SpatialReference* srs,
double west, double south,
double east, double north);
/** Contructs an invalid extent that you can grow with the expandToInclude method */
GeoExtent(const SpatialReference* srs);
/** Copy ctor */
GeoExtent(const GeoExtent& rhs);
/** create from Bounds object */
GeoExtent(const SpatialReference* srs, const Bounds& bounds);
/** dtor */
virtual ~GeoExtent() { }
//! Set from the SW and NE corners.
void set(double west, double south, double east, double north);
bool operator == (const GeoExtent& rhs) const;
bool operator != (const GeoExtent& rhs) const;
/** Gets the spatial reference system underlying this extent. */
const SpatialReference* getSRS() const { return _srs.get(); }
//! Coordinates of the bounding edges, normalized for the lat/long frame if necessary
inline double west() const;
inline double east() const;
inline double south() const;
inline double north() const;
//! Coordinates of the bounds, NOT normalized to the lat/long frame.
inline double xMin() const { return _west; }
inline double xMax() const { return _west + _width; }
inline double yMin() const { return _south; }
inline double yMax() const { return _south + _height; }
//! East-to-west span of the extent
inline double width() const { return _width; }
//! East-to-est span in specified units
double width(const UnitsType& units) const;
//! North-to-south span of the extent
inline double height() const { return _height; }
//! North-to-south span in specified units
double height(const UnitsType& units) const;
//! Gets the centroid of the bounds
GeoPoint getCentroid() const;
//! Legacy @deprecated
bool getCentroid(double& out_x, double& out_y) const;
//! True if the extent is geographic and crosses the 180 degree meridian.
bool crossesAntimeridian() const;
//! Raw bounds of the extent (unnormalized)
void getBounds(double& xmin, double& ymin, double& xmax, double& ymax) const;
/** True if this object defines a real, valid extent with positive area */
inline bool isValid() const
{
return _srs.valid() && _width >= 0.0 && _height >= 0.0;
}
inline bool isInvalid() const { return !isValid(); }
/**
* If this extent crosses the international date line, populates two extents, one for
* each side, and returns true. Otherwise returns false and leaves the reference
* parameters untouched.
*/
bool splitAcrossAntimeridian(GeoExtent& first, GeoExtent& second) const;
/**
* Returns this extent transformed into another spatial reference.
*
* NOTE! It is possible that the target SRS will not be able to accomadate the
* extents of the source SRS. (For example, transforming a full WGS84 extent
* to Mercator will resultin an error since Mercator does not cover the entire
* globe.) Consider using Profile:clampAndTransformExtent() instead of using
* this method directly.
*/
GeoExtent transform(const SpatialReference* to_srs) const;
/**
* Same as transform(srs) but puts the result in the output extent
*/
bool transform(const SpatialReference* to_srs, GeoExtent& output) const;
/**
* Returns true if the specified point falls within the bounds of the extent.
*
* @param x, y
* Coordinates to test
* @param xy_srs
* SRS of input x and y coordinates; if null, the method assumes x and y
* are in the same SRS as this object.
*/
bool contains(double x, double y, const SpatialReference* srs = 0L) const;
template<typename VEC>
bool contains(const VEC& a, const SpatialReference* srs = nullptr) const {
return contains(a.x(), a.y(), srs);
}
/**
* Returns true if the point falls within this extent.
*/
bool contains(const GeoPoint& rhs) const;
/**
* Returns true if this extent fully contains another extent.
*/
bool contains(const GeoExtent& rhs) const;
/**
* Returns true if this extent fully contains the target bounds.
*/
bool contains(const Bounds& rhs) const;
/**
* Returns TRUE if this extent intersects another extent.
* @param[in ] rhs Extent against which to perform intersect test
* @param[in ] checkSRS If false, assume the extents have the same SRS (don't check).
*/
bool intersects(const GeoExtent& rhs, bool checkSRS = true) const;
/**
* Copy of the anonymous bounding box
*/
Bounds bounds() const;
/**
* Gets a geo circle bounding this extent.
*/
GeoCircle computeBoundingGeoCircle() const;
/**
* Grow this extent to include the specified point (which is assumed to be
* in the extent's SRS.
*/
void expandToInclude(double x, double y);
void expandToInclude(const osg::Vec3d& v) { expandToInclude(v.x(), v.y()); }
//void expandToInclude( const Bounds& bounds );
/**
* Expand this extent to include the bounds of another extent.
*/
bool expandToInclude(const GeoExtent& rhs);
/**
* Intersect this extent with another extent in the same SRS and return the
* result.
*/
GeoExtent intersectionSameSRS(const GeoExtent& rhs) const; //const Bounds& rhs ) const;
/**
* Returns a human-readable string containing the extent data (without the SRS)
*/
std::string toString() const;
/**
*Inflates this GeoExtent by the given ratios
*/
void scale(double x_scale, double y_scale);
/**
* Expands the extent by x and y.
*/
void expand(double x, double y);
/**
* Expands the extent by x and y.
*/
void expand(const Distance& x, const Distance& y);
/**
*Gets the area of this GeoExtent
*/
double area() const;
/**
* Generate a polytope in world coordinates that bounds the extent.
* Return false if the extent it invalid.
*/
bool createPolytope(osg::Polytope& out) const;
/**
* Computes a scale/bias matrix that transforms parametric coordinates [0..1]
* from this extent into the target extent. Return false if the extents are
* incompatible (different SRS, etc.)
*
* For example, if this extent is 100m wide, and the target extent is
* 200m wide, the output matrix will have an x_scale = 0.5.
*
* Note! For the sake of efficiency, this method does NOT check for
* validity nor for SRS equivalence -- so be sure to validate those beforehand.
* It also assumes the output matrix is preset to the identity.
*/
bool createScaleBias(const GeoExtent& target, osg::Matrixd& output) const;
bool createScaleBias(const GeoExtent& target, osg::Matrixf& output) const;
/**
* Generates a BoundingSphere encompassing the extent and a vertical
* volume, in world coordinates.
*/
osg::BoundingSphered createWorldBoundingSphere(double minElev, double maxElev) const;
/**
* Returns true if the extent is the entire Earth, for geographic
* extents. Otherwise returns false.
*/
bool isWholeEarth() const;
public:
static GeoExtent INVALID;
public: // config
Config getConfig() const;
void fromConfig(const Config& conf);
private:
double _west, _width, _south, _height;
osg::ref_ptr<const SpatialReference> _srs;
double normalizeX(double longitude) const;
void clamp();
bool isGeographic() const;
void setOriginAndSize(double west, double south, double width, double height);
};
inline double GeoExtent::west() const { return _west; }
// if east is exactly on the antimeridian, return 180.0
inline double GeoExtent::east() const {
double a = normalizeX(_west + _width);
return (isValid() && _srs->isGeographic() && a == -180.0) ? 180.0 : a;
}
inline double GeoExtent::south() const { return _south; }
inline double GeoExtent::north() const { return _south + _height; }
/**
* A geospatial area with tile data LOD extents
*/
class OSGEARTH_EXPORT DataExtent : public GeoExtent
{
public:
DataExtent();
DataExtent(const GeoExtent& extent);
DataExtent(const GeoExtent& extent, const std::string &description);
DataExtent(const GeoExtent& extent, unsigned minLevel);
DataExtent(const GeoExtent& extent, unsigned minLevel, const std::string &description);
DataExtent(const GeoExtent& extent, unsigned minLevel, unsigned maxLevel);
DataExtent(const GeoExtent& extent, unsigned minLevel, unsigned maxLevel, const std::string &description);
/** dtor */
virtual ~DataExtent() { }
/** The minimum LOD of the extent */
optional<unsigned>& minLevel() { return _minLevel; }
const optional<unsigned>& minLevel() const { return _minLevel; }
/** The maximum LOD of the extent */
optional<unsigned>& maxLevel() { return _maxLevel; }
const optional<unsigned>& maxLevel() const { return _maxLevel; }
/** description for the data extents */
const osgEarth::optional<std::string>& description() const { return _description; }
private:
optional<unsigned> _minLevel;
optional<unsigned> _maxLevel;
optional<std::string> _description;
};
typedef std::vector< DataExtent > DataExtentList;
/**
* A georeferenced image; i.e. an osg::Image and an associated GeoExtent with SRS.
*/
class OSGEARTH_EXPORT GeoImage
{
public:
using pixel_type = osg::Vec4f;
/** Construct an empty (invalid) geoimage. */
GeoImage();
//! Construct an image with an error status
GeoImage(const Status&);
//! Constructs a new goereferenced image.
GeoImage(const osg::Image* image, const GeoExtent& extent);
//! Constructs a new goereferenced image from a future.
GeoImage(jobs::future<osg::ref_ptr<osg::Image>> image, const GeoExtent& extent);
/** dtor */
virtual ~GeoImage() { }
static GeoImage INVALID;
public:
/**
* True if this is a valid geo image.
*/
bool valid() const;
//! Error status if set
const Status& getStatus() const { return _status; }
/**
* Gets a pointer to the underlying OSG image.
*/
const osg::Image* getImage() const;
/**
* Gets the geospatial extent of the image.
*/
const GeoExtent& getExtent() const;
/**
* Shortcut to get the spatial reference system describing
* the projection of the image.
*/
const SpatialReference* getSRS() const;
/**
* Crops the image to a new geospatial extent.
*
* @param extent
* New extent to which to crop the image.
* @param exact
* If "exact" is true, the output image will have exactly the extents requested;
* this process may require resampling and will therefore be more expensive. If
* "exact" is false, we do a simple crop of the image that is rounded to the nearest
* pixel. The resulting extent will be close but usually not exactly what was
* requested - however, this method is faster.
* @param width, height
* New pixel size for the output image. By default, the method will automatically
* calculate a new pixel size.
*/
GeoImage crop(
const GeoExtent& extent,
bool exact = false,
unsigned int width = 0,
unsigned int height = 0,
bool useBilinearInterpolation = true) const;
/**
* Warps the image into a new spatial reference system.
*
* @param to_srs
* SRS into which to warp the image.
* @param to_extent
* Supply this extent if you wish to warp AND crop the image in one step. This is
* faster than calling reproject() and then crop().
* @param width, height
* New pixel size for the output image. Be default, the method will automatically
* calculate a new pixel size.
*/
GeoImage reproject(
const SpatialReference* to_srs,
const GeoExtent* to_extent = 0,
unsigned int width = 0,
unsigned int height = 0,
bool useBilinearInterpolation = true) const;
/**
* Returns the underlying OSG image and releases the reference pointer.
*/
osg::ref_ptr<osg::Image> takeImage();
/**
* Gets the units per pixel of this geoimage
*/
double getUnitsPerPixel() const;
//! Gets the coordinate at the image's s,t
bool getCoord(int s, int t, double& out_x, double& out_y) const;
//! Sets a token object in this GeoImage. You can use this to
//! keep a weak reference to the object after creating it,
//! for example to detect destruction.
void setTrackingToken(osg::Object* token);
osg::Object* getTrackingToken() const;
unsigned s() const {
return _myimage.valid() ? _myimage->s() : 0;
}
unsigned t() const {
return _myimage.valid() ? _myimage->t() : 0;
}
bool read(pixel_type& output, unsigned s, unsigned t) const {
_read(output, s, t);
return output.r() != NO_DATA_VALUE;
}
bool read(pixel_type& output, double u, double v) const {
_read(output, u, v);
return output.r() != NO_DATA_VALUE;
}
ImageUtils::PixelReader& getReader() { return _read; };
const ImageUtils::PixelReader& getReader() const { return _read; }
//! Read the value of a pixel at a geopoint.
bool read(
pixel_type& output,
const GeoPoint& p) const;
private:
GeoExtent _extent;
Status _status;
osg::ref_ptr<const osg::Image> _myimage;
mutable optional<jobs::future<osg::ref_ptr<osg::Image>>> _future;
osg::ref_ptr<osg::Object> _token;
ImageUtils::PixelReader _read;
};
typedef std::vector<GeoImage> GeoImageVector;
struct GeoImageIterator : public ImageUtils::ImageIteratorWithExtent<GeoExtent>
{
GeoImageIterator(const GeoImage& im) :
ImageUtils::ImageIteratorWithExtent<GeoExtent>(
im.getImage(), im.getExtent()) { }
};
struct GeoImagePixelReader : public ImageUtils::PixelReaderWithExtent<GeoExtent>
{
GeoImagePixelReader(const GeoImage& im) :
ImageUtils::PixelReaderWithExtent<GeoExtent>(
im.getImage(), im.getExtent()) { }
};
/**
* A georeferenced heightfield and associated normal/curvature map.
*/
class OSGEARTH_EXPORT GeoHeightField
{
public:
/** Constructs an empty (invalid) heightfield. */
GeoHeightField();
//! Construct a heightfield with an error status
GeoHeightField(const Status&);
/**
* Constructs a new georeferenced heightfield.
*/
GeoHeightField(
const osg::HeightField* heightField,
const GeoExtent& extent);
/** dtor */
virtual ~GeoHeightField() { }
static GeoHeightField INVALID;
/**
* True if this is a valid heightfield.
*/
bool valid() const;
//! Status indicator
const Status& getStatus() const { return _status; }
/**
* Gets the elevation value at a specified point.
*
* @param srs
* Spatial reference of the query coordinates. (If you pass in NULL, the method
* will assume that the SRS is equivalent to that of the GeoHeightField. Be sure
* this is case of you will get incorrect results.)
* @param x, y
* Coordinates at which to query the elevation value.
* @param interp
* Interpolation method for the elevation query.
* @param srsWithOutputVerticalDatum
* Transform the output elevation value according to the vertical datum
* associated with this SRS. If the SRS is NULL, assume a geodetic vertical datum
* relative to this object's reference ellipsoid.
* @param out_elevation
* Output: the elevation value
* @return
* True if the elevation query was succesful; false if not (e.g. if the query
* fell outside the geospatial extent of the heightfield)
*/
bool getElevation(
const SpatialReference* inputSRS,
double x,
double y,
RasterInterpolation interp,
const SpatialReference* srsWithOutputVerticalDatum,
float& out_elevation) const;
//! Gets the elevation at a point (must be in the same SRS; bilinear interpolation)
float getElevation(double x, double y, RasterInterpolation interp = INTERP_BILINEAR) const;
/**
* Subsamples the heightfield, returning a new heightfield corresponding to
* the destEx extent. The destEx must be a smaller, inset area of sourceEx.
*/
GeoHeightField createSubSample(const GeoExtent& destEx, unsigned int width, unsigned int height, RasterInterpolation interpolation) const;
/**
* Gets the geospatial extent of the heightfield.
*/
const GeoExtent& getExtent() const;
/**
* The minimum height in the heightfield
*/
float getMinHeight() const { return _minHeight; }
/**
* The maximum height in the heightfield
*/
float getMaxHeight() const { return _maxHeight; }
/**
* Gets a pointer to the underlying OSG heightfield.
*/
const osg::HeightField* getHeightField() const;
/**
* Gets the X interval of this GeoHeightField
*/
double getXInterval() const;
/**
* Gets the Y interval of this GeoHeightField
*/
double getYInterval() const;
//Sort GeoHeightField's by resolution
struct SortByResolutionFunctor
{
inline bool operator() (const GeoHeightField& lhs, const GeoHeightField& rhs) const
{
return lhs.getXInterval() < rhs.getXInterval();
}
};
protected:
GeoExtent _extent;
Status _status;
float _minHeight, _maxHeight;
osg::ref_ptr<const osg::HeightField> _heightField;
void init();
};
typedef std::vector<GeoHeightField> GeoHeightFieldVector;
/**
* A georeferenced node.
*/
class OSGEARTH_EXPORT GeoNode
{
public:
//! Construct an empty (invalid) GeoNode
GeoNode();
//! Construct an image with an error status
GeoNode(const Status&);
//! Constructs a new goereferenced node
GeoNode(const osg::Node* node, const GeoExtent& extent);
//! Global invalid node
static GeoNode INVALID;
public:
//! True if this is a valid object
bool valid() const;
//! Error status if set
const Status& getStatus() const { return _status; }
//! The underlying OSG node
const osg::Node* getNode() const { return _node.get(); }
//! The node's extent
const GeoExtent& getExtent() const { return _extent; }
private:
GeoExtent _extent;
Status _status;
osg::ref_ptr<const osg::Node> _node;
};
typedef std::vector<GeoNode> GeoNodeVector;
}