Various improvements to the sphere segment intersection code.

This commit is contained in:
Robert Osfield 2005-09-27 12:15:40 +00:00
parent 5731ea2352
commit 600349dce8

View File

@ -19,6 +19,7 @@
#include <osg/Transform>
#include <osg/Geometry>
#include <osg/TriangleIndexFunctor>
#include <osg/ShapeDrawable>
#include <osg/io_utils>
#include <algorithm>
@ -1119,6 +1120,49 @@ SphereSegment::LineList SphereSegment::computeIntersection(const osg::Matrixd& t
return all_lines;
}
osg::Node* SphereSegment::computeIntersectionSubgraph(const osg::Matrixd& transform, osg::Node* subgraph)
{
osg::notify(osg::NOTICE)<<"Creating line intersection between sphere segment and subgraph."<<std::endl;
osg::BoundingBox bb = getBoundingBox();
osg::Polytope polytope;
polytope.add(osg::Plane(1.0,0.0,0.0,-bb.xMin()));
polytope.add(osg::Plane(-1.0,0.0,0.0,bb.xMax()));
polytope.add(osg::Plane(0.0,1.0,0.0,-bb.yMin()));
polytope.add(osg::Plane(0.0,-1.0,0.0,bb.yMax()));
polytope.add(osg::Plane(0.0,0.0,1.0,-bb.zMin()));
polytope.add(osg::Plane(0.0,0.0,-1.0,bb.zMax()));
osg::Plane pl;
pl.set(osg::Vec3(-1.0,0.0,0.0), bb.corner(0));
PolytopeVisitor polytopeVisitor(transform, polytope);
subgraph->accept(polytopeVisitor);
if (polytopeVisitor.getHits().empty())
{
osg::notify(osg::NOTICE)<<"No hits found."<<std::endl;
return 0;
}
// create a LineList to store all the compute line segments
osg::Group* group = new osg::Group;
// compute the line intersections with each of the hit drawables
osg::notify(osg::NOTICE)<<"Hits found. "<<polytopeVisitor.getHits().size()<<std::endl;
PolytopeVisitor::HitList& hits = polytopeVisitor.getHits();
for(PolytopeVisitor::HitList::iterator itr = hits.begin();
itr != hits.end();
++itr)
{
group->addChild(computeIntersectionSubgraph(itr->_matrix, itr->_drawable.get()));
}
// join all the lines that have ends that are close together..
return group;
}
struct dereference_less
{
@ -1158,6 +1202,16 @@ struct TriangleIntersectOperator
_numInside(0),
_numIntersecting(0) {}
enum SurfaceType
{
NO_SURFACE = 0,
RADIUS_SURFACE,
LEFT_SURFACE,
RIGHT_SURFACE,
BOTTOM_SURFACE,
TOP_SURFACE
};
struct Triangle;
struct Edge : public osg::Referenced
@ -1173,7 +1227,7 @@ struct TriangleIntersectOperator
BOTH_ENDS
};
Edge(unsigned int p1, unsigned int p2, bool intersectionEdge=false):
Edge(unsigned int p1, unsigned int p2, SurfaceType intersectionEdge=NO_SURFACE):
_intersectionType(NO_INTERSECTION),
_intersectionVertexIndex(0),
_p1Outside(false),
@ -1226,7 +1280,7 @@ struct TriangleIntersectOperator
bool _p1Outside;
bool _p2Outside;
TriangleList _toTraverse;
bool _intersectionEdge;
SurfaceType _intersectionEdge;
};
typedef std::list< osg::ref_ptr<Edge> > EdgeList;
@ -1305,197 +1359,9 @@ struct TriangleIntersectOperator
}
template<class I>
unsigned int computeHitEdges(TriangleIntersectOperator& tio, I intersector)
{
// collect all the intersecting edges
EdgeList hitEdges;
for(EdgeList::iterator itr = _edges.begin();
itr != _edges.end();
++itr)
{
Edge* edge = const_cast<Edge*>(itr->get());
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"<<hitEdges.size()<<std::endl;
while (hitEdges.size()>=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<Edge*>(itr->get());
if (!(edge->completlyOutside()))
{
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"<<std::endl;
}
}
}
}
_edges.swap(newEdgeList);
return numHitEdges;
}
unsigned int computeHitEdges(TriangleIntersectOperator& tio, I intersector, SurfaceType surfaceType);
bool createLine(TriangleIntersectOperator& tio, SphereSegment::LineList& generatedLines) const
{
osg::notify(osg::NOTICE)<<"createLine "<<_edges.size()<<std::endl;
typedef std::vector< osg::ref_ptr<Edge> > 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<<std::endl;
edges.push_back(*itr);
}
else
{
osg::notify(osg::NOTICE)<<" disgarding edge "<<(*itr)->_p1<<" "<<(*itr)->_p2<<std::endl;
}
}
if (edges.empty()) return false;
// find open edge.
unsigned int i=0;
unsigned int numMatchesFor_p1=0;
unsigned int numMatchesFor_p2=0;
for(i=0; i<edges.size()-1; ++i)
{
numMatchesFor_p1=0;
numMatchesFor_p2=0;
for(unsigned j=i+1; j<edges.size(); ++j)
{
if ((edges[i]->_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> 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 "<<edge->_p1<<" "<<edge->_p2<<" activePoint="<<activePoint<<std::endl;
while (!edges.empty())
{
bool intersectionFound = false;
for(EdgeVector::iterator itr = edges.begin();
itr != edges.end() && !intersectionFound;
++itr)
{
if ((*itr)->_p1 == activePoint)
{
activePoint = (*itr)->_p2;
newLine->push_back(tio._originalVertices[activePoint]+tio._centre);
osg::notify(osg::NOTICE)<<"A Found "<<(*itr)->_p1<<" "<<(*itr)->_p2<<" activePoint="<<activePoint<<std::endl;
edges.erase(itr);
intersectionFound = true;
}
else if ((*itr)->_p2 == activePoint)
{
activePoint = (*itr)->_p1;
newLine->push_back(tio._originalVertices[activePoint]+tio._centre);
osg::notify(osg::NOTICE)<<"B Found "<<(*itr)->_p1<<" "<<(*itr)->_p2<<" activePoint="<<activePoint<<std::endl;
edges.erase(itr);
intersectionFound = true;
}
}
if (!intersectionFound)
{
// start a new line, add it to the list of lines.
newLine = new osg::Vec3Array;
generatedLines.push_back(newLine);
osg::ref_ptr<Edge> 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 "<<edge->_p1<<" "<<edge->_p2<<" activePoint="<<activePoint<<std::endl;
}
}
return true;
}
bool createLine(TriangleIntersectOperator& tio, SphereSegment::LineList& generatedLines) const;
EdgeList _edges;
@ -1521,13 +1387,17 @@ struct TriangleIntersectOperator
void classify(const osg::Vec3& vertex, double radius2, double azimMin, double azimMax, double elevMin, double elevMax)
{
double azimCenter = (azimMax+azimMin)*0.5;
double azimRange = (azimMax-azimMin)*0.5;
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());
if (azim<0.0) azim += 2.0*osg::PI;
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;
else if (rad2 < radius2) _radiusSurface = INSIDE;
@ -1543,15 +1413,26 @@ struct TriangleIntersectOperator
else if (elevation<elevMax) _topSurface = INSIDE;
else _topSurface = INTERSECTS;
// left surface
if (azim<azimMin) _leftSurface = OUTSIDE;
else if (azim>azimMin) _leftSurface = INSIDE;
else _leftSurface = INTERSECTS;
// right surface
if (azim>azimMax) _rightSurface = OUTSIDE;
else if (azim<azimMax) _rightSurface = INSIDE;
else _rightSurface = INTERSECTS;
if (fabs(azimDelta)>azimRange)
{
_leftSurface = (azimDelta<-azimRange || azimDelta>(osg::PI-azimRange)) ? OUTSIDE : INSIDE;
_rightSurface = (azimDelta>azimRange || azimDelta<(azimRange-osg::PI)) ? OUTSIDE : INSIDE;
}
else if (azimDelta==-azimRange)
{
_leftSurface = INTERSECTS;
_rightSurface = INSIDE;
}
else if (azimDelta==azimRange)
{
_leftSurface = INSIDE;
_rightSurface = INTERSECTS;
}
else
{
_leftSurface = INSIDE;
_rightSurface = INSIDE;
}
}
Classification _radiusSurface;
@ -1626,6 +1507,44 @@ struct TriangleIntersectOperator
return Region::INTERSECTS;
}
Region::Classification overallClassification(SurfaceType surfaceType, SurfaceType assocatedSurfaceType) const
{
// if all vertices are outside any of the surfaces then we are completely outside
if ((assocatedSurfaceType!=RADIUS_SURFACE && surfaceType!=RADIUS_SURFACE && _outside_radiusSurface==_numVertices) ||
(assocatedSurfaceType!=LEFT_SURFACE && surfaceType!=LEFT_SURFACE && _outside_leftSurface==_numVertices) ||
(assocatedSurfaceType!=RIGHT_SURFACE && surfaceType!=RIGHT_SURFACE && _outside_rightSurface==_numVertices) ||
(assocatedSurfaceType!=TOP_SURFACE && surfaceType!=TOP_SURFACE && _outside_topSurface==_numVertices) ||
(assocatedSurfaceType!=BOTTOM_SURFACE && surfaceType!=BOTTOM_SURFACE && _outside_bottomSurface==_numVertices)) return Region::OUTSIDE;
// if all the vertices on all the sides and inside then we are completely inside
if ((assocatedSurfaceType!=RADIUS_SURFACE && surfaceType!=RADIUS_SURFACE && _inside_radiusSurface==_numVertices) &&
(assocatedSurfaceType!=LEFT_SURFACE && surfaceType!=LEFT_SURFACE && _inside_leftSurface==_numVertices) &&
(assocatedSurfaceType!=RIGHT_SURFACE && surfaceType!=RIGHT_SURFACE && _inside_rightSurface==_numVertices) &&
(assocatedSurfaceType!=TOP_SURFACE && surfaceType!=TOP_SURFACE && _inside_topSurface==_numVertices) &&
(assocatedSurfaceType!=BOTTOM_SURFACE && surfaceType!=BOTTOM_SURFACE && _inside_bottomSurface==_numVertices)) return Region::INSIDE;
return Region::INTERSECTS;
}
bool intersecting(SurfaceType surfaceType) const
{
// if all vertices are outside any of the surfaces then we are completely outside
if ((surfaceType!=RADIUS_SURFACE && _outside_radiusSurface!=0) ||
(surfaceType!=LEFT_SURFACE && _outside_leftSurface!=0) ||
(surfaceType!=RIGHT_SURFACE && _outside_rightSurface!=0) ||
(surfaceType!=TOP_SURFACE && _outside_topSurface!=0) ||
(surfaceType!=BOTTOM_SURFACE && _outside_bottomSurface!=0)) return false;
// if all the vertices on all the sides and inside then we are completely inside
if ((surfaceType!=RADIUS_SURFACE && _inside_radiusSurface!=0) &&
(surfaceType!=LEFT_SURFACE && _inside_leftSurface!=0) &&
(surfaceType!=RIGHT_SURFACE && _inside_rightSurface!=0) &&
(surfaceType!=TOP_SURFACE && _inside_topSurface!=0) &&
(surfaceType!=BOTTOM_SURFACE && _inside_bottomSurface!=0)) return false;
return true;
}
int numberOfIntersectingSurfaces() const
{
int sidesThatIntersect = 0;
@ -2401,6 +2320,254 @@ struct RadiusIntersector
};
template<class I>
unsigned int TriangleIntersectOperator::Polygon::computeHitEdges(TriangleIntersectOperator& tio, I intersector, SurfaceType surfaceType)
{
// collect all the intersecting edges
EdgeList hitEdges;
for(EdgeList::iterator itr = _edges.begin();
itr != _edges.end();
++itr)
{
Edge* edge = const_cast<Edge*>(itr->get());
if (intersector(edge)) hitEdges.push_back(edge);
}
if (hitEdges.empty()) return 0;
unsigned int numHitEdges = hitEdges.size();
EdgeList newEdgeList;
double radius2 = tio._radius*tio._radius;
osg::notify(osg::NOTICE)<<"Num Hit edges"<<hitEdges.size()<<std::endl;
while (hitEdges.size()>=2)
{
Edge* edge1 = hitEdges.front().get(); hitEdges.pop_front();
int p1 = tio._originalVertices.size();
edge1->_intersectionVertexIndex = p1;
tio._originalVertices.push_back(edge1->_intersectionVertex);
tio._regions.push_back(Region());
tio._regions[p1].classify(edge1->_intersectionVertex, radius2, tio._azMin, tio._azMax, tio._elevMin, tio._elevMax);
Edge* edge2 = hitEdges.front().get(); hitEdges.pop_front();
int p2 = tio._originalVertices.size();
edge2->_intersectionVertexIndex = p2;
tio._originalVertices.push_back(edge2->_intersectionVertex);
tio._regions.push_back(Region());
tio._regions[p2].classify(edge2->_intersectionVertex, radius2, tio._azMin, tio._azMax, tio._elevMin, tio._elevMax);
newEdgeList.push_back(new Edge(p1,p2,surfaceType));
}
for(EdgeList::iterator itr = _edges.begin();
itr != _edges.end();
++itr)
{
Edge* edge = const_cast<Edge*>(itr->get());
if (!(edge->completlyOutside()))
{
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"<<std::endl;
}
}
}
}
_edges.swap(newEdgeList);
return numHitEdges;
}
bool TriangleIntersectOperator::Polygon::createLine(TriangleIntersectOperator& tio, SphereSegment::LineList& generatedLines) const
{
SurfaceType adjacentEdge[] =
{
NO_SURFACE,
NO_SURFACE, // adjacent to RADIUS_SURFACE,
RIGHT_SURFACE, // adjacent to LEFT_SURFACE,
LEFT_SURFACE, // adjacent to RIGHT_SURFACE,
TOP_SURFACE, // adjacent to BOTTOM_SURFACE,
BOTTOM_SURFACE, // adjacent to TOP_SURFACE
};
osg::notify(osg::NOTICE)<<"createLine "<<_edges.size()<<std::endl;
typedef std::vector< osg::ref_ptr<Edge> > EdgeVector;
EdgeVector edges;
for(EdgeList::const_iterator itr = _edges.begin();
itr != _edges.end();
++itr)
{
#if 0
// if ((*itr)->_intersectionEdge)
{
edges.push_back(*itr);
}
#else
if ((*itr)->_intersectionEdge)
{
RegionCounter rc;
rc.add(tio._regions[(*itr)->_p1]);
rc.add(tio._regions[(*itr)->_p2]);
#if 1
Region::Classification classification = rc.overallClassification((*itr)->_intersectionEdge, adjacentEdge[(*itr)->_intersectionEdge]);
// Region::Classification classification = rc.overallClassification();
// reject if outside.
if (classification==Region::OUTSIDE)
{
osg::notify(osg::NOTICE)<<" disgarding outside edge "<<(*itr)->_p1<<" "<<(*itr)->_p2<<std::endl;
edges.push_back(*itr);
}
else if (classification==Region::INSIDE)
{
osg::notify(osg::NOTICE)<<" disgarding inside edge "<<(*itr)->_p1<<" "<<(*itr)->_p2<<std::endl;
// edges.push_back(*itr);
}
else
{
osg::notify(osg::NOTICE)<<" accepting edge "<<(*itr)->_p1<<" "<<(*itr)->_p2<<std::endl;
edges.push_back(*itr);
}
#else
if (rc.intersecting((*itr)->_intersectionEdge))
{
osg::notify(osg::NOTICE)<<" accepting edge "<<(*itr)->_p1<<" "<<(*itr)->_p2<<std::endl;
edges.push_back(*itr);
}
#endif
}
else
{
osg::notify(osg::NOTICE)<<" disgarding edge "<<(*itr)->_p1<<" "<<(*itr)->_p2<<std::endl;
}
#endif
}
if (edges.empty()) return false;
// find open edge.
unsigned int i=0;
unsigned int numMatchesFor_p1=0;
unsigned int numMatchesFor_p2=0;
for(i=0; i<edges.size()-1; ++i)
{
numMatchesFor_p1=0;
numMatchesFor_p2=0;
for(unsigned j=i+1; j<edges.size(); ++j)
{
if ((edges[i]->_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> 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 "<<edge->_p1<<" "<<edge->_p2<<" activePoint="<<activePoint<<std::endl;
while (!edges.empty())
{
bool intersectionFound = false;
for(EdgeVector::iterator itr = edges.begin();
itr != edges.end() && !intersectionFound;
++itr)
{
if ((*itr)->_p1 == activePoint)
{
activePoint = (*itr)->_p2;
newLine->push_back(tio._originalVertices[activePoint]+tio._centre);
osg::notify(osg::NOTICE)<<"A Found "<<(*itr)->_p1<<" "<<(*itr)->_p2<<" activePoint="<<activePoint<<std::endl;
edges.erase(itr);
intersectionFound = true;
}
else if ((*itr)->_p2 == activePoint)
{
activePoint = (*itr)->_p1;
newLine->push_back(tio._originalVertices[activePoint]+tio._centre);
osg::notify(osg::NOTICE)<<"B Found "<<(*itr)->_p1<<" "<<(*itr)->_p2<<" activePoint="<<activePoint<<std::endl;
edges.erase(itr);
intersectionFound = true;
}
}
if (!intersectionFound)
{
// start a new line, add it to the list of lines.
newLine = new osg::Vec3Array;
generatedLines.push_back(newLine);
osg::ref_ptr<Edge> 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 "<<edge->_p1<<" "<<edge->_p2<<" activePoint="<<activePoint<<std::endl;
}
}
return true;
}
void TriangleIntersectOperator::countMultipleIntersections()
{
osg::notify(osg::NOTICE)<<"countMultipleIntersections("<<std::endl;
@ -2431,11 +2598,11 @@ void TriangleIntersectOperator::countMultipleIntersections()
osg::notify(osg::NOTICE)<<"Testing Polygon with numIntersections = "<<numIntersections<<std::endl;
Polygon polygon(tri);
numIntersections=0;
numIntersections += polygon.computeHitEdges(*this, RadiusIntersector(*this));
numIntersections += polygon.computeHitEdges(*this, AzimPlaneIntersector(*this,_azMin, true));
numIntersections += polygon.computeHitEdges(*this, AzimPlaneIntersector(*this,_azMax, false));
numIntersections += polygon.computeHitEdges(*this, ElevationIntersector(*this,_elevMin, true));
numIntersections += polygon.computeHitEdges(*this, ElevationIntersector(*this,_elevMax, false));
numIntersections += polygon.computeHitEdges(*this, RadiusIntersector(*this), RADIUS_SURFACE);
numIntersections += polygon.computeHitEdges(*this, AzimPlaneIntersector(*this,_azMin, true), LEFT_SURFACE);
numIntersections += polygon.computeHitEdges(*this, AzimPlaneIntersector(*this,_azMax, false), RIGHT_SURFACE);
numIntersections += polygon.computeHitEdges(*this, ElevationIntersector(*this,_elevMin, true), BOTTOM_SURFACE);
numIntersections += polygon.computeHitEdges(*this, ElevationIntersector(*this,_elevMax, false), TOP_SURFACE);
if (numIntersections>0)
{
@ -2504,3 +2671,99 @@ SphereSegment::LineList SphereSegment::computeIntersection(const osg::Matrixd& m
return tif._generatedLines;
}
osg::Node* SphereSegment::computeIntersectionSubgraph(const osg::Matrixd& matrix, osg::Drawable* drawable)
{
// cast to Geometry, return empty handed if Drawable not a Geometry.
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable);
if (!geometry) return 0;
// get vertices from geometry, return empty handed if a Vec3Array not present.
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
if (!vertices) return 0;
typedef osg::TriangleIndexFunctor<TriangleIntersectOperator> TriangleIntersectFunctor;
TriangleIntersectFunctor tif;
tif._centre = _centre;
tif._radius = _radius;
tif._azMin = _azMin;
tif._azMax = _azMax;
tif._elevMin = _elevMin;
tif._elevMax = _elevMax;
tif.computePositionAndRegions(matrix, *vertices);
// traverse the triangles in the Geometry dedicating intersections
geometry->accept(tif);
osg::notify(osg::NOTICE)<<"_numOutside = "<<tif._numOutside<<std::endl;
osg::notify(osg::NOTICE)<<"_numInside = "<<tif._numInside<<std::endl;
osg::notify(osg::NOTICE)<<"_numIntersecting = "<<tif._numIntersecting<<std::endl;
tif.removeDuplicateVertices();
tif.removeDuplicateTriangles();
tif.buildEdges();
tif.computeIntersections(RadiusIntersector(tif));
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();
osg::Geode* geode = new osg::Geode;
geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
for(osgSim::SphereSegment::LineList::iterator itr=tif._generatedLines.begin();
itr!=tif._generatedLines.end();
++itr)
{
osg::Geometry* geom = new osg::Geometry;
geode->addDrawable(geom);
osg::Vec3Array* vertices = itr->get();
geom->setVertexArray(vertices);
geom->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, vertices->getNumElements()));
}
float radius = 0.1f;
for(unsigned int i=0; i<tif._originalVertices.size(); ++i)
{
osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(tif._originalVertices[i]+tif._centre,radius));
TriangleIntersectFunctor::RegionCounter rc;
rc.add(tif._regions[i]);
#if 0
unsigned int _outside_leftSurface;
unsigned int _inside_leftSurface;
unsigned int _intersects_leftSurface;
unsigned int _outside_rightSurface;
unsigned int _inside_rightSurface;
unsigned int _intersects_rightSurface;
#else
TriangleIntersectFunctor::Region::Classification region = rc.overallClassification();
if (region==TriangleIntersectFunctor::Region::OUTSIDE)
{
sd->setColor(osg::Vec4(1.0,0.0,0.0,1.0));
}
else if (region==TriangleIntersectFunctor::Region::INSIDE)
{
sd->setColor(osg::Vec4(1.0,1.0,0.0,1.0));
}
else if (region==TriangleIntersectFunctor::Region::INTERSECTS)
{
sd->setColor(osg::Vec4(1.0,1.0,1.0,1.0));
}
#endif
geode->addDrawable(sd);
}
return geode;
}