From f1125f7b4dd5f43282bbb5ee79a1e0f54331adae Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sat, 24 Sep 2005 14:53:22 +0000 Subject: [PATCH] Improvements to the clipping of polygons at boundary edges. --- src/osgSim/SphereSegment.cpp | 283 +++++++++++++++++++++++++++++------ 1 file changed, 238 insertions(+), 45 deletions(-) diff --git a/src/osgSim/SphereSegment.cpp b/src/osgSim/SphereSegment.cpp index 5d717deef..6f0252b80 100644 --- a/src/osgSim/SphereSegment.cpp +++ b/src/osgSim/SphereSegment.cpp @@ -1173,7 +1173,12 @@ struct TriangleIntersectOperator BOTH_ENDS }; - Edge(unsigned int p1, unsigned int p2) + Edge(unsigned int p1, unsigned int p2, bool intersectionEdge=false): + _intersectionType(NO_INTERSECTION), + _intersectionVertexIndex(0), + _p1Outside(false), + _p2Outside(false), + _intersectionEdge(intersectionEdge) { if (p1>p2) { @@ -1206,15 +1211,22 @@ struct TriangleIntersectOperator if (itr!=_toTraverse.end()) _toTraverse.erase(itr); } + + bool completlyOutside() const { return _p1Outside && _p2Outside; } + unsigned int _p1; unsigned int _p2; TriangleList _triangles; - // intersection information + // intersection information IntersectionType _intersectionType; osg::Vec3 _intersectionVertex; + unsigned int _intersectionVertexIndex; + bool _p1Outside; + bool _p2Outside; TriangleList _toTraverse; + bool _intersectionEdge; }; typedef std::list< osg::ref_ptr > EdgeList; @@ -1283,13 +1295,17 @@ struct TriangleIntersectOperator { Polygon(Triangle* tri) { + osg::notify(osg::NOTICE)<<"Polgyon"<_e1) _edges.push_back(tri->_e1); + else osg::notify(osg::NOTICE)<<" Missing edge"<_e2) _edges.push_back(tri->_e2); + else osg::notify(osg::NOTICE)<<" Missing edge"<_e3) _edges.push_back(tri->_e3); + else osg::notify(osg::NOTICE)<<" Missing edge"< - unsigned int computeIntersections(I intersector) + unsigned int computeHitEdges(TriangleIntersectOperator& tio, I intersector) { // collect all the intersecting edges EdgeList hitEdges; @@ -1298,16 +1314,189 @@ struct TriangleIntersectOperator ++itr) { Edge* edge = const_cast(itr->get()); - if (intersector(edge)) + if (intersector(edge)) hitEdges.push_back(edge); + } + + if (hitEdges.empty()) return 0; + + + unsigned int numHitEdges = hitEdges.size(); + + EdgeList newEdgeList; + + osg::notify(osg::NOTICE)<<"Num Hit edges"<=2) + { + Edge* edge1 = hitEdges.front().get(); hitEdges.pop_front(); + int p1 = tio._originalVertices.size(); + edge1->_intersectionVertexIndex = p1; + tio._originalVertices.push_back(edge1->_intersectionVertex); + + Edge* edge2 = hitEdges.front().get(); hitEdges.pop_front(); + int p2 = tio._originalVertices.size(); + edge2->_intersectionVertexIndex = p2; + tio._originalVertices.push_back(edge2->_intersectionVertex); + + newEdgeList.push_back(new Edge(p1,p2,true)); + } + + for(EdgeList::iterator itr = _edges.begin(); + itr != _edges.end(); + ++itr) + { + Edge* edge = const_cast(itr->get()); + if (!(edge->completlyOutside())) { - hitEdges.push_back(edge); + if (edge->_intersectionType==Edge::NO_INTERSECTION) + { + newEdgeList.push_back(edge); + } + else + { + if (!edge->_p1Outside) + { + newEdgeList.push_back(new Edge(edge->_intersectionVertexIndex, edge->_p1, edge->_intersectionEdge)); + } + else if (!edge->_p2Outside) + { + newEdgeList.push_back(new Edge(edge->_intersectionVertexIndex, edge->_p2, edge->_intersectionEdge)); + } + else + { + osg::notify(osg::NOTICE)<<"Problem"< > EdgeVector; + EdgeVector edges; + for(EdgeList::const_iterator itr = _edges.begin(); + itr != _edges.end(); + ++itr) + { + if ((*itr)->_intersectionEdge) + { + osg::notify(osg::NOTICE)<<" accepting edge "<<(*itr)->_p1<<" "<<(*itr)->_p2<_p1<<" "<<(*itr)->_p2<_p1 == edges[j]->_p1) || (edges[i]->_p1 == edges[j]->_p2)) + { + ++numMatchesFor_p1; + } + + if ((edges[i]->_p2 == edges[j]->_p1) || (edges[i]->_p2 == edges[j]->_p2)) + { + ++numMatchesFor_p2; + } + } + if (numMatchesFor_p1==0) break; + if (numMatchesFor_p2==0) break; + } + + // get first edge. + osg::ref_ptr edge = edges[i]; + edges.erase(edges.begin()+i); + + // start a new line, add it to the list of lines. + osg::Vec3Array* newLine = new osg::Vec3Array; + generatedLines.push_back(newLine); + + unsigned int activePoint = 0; + if (numMatchesFor_p1==0) + { + newLine->push_back(tio._originalVertices[edge->_p1]+tio._centre); + newLine->push_back(tio._originalVertices[edge->_p2]+tio._centre); + activePoint = edge->_p2; + } + else + { + newLine->push_back(tio._originalVertices[edge->_p2]+tio._centre); + newLine->push_back(tio._originalVertices[edge->_p1]+tio._centre); + activePoint = edge->_p1; + } + + osg::notify(osg::NOTICE)<<"Start with "<_p1<<" "<_p2<<" activePoint="<_p1 == activePoint) + { + + activePoint = (*itr)->_p2; + newLine->push_back(tio._originalVertices[activePoint]+tio._centre); + + osg::notify(osg::NOTICE)<<"A Found "<<(*itr)->_p1<<" "<<(*itr)->_p2<<" activePoint="<_p2 == activePoint) + { + activePoint = (*itr)->_p1; + newLine->push_back(tio._originalVertices[activePoint]+tio._centre); + osg::notify(osg::NOTICE)<<"B Found "<<(*itr)->_p1<<" "<<(*itr)->_p2<<" activePoint="< edge = edges.front(); + edges.erase(edges.begin()); + + newLine->push_back(tio._originalVertices[edge->_p1]+tio._centre); + newLine->push_back(tio._originalVertices[edge->_p2]+tio._centre); + activePoint = edge->_p2; + + osg::notify(osg::NOTICE)<<"*********** Problem 2 with "<_p1<<" "<_p2<<" activePoint="< edge = new Edge(p1, p2); EdgeSet::iterator itr = _edges.find(edge); if (itr==_edges.end()) @@ -1893,12 +2074,14 @@ bool computeQuadraticSolution(double a, double b, double c, double& s1, double& struct AzimIntersector { - AzimIntersector(TriangleIntersectOperator& tif, double azim): + AzimIntersector(TriangleIntersectOperator& tif, double azim, bool lowerOutside): _tif(tif), - _azim(azim) {} + _azim(azim), + _lowerOutside(lowerOutside) {} TriangleIntersectOperator& _tif; double _azim; + bool _lowerOutside; inline bool operator() (TriangleIntersectOperator::Edge* edge) { @@ -1913,6 +2096,9 @@ struct AzimIntersector double azim2 = atan2(v2.x(),v2.y()); if (azim2<0.0) azim2 += 2.0*osg::PI; + edge->_p1Outside = _lowerOutside ? (azim1<_azim) : (azim1>_azim); + edge->_p2Outside = _lowerOutside ? (azim2<_azim) : (azim2>_azim); + // if both points inside then disgard if (azim1<_azim && azim2<_azim) return false; @@ -1967,14 +2153,16 @@ struct AzimIntersector struct AzimPlaneIntersector { - AzimPlaneIntersector(TriangleIntersectOperator& tif, double azim): - _tif(tif) + AzimPlaneIntersector(TriangleIntersectOperator& tif, double azim, bool lowerOutside): + _tif(tif), + _lowerOutside(lowerOutside) { _plane.set(cos(azim),-sin(azim),0.0,0.0); } TriangleIntersectOperator& _tif; osg::Plane _plane; + bool _lowerOutside; inline bool operator() (TriangleIntersectOperator::Edge* edge) { @@ -1986,6 +2174,9 @@ struct AzimPlaneIntersector double d1 = _plane.distance(v1); double d2 = _plane.distance(v2); + edge->_p1Outside = _lowerOutside ? (d1<0.0) : (d1>0.0); + edge->_p2Outside = _lowerOutside ? (d2<0.0) : (d2>0.0); + // if both points inside then disgard if (d1<0.0 && d2<0.0) return false; @@ -2038,12 +2229,14 @@ struct AzimPlaneIntersector struct ElevationIntersector { - ElevationIntersector(TriangleIntersectOperator& tif, double elev): + ElevationIntersector(TriangleIntersectOperator& tif, double elev, bool lowerOutside): _tif(tif), - _elev(elev) {} + _elev(elev), + _lowerOutside(lowerOutside) {} TriangleIntersectOperator& _tif; double _elev; + bool _lowerOutside; inline bool operator() (TriangleIntersectOperator::Edge* edge) { @@ -2058,6 +2251,9 @@ struct ElevationIntersector double length_xy2 = sqrt(v2.x()*v2.x() + v2.y()*v2.y()); double elev2 = atan2(v2.z(),length_xy2); + edge->_p1Outside = _lowerOutside ? (elev1<_elev) : (elev1>_elev); + edge->_p2Outside = _lowerOutside ? (elev2<_elev) : (elev2>_elev); + // if both points inside then disgard if (elev1<_elev && elev2<_elev) return false; @@ -2138,6 +2334,9 @@ struct RadiusIntersector double radius1 = v1.length(); double radius2 = v2.length(); + edge->_p1Outside = radius1>_tif._radius; + edge->_p2Outside = radius2>_tif._radius; + // if both points inside then disgard if (radius1<_tif._radius && radius2<_tif._radius) return false; @@ -2194,6 +2393,7 @@ struct RadiusIntersector double one_minus_r = 1.0-r; edge->_intersectionType = TriangleIntersectOperator::Edge::MID_POINT; edge->_intersectionVertex = v1*one_minus_r + v2*r; + } return true; @@ -2230,33 +2430,26 @@ void TriangleIntersectOperator::countMultipleIntersections() osg::notify(osg::NOTICE)<<"Testing Polygon with numIntersections = "<0 && !singleIntersectFound) + if (numIntersections>0) { +#if 1 + polygon.createLine(*this, _generatedLines); +#else + osg::notify(osg::NOTICE)<<"Testing Polygon with numIntersections = "<push_back(_originalVertices[tri->_p1]+_centre); newLine->push_back(_originalVertices[tri->_p2]+_centre); newLine->push_back(_originalVertices[tri->_p3]+_centre); newLine->push_back(_originalVertices[tri->_p1]+_centre); _generatedLines.push_back(newLine); +#endif } } @@ -2302,10 +2495,10 @@ SphereSegment::LineList SphereSegment::computeIntersection(const osg::Matrixd& m tif.buildEdges(); tif.computeIntersections(RadiusIntersector(tif)); - tif.computeIntersections(AzimIntersector(tif,_azMin)); - tif.computeIntersections(AzimIntersector(tif,_azMax)); - tif.computeIntersections(ElevationIntersector(tif,_elevMin)); - tif.computeIntersections(ElevationIntersector(tif,_elevMax)); + tif.computeIntersections(AzimIntersector(tif,_azMin, true)); + tif.computeIntersections(AzimIntersector(tif,_azMax, false)); + tif.computeIntersections(ElevationIntersector(tif,_elevMin, true)); + tif.computeIntersections(ElevationIntersector(tif,_elevMax, false)); tif.countMultipleIntersections();