/* -*-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.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see
*/
#ifndef OSGEARTHUTIL_LINEOFSIGHT
#define OSGEARTHUTIL_LINEOFSIGHT
#include
#include
#include
#include
#include
#include
namespace osgEarth { namespace Contrib
{
using namespace osgEarth;
/**
* A Node that can be used to display radial line of sight calculations
*/
class OSGEARTH_EXPORT RadialLineOfSightNode : public LineOfSightNode, public MapNodeObserver
{
public:
/**
* Create a new RadialLineOfSightNode
* @param mapNode
* The MapNode this RadialLineOfSightNode is operating on.
*/
RadialLineOfSightNode( MapNode* mapNode );
virtual ~RadialLineOfSightNode();
/**
* Sets the radius in meters
*/
void setRadius( double radius );
/**
* Gets the radius in meters
*/
double getRadius() const;
/**
* Sets the number of spokes in the radial line of sight calculation
*/
void setNumSpokes( int numSpokes );
/**
* Gets the number of spokes in the radial line of sight calculation
*/
int getNumSpokes() const;
/**
* Gets the center point in world coordinates
*/
const osg::Vec3d& getCenterWorld() const;
/**
* Gets the center point
*/
const GeoPoint& getCenter() const;
/**
* Set the center point. The point should be in the Map's coordinate system. So if you're dealing with a geocentric map
* the location should be in the form lon, lat, elevation
*/
void setCenter(const GeoPoint& center);
/**
* Sets the good color
*/
void setGoodColor( const osg::Vec4f &color );
/**
* Gets the good color
*/
const osg::Vec4f& getGoodColor() const;
/**
* Sets the bad color
*/
void setBadColor( const osg::Vec4f &color );
/**
* Gets the bad color
*/
const osg::Vec4f& getBadColor() const;
/**
* Sets the outline color
*/
void setOutlineColor( const osg::Vec4f &color );
/**
* Gets the outline color
*/
const osg::Vec4f& getOutlineColor() const;
/**
* Gets the display mode
*/
LineOfSight::DisplayMode getDisplayMode() const;
/*
* Sets the display mode
*/
void setDisplayMode( LineOfSight::DisplayMode displayMode );
/**
* Gets whether to draw the fill of this RadialLineOfSightNode
*/
bool getFill() const;
/*
* Sets whether to draw the fill of this RadialLineOfSightNode
*/
void setFill( bool fill );
void addChangedCallback( LOSChangedCallback* callback );
void removeChangedCallback( LOSChangedCallback* callback );
/**
* Called when the underlying terrain has changed.
*/
void terrainChanged( const osgEarth::TileKey& tileKey, osg::Node* terrain );
bool getTerrainOnly() const;
void setTerrainOnly( bool terrainOnly );
public: // MapNodeObserver
virtual void setMapNode( MapNode* mapNode );
MapNode* getMapNode() { return _mapNode.get(); }
private:
osg::Node* getNode();
void compute(osg::Node* node);
void compute_line(osg::Node* node);
void compute_fill(osg::Node* node);
int _numSpokes;
double _radius;
LineOfSight::DisplayMode _displayMode;
bool _fill;
osg::Vec4 _goodColor;
osg::Vec4 _badColor;
osg::Vec4 _outlineColor;
GeoPoint _center;
osg::Vec3d _centerWorld;
osg::observer_ptr< MapNode > _mapNode;
LOSChangedCallbackList _changedCallbacks;
osg::ref_ptr < osgEarth::TerrainCallback > _terrainChangedCallback;
bool _terrainOnly;
};
/**********************************************************************/
/**
* An update callback that allows you to attach a RadialLineOfSightNode to a moving node.
* The update callback will update the center point of the calcuation to follow the node.
*
* Example:
* RadialLineOfSightNode* los = new RadialLineOfSightNode(myMapNode);
* los->setUpdateCallback( new RadialLineOfSightTether( myNode ) );
*/
class OSGEARTH_EXPORT RadialLineOfSightTether : public osg::NodeCallback
{
public:
RadialLineOfSightTether(osg::Node* node);
virtual ~RadialLineOfSightTether() { }
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
osg::Node* node() { return _node.get(); }
private:
osg::ref_ptr< osg::Node > _node;
};
/**********************************************************************/
class OSGEARTH_EXPORT RadialLineOfSightEditor : public osg::Group
{
public:
/**
* Create a new RadialLineOfSightEditor
* @param los
* The RadialLineOfSightNode to edit
*/
RadialLineOfSightEditor(RadialLineOfSightNode* los);
virtual ~RadialLineOfSightEditor();
/**
*Updates the position of the dragger to represent the actual location of the RadialLineOfSightNode.
*This should be called if the los is changed outside of the editor and would probably benefit
*from the RadialLineOfSightNode having a callback that notifies listeners that the start/end points have changed.
*/
void updateDraggers();
private:
osg::ref_ptr< RadialLineOfSightNode > _los;
osgEarth::Dragger* _dragger;
osg::ref_ptr< LOSChangedCallback > _callback;
};
} } // namespace osgEarth::Tools
#endif // OSGEARTHUTIL_LINEOFSIGHT