Added an optional use of doubles for computing error metrics to help investigate precision issues seen in VPB when working with small segments of geographic data.

This commit is contained in:
Robert Osfield
2007-12-20 15:50:07 +00:00
parent f8253ca4bd
commit 2c0842c7b7
2 changed files with 35 additions and 22 deletions

View File

@@ -28,7 +28,7 @@ class OSGUTIL_EXPORT Simplifier : public osg::NodeVisitor
{
public:
Simplifier(float sampleRatio=1.0f, float maximumError=FLT_MAX, float maximumLength=0.0);
Simplifier(double sampleRatio=1.0, double maximumError=FLT_MAX, double maximumLength=0.0);
void setSampleRatio(float sampleRatio) { _sampleRatio = sampleRatio; }
@@ -104,9 +104,9 @@ class OSGUTIL_EXPORT Simplifier : public osg::NodeVisitor
protected:
float _sampleRatio;
float _maximumError;
float _maximumLength;
double _sampleRatio;
double _maximumError;
double _maximumLength;
bool _triStrip;
bool _smoothing;

View File

@@ -56,6 +56,13 @@ class EdgeCollapse
{
public:
#if 1
typedef float error_type;
#else
typedef double error_type;
#endif
struct Triangle;
struct Edge;
struct Point;
@@ -102,11 +109,14 @@ public:
return computeInterpolatedPoint(edge,0.5f);
}
float computeErrorMetric(Edge* edge,Point* point) const
error_type computeErrorMetric(Edge* edge,Point* point) const
{
if (_computeErrorMetricUsingLength)
{
return (edge->_p1->_vertex - edge->_p2->_vertex).length();
error_type dx = error_type(edge->_p1->_vertex.x()) - error_type(edge->_p2->_vertex.x());
error_type dy = error_type(edge->_p1->_vertex.y()) - error_type(edge->_p2->_vertex.y());
error_type dz = error_type(edge->_p1->_vertex.z()) - error_type(edge->_p2->_vertex.z());
return sqrt(dx*dx + dy*dy + dz*dz);
}
else if (point)
{
@@ -116,9 +126,9 @@ public:
std::copy( edge->_p2->_triangles.begin(), edge->_p2->_triangles.end(), std::inserter(triangles,triangles.begin()));
const osg::Vec3& vertex = point->_vertex;
float error = 0.0f;
error_type error = 0.0;
if (triangles.empty()) return 0.0f;
if (triangles.empty()) return 0.0;
for(LocalTriangleSet::iterator itr=triangles.begin();
itr!=triangles.end();
@@ -128,7 +138,7 @@ public:
}
// use average of error
error /= (float)triangles.size();
error /= error_type(triangles.size());
return error;
}
@@ -164,7 +174,7 @@ public:
{
edge->updateMaxNormalDeviationOnEdgeCollapse();
if (edge->getMaxNormalDeviationOnEdgeCollapse()<=1.0f && !edge->isAdjacentToBoundary())
if (edge->getMaxNormalDeviationOnEdgeCollapse()<=1.0 && !edge->isAdjacentToBoundary())
edge->setErrorMetric( computeErrorMetric( edge, edge->_proposedPoint.get()));
else
edge->setErrorMetric( FLT_MAX );
@@ -196,7 +206,7 @@ public:
edge->_proposedPoint = computeOptimalPoint(edge);
edge->updateMaxNormalDeviationOnEdgeCollapse();
if (edge->getMaxNormalDeviationOnEdgeCollapse()<=1.0f && !edge->isAdjacentToBoundary())
if (edge->getMaxNormalDeviationOnEdgeCollapse()<=1.0 && !edge->isAdjacentToBoundary())
edge->setErrorMetric( computeErrorMetric( edge, edge->_proposedPoint.get()));
else
edge->setErrorMetric( FLT_MAX );
@@ -303,7 +313,7 @@ public:
struct Edge : public osg::Referenced
{
Edge(): _errorMetric(0.0f), _maximumDeviation(1.0f) {}
Edge(): _errorMetric(0.0), _maximumDeviation(1.0) {}
void clear()
{
@@ -317,13 +327,13 @@ public:
TriangleSet _triangles;
float _errorMetric;
float _maximumDeviation;
error_type _errorMetric;
error_type _maximumDeviation;
osg::ref_ptr<Point> _proposedPoint;
void setErrorMetric(float errorMetric) { _errorMetric = errorMetric; }
float getErrorMetric() const { return _errorMetric; }
void setErrorMetric(error_type errorMetric) { _errorMetric = errorMetric; }
error_type getErrorMetric() const { return _errorMetric; }
bool operator < ( const Edge& rhs) const
{
@@ -394,7 +404,7 @@ public:
}
}
float getMaxNormalDeviationOnEdgeCollapse() const { return _maximumDeviation; }
error_type getMaxNormalDeviationOnEdgeCollapse() const { return _maximumDeviation; }
};
@@ -465,7 +475,7 @@ public:
}
// note return 1 - dotproduct, so that deviation is in the range of 0.0 to 2.0, where 0 is coincident, 1.0 is 90 degrees, and 2.0 is 180 degrees.
float computeNormalDeviationOnEdgeCollapse(Edge* edge,Point* pNew) const
error_type computeNormalDeviationOnEdgeCollapse(Edge* edge,Point* pNew) const
{
const Point* p1 = (_p1==edge->_p1 || _p1==edge->_p2) ? pNew : _p1.get();
const Point* p2 = (_p2==edge->_p1 || _p2==edge->_p2) ? pNew : _p2.get();
@@ -474,13 +484,16 @@ public:
osg::Vec3 new_normal = (p2->_vertex - p1->_vertex) ^ (p3->_vertex - p2->_vertex);
new_normal.normalize();
float result = 1.0f - (new_normal.x() * _plane[0] + new_normal.y() * _plane[1] + new_normal.z() * _plane[2]);
error_type result = 1.0 - (new_normal.x() * _plane[0] + new_normal.y() * _plane[1] + new_normal.z() * _plane[2]);
return result;
}
float distance(const osg::Vec3& vertex) const
error_type distance(const osg::Vec3& vertex) const
{
return _plane.distance(vertex);
return error_type(_plane[0])*error_type(vertex.x())+
error_type(_plane[1])*error_type(vertex.y())+
error_type(_plane[2])*error_type(vertex.z())+
error_type(_plane[3]);
}
bool isBoundaryTriangle() const
@@ -1686,7 +1699,7 @@ void EdgeCollapse::copyBackToGeometry()
}
Simplifier::Simplifier(float sampleRatio, float maximumError, float maximumLength):
Simplifier::Simplifier(double sampleRatio, double maximumError, double maximumLength):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_sampleRatio(sampleRatio),
_maximumError(maximumError),