Implemented HeightAboveTerrain and added usage into osgintersection

This commit is contained in:
Robert Osfield 2006-10-31 12:59:51 +00:00
parent e9b501002c
commit a253e17d3e
5 changed files with 215 additions and 14 deletions

View File

@ -1,6 +1,7 @@
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>
#include <osg/Timer>
#include <osg/CoordinateSystemNode>
#include <osg/Notify>
#include <osg/io_utils>
@ -9,6 +10,7 @@
#include <osgUtil/IntersectionVisitor>
#include <osgSim/LineOfSight>
#include <osgSim/HeightAboveTerrain>
#include <iostream>
@ -31,9 +33,9 @@ int main(int argc, char **argv)
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName());
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
osg::ref_ptr<osg::Node> root = osgDB::readNodeFiles(arguments);
osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);
if (!root)
if (!scene)
{
std::cout<<"No model loaded, please specify a valid model on the command line."<<std::endl;
return 0;
@ -42,8 +44,10 @@ int main(int argc, char **argv)
std::cout<<"Intersection "<<std::endl;
osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(scene.get());
osg::EllipsoidModel* em = csn ? csn->getEllipsoidModel() : 0;
osg::BoundingSphere bs = root->getBound();
osg::BoundingSphere bs = scene->getBound();
bool useIntersectorGroup = true;
@ -57,10 +61,13 @@ int main(int argc, char **argv)
osg::Vec3d end = bs.center();// - osg::Vec3d(0.0, bs.radius(),0.0);
osg::Vec3d deltaRow( 0.0, 0.0, bs.radius()*0.01);
osg::Vec3d deltaColumn( bs.radius()*0.01, 0.0, 0.0);
unsigned int numRows = 50;
unsigned int numColumns = 50;
unsigned int numRows = 20;
unsigned int numColumns = 20;
osgSim::LineOfSight los;
osgSim::HeightAboveTerrain hat;
hat.setDatabaseCacheReadCallback(los.getDatabaseCacheReadCallback());
for(unsigned int r=0; r<numRows; ++r)
{
@ -69,17 +76,20 @@ int main(int argc, char **argv)
osg::Vec3d s = start + deltaColumn * double(c) + deltaRow * double(r);
osg::Vec3d e = end + deltaColumn * double(c) + deltaRow * double(r);
los.addLOS(s,e);
hat.addPoint(s);
}
}
los.computeIntersections(root.get());
std::cout<<"Computing LineOfSight"<<std::endl;
los.computeIntersections(scene.get());
osg::Timer_t endTick = osg::Timer::instance()->tick();
std::cout<<"Completed in "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl;
#if 0
#if 1
for(unsigned int i=0; i<los.getNumLOS(); i++)
{
const osgSim::LineOfSight::Intersections& intersections = los.getIntersections(i);
@ -95,8 +105,15 @@ int main(int argc, char **argv)
// now do a second traversal to test performance of cache.
startTick = osg::Timer::instance()->tick();
los.computeIntersections(root.get());
std::cout<<"Computing HeightAboveTerrain"<<std::endl;
hat.computeIntersections(scene.get());
for(unsigned int i=0; i<hat.getNumPoints(); i++)
{
std::cout<<" point = "<<hat.getPoint(i)<<" hat = "<<hat.getHeightAboveTerrain(i)<<std::endl;
}
endTick = osg::Timer::instance()->tick();
std::cout<<"Completed in "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl;
@ -128,7 +145,7 @@ int main(int argc, char **argv)
osgUtil::IntersectionVisitor intersectVisitor( intersectorGroup.get(), new MyReadCallback );
root->accept(intersectVisitor);
scene->accept(intersectVisitor);
osg::Timer_t endTick = osg::Timer::instance()->tick();
@ -181,7 +198,7 @@ int main(int argc, char **argv)
osgUtil::IntersectionVisitor intersectVisitor( intersector.get(), new MyReadCallback );
root->accept(intersectVisitor);
scene->accept(intersectVisitor);
osg::Timer_t endTick = osg::Timer::instance()->tick();

View File

@ -16,7 +16,8 @@
#include <osgUtil/IntersectionVisitor>
#include <osgSim/Export>
// include so we can get access to the DatabaseCacheReadCallback
#include <osgSim/LineOfSight>
namespace osgSim {
@ -25,7 +26,85 @@ class OSGSIM_EXPORT HeightAboveTerrain
{
public :
HeightAboveTerrain();
/** Clear the internal HAT List so it contains no height above terrain tests.*/
void clear();
/** Add a height above terrain test point in the CoordinateFrame.*/
unsigned int addPoint(const osg::Vec3d& point);
/** Get the number of height above terrain tests.*/
unsigned int getNumPoints() const { return _HATList.size(); }
/** Set the source point of single height above terrain test.*/
void setPoint(unsigned int i, const osg::Vec3d& point) { _HATList[i]._point = point; }
/** Get the source point of single height above terrain test.*/
const osg::Vec3d& getPoint(unsigned int i) const { return _HATList[i]._point; }
/** Get the intersection height for a single height above terrain test.
* Note, you must call computeIntersections(..) before you can querry the HeightAboveTerrain.
* If no intersections are found then height returned will be the height above mean sea level. */
double getHeightAboveTerrain(unsigned int i) const { return _HATList[i]._hat; }
/** Set the lowest height that the should be tested for.
* Defaults to -1000, i.e. 1000m below mean sea level. */
void setLowestHeight(double lowestHeight) { _lowestHeight = lowestHeight; }
/** Get the lowest height that the should be tested for.*/
double getLowestHeight() const { return _lowestHeight; }
/** Compute the HAT intersections with the specified scene graph.
* The results are all stored in the form of a single height above terrain value per HAT test.
* Note, if the topmost node is a CoordinateSystemNode then the input points are assumed to be geocentric,
* with the up vector defined by the EllipsoidModel attached to the CoordinateSystemNode.
* If the topmost node is not a CoordinateSystemNode then a local coordinates frame is assumed, with a local up vector. */
void computeIntersections(osg::Node* scene);
/** Compute the vertical distance between the specified scene graph and a single HAT point. .*/
static double computeHeightAboveTerrain(osg::Node* scene, const osg::Vec3d& point);
/** Clear the database cache.*/
void clearDatabaseCache() { if (_dcrc.valid()) _dcrc->clearDatabaseCache(); }
/** Set the ReadCallback that does the reading of external PagedLOD models, and caching of loaded subgraphs.
* Note, if you have mulitple LineOfSight or HeightAboveTerrain objects in use at one time then you should share a single
* DatabaseCacheReadCallback between all of them. */
void setDatabaseCacheReadCallback(DatabaseCacheReadCallback* dcrc);
/** Get the ReadCallback that does the reading of external PagedLOD models, and caching of loaded subgraphs.*/
DatabaseCacheReadCallback* getDatabaseCacheReadCallback() { return _dcrc.get(); }
/** Get the IntersectionVistor that does the intersection traversal over the scene.
* Note, if you want to customized the traversal then you can use the IntersectionVisitor's method to alter its behavior. */
osgUtil::IntersectionVisitor& getIntersectionVisitor() { return _intersectionVisitor; }
protected :
struct HAT
{
HAT(const osg::Vec3d& point):
_point(point),
_hat(0.0) {}
osg::Vec3d _point;
double _hat;
};
typedef std::vector<HAT> HATList;
double _lowestHeight;
HATList _HATList;
osg::ref_ptr<DatabaseCacheReadCallback> _dcrc;
osgUtil::IntersectionVisitor _intersectionVisitor;
};

View File

@ -52,7 +52,7 @@ class OSGSIM_EXPORT LineOfSight
LineOfSight();
/** Clear the internal LOS List so it contains no line of sight tests.*/
void clearLOS();
void clear();
/** Add a line of sight test, consisting of start and end point. Returns the index number of the newly adding LOS test.*/
unsigned int addLOS(const osg::Vec3d& start, const osg::Vec3d& end);
@ -78,7 +78,7 @@ class OSGSIM_EXPORT LineOfSight
const Intersections& getIntersections(unsigned int i) const { return _LOSList[i]._intersections; }
/** Compute the LOS intersections with the specified scene graph.
* The results are all stored in the form of IntersectionList, one per LOS test.*/
* The results are all stored in the form of Intersections list, one per LOS test.*/
void computeIntersections(osg::Node* scene);
/** Compute the intersection between the specified scene graph and a single LOS start,end pair. Returns an IntersectionList, of all the points intersected.*/

View File

@ -11,6 +11,111 @@
* OpenSceneGraph Public License for more details.
*/
#include <osg/CoordinateSystemNode>
#include <osgSim/HeightAboveTerrain>
#include <osg/Notify>
using namespace osgSim;
HeightAboveTerrain::HeightAboveTerrain()
{
_lowestHeight = -1000.0;
setDatabaseCacheReadCallback(new DatabaseCacheReadCallback);
}
void HeightAboveTerrain::clear()
{
_HATList.clear();
}
unsigned int HeightAboveTerrain::addPoint(const osg::Vec3d& point)
{
unsigned int index = _HATList.size();
_HATList.push_back(HAT(point));
return index;
}
void HeightAboveTerrain::computeIntersections(osg::Node* scene)
{
osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(scene);
osg::EllipsoidModel* em = csn ? csn->getEllipsoidModel() : 0;
osg::ref_ptr<osgUtil::IntersectorGroup> intersectorGroup = new osgUtil::IntersectorGroup();
for(HATList::iterator itr = _HATList.begin();
itr != _HATList.end();
++itr)
{
if (em)
{
osg::Vec3d start = itr->_point;
osg::Vec3d upVector = em->computeLocalUpVector(start.x(), start.y(), start.z());
double latitude, longitude, height;
em->convertXYZToLatLongHeight(start.x(), start.y(), start.z(), latitude, longitude, height);
osg::Vec3d end = start - upVector * (height - _lowestHeight);
itr->_hat = height;
osg::notify(osg::NOTICE)<<"lat = "<<latitude<<" longitude = "<<longitude<<" height = "<<height<<std::endl;
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(start, end);
intersectorGroup->addIntersector( intersector.get() );
}
else
{
osg::Vec3d start = itr->_point;
osg::Vec3d upVector (0.0, 0.0, 1.0);
double height = start.z();
osg::Vec3d end = start - upVector * (height - _lowestHeight);
itr->_hat = height;
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector( start, end);
intersectorGroup->addIntersector( intersector.get() );
}
}
_intersectionVisitor.reset();
_intersectionVisitor.setIntersector( intersectorGroup.get() );
scene->accept(_intersectionVisitor);
unsigned int index = 0;
osgUtil::IntersectorGroup::Intersectors& intersectors = intersectorGroup->getIntersectors();
for(osgUtil::IntersectorGroup::Intersectors::iterator intersector_itr = intersectors.begin();
intersector_itr != intersectors.end();
++intersector_itr, ++index)
{
osgUtil::LineSegmentIntersector* lsi = dynamic_cast<osgUtil::LineSegmentIntersector*>(intersector_itr->get());
if (lsi)
{
osgUtil::LineSegmentIntersector::Intersections& intersections = lsi->getIntersections();
if (!intersections.empty())
{
const osgUtil::LineSegmentIntersector::Intersection& intersection = *intersections.begin();
osg::Vec3d intersectionPoint = intersection.localIntersectionPoint * (*intersection.matrix);
_HATList[index]._hat = (_HATList[index]._point - intersectionPoint).length();
}
}
}
}
double HeightAboveTerrain::computeHeightAboveTerrain(osg::Node* scene, const osg::Vec3d& point)
{
HeightAboveTerrain hat;
unsigned int index = hat.addPoint(point);
hat.computeIntersections(scene);
return hat.getHeightAboveTerrain(index);
}
void HeightAboveTerrain::setDatabaseCacheReadCallback(DatabaseCacheReadCallback* dcrc)
{
_dcrc = dcrc;
_intersectionVisitor.setReadCallback(dcrc);
}

View File

@ -92,7 +92,7 @@ LineOfSight::LineOfSight()
setDatabaseCacheReadCallback(new DatabaseCacheReadCallback);
}
void LineOfSight::clearLOS()
void LineOfSight::clear()
{
_LOSList.clear();
}