From 3b4e0a419aaa17eee4afeaccf477354ff4f81beb Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 15 Apr 2004 09:37:10 +0000 Subject: [PATCH] Added tests for the consistency of points, edges and triangles. --- src/osgUtil/Simplifier.cpp | 330 +++++++++++++++++++++++++++++++++++-- 1 file changed, 313 insertions(+), 17 deletions(-) diff --git a/src/osgUtil/Simplifier.cpp b/src/osgUtil/Simplifier.cpp index 447d654c5..de85b716e 100644 --- a/src/osgUtil/Simplifier.cpp +++ b/src/osgUtil/Simplifier.cpp @@ -87,22 +87,33 @@ public: struct Edge : public osg::Referenced { - Edge():_errorMetric(0.0f) {} + Edge():_needToRecomputeErrorMetric(true), _errorMetric(0.0f) {} osg::ref_ptr _p1; osg::ref_ptr _p2; osg::ref_ptr _t1; osg::ref_ptr _t2; - + + bool _needToRecomputeErrorMetric; + float _errorMetric; + void setErrorMetric(float errorMetric) { _errorMetric = errorMetric; } float getErrorMetric() const { return _errorMetric; } bool operator < ( const Edge& rhs) const { - if (getErrorMetric()getErrorMetric()) return false; - + // edge that need to be recomputed are always first. + if (_needToRecomputeErrorMetric && !rhs._needToRecomputeErrorMetric) return true; + if (!_needToRecomputeErrorMetric && rhs._needToRecomputeErrorMetric) return false; + + if (!_needToRecomputeErrorMetric && !rhs._needToRecomputeErrorMetric) + { + // both error metrics are computed + if (getErrorMetric()getErrorMetric()) return false; + } + if (_p1 < rhs._p1) return true; if (rhs._p1 < _p1) return false; @@ -125,7 +136,6 @@ public: } } - float _errorMetric; }; struct Triangle : public osg::Referenced @@ -188,17 +198,93 @@ public: void removeTriangle(Triangle* triangle) { - removePoint(triangle,triangle->_p1.get()); - removePoint(triangle,triangle->_p2.get()); - removePoint(triangle,triangle->_p3.get()); + if (triangle->_p1.valid()) removePoint(triangle,triangle->_p1.get()); + if (triangle->_p2.valid()) removePoint(triangle,triangle->_p2.get()); + if (triangle->_p3.valid()) removePoint(triangle,triangle->_p3.get()); - removeEdge(triangle,triangle->_e1.get()); - removeEdge(triangle,triangle->_e2.get()); - removeEdge(triangle,triangle->_e3.get()); + if (triangle->_e1.valid()) removeEdge(triangle,triangle->_e1.get()); + if (triangle->_e2.valid()) removeEdge(triangle,triangle->_e2.get()); + if (triangle->_e3.valid()) removeEdge(triangle,triangle->_e3.get()); _triangleSet.erase(triangle); } + void replaceTrianglePoint(Triangle* triangle, Point* pOriginal, Point* pNew) + { + if (triangle->_p1==pOriginal || triangle->_p2==pOriginal || triangle->_p3==pOriginal) + { + // fix the corner points to use the new point + if (triangle->_p1==pOriginal) triangle->_p1=pNew; + if (triangle->_p2==pOriginal) triangle->_p2=pNew; + if (triangle->_p3==pOriginal) triangle->_p3=pNew; + + // fixes the edges so they point to use the new point + triangle->_e1 = replaceEdgePoint(triangle->_e1.get(),pOriginal,pNew); + triangle->_e2 = replaceEdgePoint(triangle->_e2.get(),pOriginal,pNew); + triangle->_e3 = replaceEdgePoint(triangle->_e3.get(),pOriginal,pNew); + + // remove the triangle form the orignal point, and possibly the point if its the last triangle to use it + removePoint(triangle, pOriginal); + + // add the triangle to that point + addPoint(triangle,pNew); + } + + } + + bool testTriangle(Triangle* triangle) + { + bool result = true; + if (!(triangle->_p1)) + { + std::cout<<"testTriangle("<_p1->_triangles.count(triangle)==0) + { + std::cout<<"testTriangle("<_triangles does not contain triangle"<_p2)) + { + std::cout<<"testTriangle("<_p2->_triangles.count(triangle)==0) + { + std::cout<<"testTriangle("<_triangles does not contain triangle"<_p3)) + { + std::cout<<"testTriangle("<_p3->_triangles.count(triangle)==0) + { + std::cout<<"testTriangle("<_triangles does not contain triangle"<(itr->get()))) + { + ++numErrors; + } + } + return numErrors; + } + Edge* addEdge(Triangle* triangle, Point* p1, Point* p2) { //std::cout<<"addEdge("<_p1==pOriginal || edge->_p2==pOriginal) + { + EdgeSet::iterator itr = _edgeSet.find(edge); + if (itr!=_edgeSet.end()) + { + // remove the edge from the list, as its positoin in the list + // may need to change once its values have been ammended + _edgeSet.erase(itr); + } + + // modify its values + if (edge->_p1==pOriginal) edge->_p1=pNew; + if (edge->_p2==pOriginal) edge->_p2=pNew; + + if (edge->_p2 > edge->_p1) + { + // swap to ensure that lowest ptr value of p1, p2 pair is first. + osg::ref_ptr tmp = edge->_p1; + edge->_p1 = edge->_p2; + edge->_p2 = tmp; + } + + itr = _edgeSet.find(edge); + if (itr!=_edgeSet.end()) + { + // reuse existing edge. + edge = const_cast(itr->get()); + } + else + { + // put it back in. + _edgeSet.insert(edge); + } + return edge; + } + else + { + return edge; + } + + } + + void collapseEdge(Edge* edge, Point* pNew) + { + if (!edge->_t1.valid() || !edge->_t2.valid()) return; + + osg::ref_ptr keep_edge_locally_referenced_to_prevent_premature_deletion = edge; + osg::ref_ptr keep_point_locally_referenced_to_prevent_premature_deletion = pNew; + + if (edge->_p1 != pNew) + { + TriangleSet triangles_p1 = edge->_p1->_triangles; + triangles_p1.erase(edge->_t1.get()); + triangles_p1.erase(edge->_t2.get()); + for(TriangleSet::iterator titr_p1 = triangles_p1.begin(); + titr_p1 != triangles_p1.end(); + ++titr_p1) + { + replaceTrianglePoint(const_cast(titr_p1->get()),edge->_p1.get(),pNew); + } + } + + if (edge->_p2 != pNew) + { + TriangleSet triangles_p2 = edge->_p2->_triangles; + triangles_p2.erase(edge->_t1.get()); + triangles_p2.erase(edge->_t2.get()); + for(TriangleSet::iterator titr_p2 = triangles_p2.begin(); + titr_p2 != triangles_p2.end(); + ++titr_p2) + { + replaceTrianglePoint(const_cast(titr_p2->get()),edge->_p2.get(),pNew); + } + } +#if 1 + osg::ref_ptr t1 = edge->_t1; + osg::ref_ptr t2 = edge->_t1; + + // remove triangles directly connected to edge + if (edge->_t1.valid()) removeTriangle(edge->_t1.get()); + if (edge->_t2.valid()) removeTriangle(edge->_t2.get()); +#endif + } + + + unsigned int testEdge(Edge* edge) + { + unsigned int numErrors = 0; + if (edge->_t1.valid()) + { + if (!(edge->_t1->_e1 == edge || edge->_t1->_e2 == edge || edge->_t1->_e3 == edge)) + { + std::cout<<"testEdge("<_e1=="<_t1->_e1.get()<_e2=="<_t1->_e2.get()<_e3=="<_t1->_e3.get()<_t2.valid()) + { + if (!(edge->_t2->_e1 == edge || edge->_t2->_e2 == edge || edge->_t2->_e3 == edge)) + { + std::cout<<"testEdge("<_e1=="<_t2->_e1.get()<_e2=="<_t2->_e2.get()<_e3=="<_t2->_e3.get()<(itr->get())); + } + return numErrors; + } + + Point* addPoint(Triangle* triangle, unsigned int p1) { - - osg::ref_ptr point = _originalPointList[p1]; + return addPoint(triangle,_originalPointList[p1].get()); + } + Point* addPoint(Triangle* triangle, Point* point) + { + PointSet::iterator itr = _pointSet.find(point); if (itr==_pointSet.end()) { @@ -263,13 +481,13 @@ public: } else { - point = *itr; + point = const_cast(itr->get()); //std::cout<<" reusePoint("<_triangles.insert(triangle); - return point.get(); + return point; } void removePoint(Triangle* triangle, Point* point) @@ -288,6 +506,40 @@ public: } + unsigned int testPoint(Point* point) + { + unsigned int numErrors = 0; + + for(TriangleSet::iterator itr=point->_triangles.begin(); + itr!=point->_triangles.end(); + ++itr) + { + Triangle* triangle = const_cast(itr->get()); + if (!(triangle->_p1 == point || triangle->_p2 == point || triangle->_p3 == point)) + { + std::cout<<"testPoint("<_p1 "<_p1.get()<_p2 "<_p2.get()<_p3 "<_p3.get()<(itr->get())); + } + return numErrors; + } + protected: typedef std::vector< osg::ref_ptr > ArrayList; @@ -644,6 +896,50 @@ class CopyPointsToVertexArrayVisitor : public osg::ArrayVisitor void EdgeCollapse::copyBackToGeometry() { + std::cout<<"Number of triangle errors before edge collapse= "<