From 06401ba12922692f0107ce988999c739ffcad9e8 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 30 Sep 2005 19:36:22 +0000 Subject: [PATCH] Changed the line intersection algorithm to computer full line intersections then trim down to size by intersecting with the sphere segmenet sufaces --- src/osgSim/SphereSegment.cpp | 370 ++++++++++++++++++++++++++++++----- 1 file changed, 318 insertions(+), 52 deletions(-) diff --git a/src/osgSim/SphereSegment.cpp b/src/osgSim/SphereSegment.cpp index 60dd7ff31..000c2fd8f 100644 --- a/src/osgSim/SphereSegment.cpp +++ b/src/osgSim/SphereSegment.cpp @@ -1393,10 +1393,6 @@ struct TriangleIntersectOperator double rad2 = vertex.length2(); double length_xy = sqrtf(vertex.x()*vertex.x() + vertex.y()*vertex.y()); double elevation = atan2((double)vertex.z(),length_xy); - double azim = atan2(vertex.x(),vertex.y()); - double azimDelta1 = azim-azimCenter; - double azimDelta2 = 2.0*osg::PI + azim-azimCenter; - double azimDelta = std::min(fabs(azimDelta1), fabs(azimDelta2)); // radius surface if (rad2 > radius2) _radiusSurface = OUTSIDE; @@ -1413,29 +1409,37 @@ struct TriangleIntersectOperator else if (elevationazimRange) + + double dot_alphaMin = cos(azimMin)*vertex.x() - sin(azimMin)*vertex.y(); + if (dot_alphaMin<0.0) _leftSurface = OUTSIDE; + else if (dot_alphaMin>0.0) _leftSurface = INSIDE; + else _leftSurface = INTERSECTS; + + double dot_alphaMax = cos(azimMax)*vertex.x() - sin(azimMax)*vertex.y(); + if (dot_alphaMax>0.0) _rightSurface = OUTSIDE; + else if (dot_alphaMax<0.0) _rightSurface = INSIDE; + else _rightSurface = INTERSECTS; + + double azim = atan2(vertex.x(),vertex.y()); + double azimDelta1 = azim-azimCenter; + double azimDelta2 = 2.0*osg::PI + azim-azimCenter; + double azimDelta = std::min(fabs(azimDelta1), fabs(azimDelta2)); + if (azimDelta>azimRange) { - _leftSurface = (azimDelta<-azimRange || azimDelta>(osg::PI-azimRange)) ? OUTSIDE : INSIDE; - _rightSurface = (azimDelta>azimRange || azimDelta<(azimRange-osg::PI)) ? OUTSIDE : INSIDE; + _leftRightSurfaces = OUTSIDE; } - else if (azimDelta==-azimRange) + else if (azimDelta_p2]); rc.add(_regions[tri->_p3]); int numIntersections = rc.numberOfIntersectingSurfaces(); + #if 0 if (numIntersections==1) { buildEdges(tri); } + #else + if (numIntersections>=1) + { + buildEdges(tri); + } + #endif + #else buildEdges(tri); #endif @@ -1826,11 +1847,13 @@ struct TriangleIntersectOperator void countMultipleIntersections(); - void connectIntersections(EdgeList& hitEdges) + SphereSegment::LineList connectIntersections(EdgeList& hitEdges) { + SphereSegment::LineList lineList; + osg::notify(osg::NOTICE)<<"Number of edge intersections "<get(); while (edge) @@ -1950,12 +1973,12 @@ struct TriangleIntersectOperator edge = newEdge; } - } + return lineList; } template - void computeIntersections(I intersector) + SphereSegment::LineList computeIntersections(I intersector) { // collect all the intersecting edges EdgeList hitEdges; @@ -1970,8 +1993,86 @@ struct TriangleIntersectOperator } } - connectIntersections(hitEdges); + return connectIntersections(hitEdges); } + + template + void trim(SphereSegment::LineList& lineList, osg::Vec3Array* sourceLine, I intersector) + { + if (sourceLine->empty()) return; + + osg::notify(osg::NOTICE)<<"Testing line of "<size()<size()) + { + // find first valid vertex. + for(; firstsize(); ++first) + { + if (intersector.distance((*sourceLine)[first]-_centre)>=0.0) break; + } + + if (first==sourceLine->size()) + { + osg::notify(osg::NOTICE)<<"No valid points found"<size(); ++last) + { + if (intersector.distance((*sourceLine)[last]-_centre)<0.0) break; + } + + if (first==0 && last==sourceLine->size()) + { + osg::notify(osg::NOTICE)<<"Copying complete line"<0) + { + newLine->push_back(intersector.intersectionPoint((*sourceLine)[first-1]-_centre, (*sourceLine)[first]-_centre)+_centre); + } + + for(unsigned int i=first; ipush_back((*sourceLine)[i]); + } + if (lastsize()) + { + newLine->push_back(intersector.intersectionPoint((*sourceLine)[last-1]-_centre, (*sourceLine)[last]-_centre)+_centre); + } + + lineList.push_back(newLine); + } + + first = last; + } + } + + template + void trim(SphereSegment::LineList& lineList, I intersector) + { + SphereSegment::LineList newLines; + + // collect all the intersecting edges + for(SphereSegment::LineList::iterator itr = lineList.begin(); + itr != lineList.end(); + ++itr) + { + osg::Vec3Array* line = itr->get(); + trim(newLines, line, intersector); + } + lineList.swap(newLines); + } + }; bool computeQuadraticSolution(double a, double b, double c, double& s1, double& s2) @@ -2077,10 +2178,12 @@ struct AzimPlaneIntersector _lowerOutside(lowerOutside) { _plane.set(cos(azim),-sin(azim),0.0,0.0); + _endPlane.set(sin(azim),cos(azim),0.0,0.0); } TriangleIntersectOperator& _tif; osg::Plane _plane; + osg::Plane _endPlane; bool _lowerOutside; inline bool operator() (TriangleIntersectOperator::Edge* edge) @@ -2102,6 +2205,12 @@ struct AzimPlaneIntersector // if both points outside then disgard if (d1>0.0 && d2>0.0) return false; +#if 0 + double e1 = _endPlane.distance(v1); + double e2 = _endPlane.distance(v2); + if (e1<0.0 && e2<0.0) return false; +#endif + if (d1==0.0) { if (d2==0.0) @@ -2144,6 +2253,30 @@ struct AzimPlaneIntersector return true; } + + // compute the intersection between line segment and surface + osg::Vec3 intersectionPoint(const osg::Vec3& v1, const osg::Vec3& v2) + { + double d1 = _plane.distance(v1); + double d2 = _plane.distance(v2); + + double div = d2-d1; + if (div==0.0) + { + return v1; + } + + double r = -d1 / div; + double one_minus_r = 1.0-r; + + return v1*one_minus_r + v2*r; + } + + // positive distance to the inside. + double distance(const osg::Vec3& v) + { + return _lowerOutside ? _plane.distance(v) : -_plane.distance(v) ; + } }; struct ElevationIntersector @@ -2235,6 +2368,53 @@ struct ElevationIntersector return true; } + + // compute the intersection between line segment and surface + osg::Vec3 intersectionPoint(const osg::Vec3& v1, const osg::Vec3& v2) + { + double dx = v2.x()-v1.x(); + double dy = v2.y()-v1.y(); + double dz = v2.z()-v1.z(); + double t = tan(_elev); + double tt = t*t; + double a = dz*dz-tt*(dx*dx + dy*dy); + double b = 2.0*(v1.z()*dz - tt*(v1.x()*dx + v1.y()*dy)); + double c = v1.z()*v1.z() - tt*(v1.x()*v1.x() + v1.y()*v1.y()); + + double s1, s2; + if (!computeQuadraticSolution(a,b,c,s1,s2)) + { + osg::notify(osg::NOTICE)<<"Warning::neither segment intersects s1="<