From ba5c7cdc9145bed179b6f090f6357eb0f3fddc7e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 3 Oct 2005 16:13:26 +0000 Subject: [PATCH] Added fusing of ends of lines --- src/osgSim/SphereSegment.cpp | 260 +++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) diff --git a/src/osgSim/SphereSegment.cpp b/src/osgSim/SphereSegment.cpp index b36208c72..e2e057c79 100644 --- a/src/osgSim/SphereSegment.cpp +++ b/src/osgSim/SphereSegment.cpp @@ -2209,6 +2209,255 @@ struct TriangleIntersectOperator } lineList.swap(newLines); } + + struct LinePair + { + LinePair(osg::Vec3Array* line): + _line(line), + _lineEnd(0), + _neighbourLine(0), + _neighbourLineEnd(0) {} + + bool operator < (const LinePair& linePair) const + { + return _distance < linePair._distance; + } + + void consider(osg::Vec3Array* testline) + { + if (_neighbourLine.valid()) + { + float distance = ((*_line)[0]-(*testline)[0]).length(); + if (distance<_distance) + { + _lineEnd = 0; + _neighbourLine = testline; + _neighbourLineEnd = 0; + _distance = distance; + } + + distance = ((*_line)[0]-(*testline)[testline->size()-1]).length(); + if (distance<_distance) + { + _lineEnd = 0; + _neighbourLine = testline; + _neighbourLineEnd = testline->size()-1; + _distance = distance; + } + + distance = ((*_line)[_line->size()-1]-(*testline)[0]).length(); + if (distance<_distance) + { + _lineEnd = _line->size()-1; + _neighbourLine = testline; + _neighbourLineEnd = 0; + _distance = distance; + } + + distance = ((*_line)[_line->size()-1]-(*testline)[testline->size()-1]).length(); + if (distance<_distance) + { + _lineEnd = _line->size()-1; + _neighbourLine = testline; + _neighbourLineEnd = testline->size()-1; + _distance = distance; + } + + } + else + { + _neighbourLine = testline; + if (_neighbourLine==_line) + { + _lineEnd = 0; + _neighbourLineEnd = _neighbourLine->size()-1; + _distance = ((*_line)[_lineEnd]-(*_neighbourLine)[_neighbourLineEnd]).length(); + } + else + { + _distance = ((*_line)[0]-(*_neighbourLine)[0]).length(); + _lineEnd = 0; + _neighbourLineEnd = 0; + + float distance = ((*_line)[0]-(*_neighbourLine)[_neighbourLine->size()-1]).length(); + if (distance<_distance) + { + _lineEnd = 0; + _neighbourLineEnd = _neighbourLine->size()-1; + _distance = distance; + } + + distance = ((*_line)[_line->size()-1]-(*_neighbourLine)[0]).length(); + if (distance<_distance) + { + _lineEnd = _line->size()-1; + _neighbourLineEnd = 0; + _distance = distance; + } + + distance = ((*_line)[_line->size()-1]-(*_neighbourLine)[_neighbourLine->size()-1]).length(); + if (distance<_distance) + { + _lineEnd = _line->size()-1; + _neighbourLineEnd = _neighbourLine->size()-1; + _distance = distance; + } + } + } + }; + + bool contains(osg::Vec3Array* line) const + { + return _line==line || _neighbourLine==line; + } + + + osg::ref_ptr _line; + unsigned int _lineEnd; + osg::ref_ptr _neighbourLine; + unsigned int _neighbourLineEnd; + float _distance; + }; + + void fuseEnds(float fuseDistance) + { + SphereSegment::LineList fusedLines; + SphereSegment::LineList unfusedLines; + + // first seperat the already fused lines from the unfused ones. + for(SphereSegment::LineList::iterator itr = _generatedLines.begin(); + itr != _generatedLines.end(); + ++itr) + { + osg::Vec3Array* line = itr->get(); + if (line->size()>=2) + { + if ((*line)[0]==(*line)[line->size()-1]) + { + fusedLines.push_back(line); + } + else + { + unfusedLines.push_back(line); + } + } + } + + while (unfusedLines.size()>=1) + { + // generate a set of line pairs to establish which + // line pair has the minimum distance. + typedef std::multiset LinePairSet; + LinePairSet linePairs; + for(unsigned int i=0; i_line.get()<<" "<_lineEnd<<" neighbour "<_neighbourLine.get()<<" "<_neighbourLineEnd<<" distance="<_distance< fuseDistance) + { + osg::notify(osg::NOTICE)<<"Completed work, shortest distance left is "<size()-1])*0.5f; + (*line)[0] = average; + (*line)[line->size()-1] = average; + fusedLines.push_back(line); + + SphereSegment::LineList::iterator fitr = std::find(unfusedLines.begin(), unfusedLines.end(), line); + if (fitr != unfusedLines.end()) + { + unfusedLines.erase(fitr); + } + else + { + osg::notify(osg::NOTICE)<<"Error couldn't find line in unfused list, exiting fusing loop."<size()-1 : 0; + int direction1 = openEnd1size()-1 : 0; + int direction2 = fuseEnd2push_back((*line1)[i]); + } + + // add the average of the two fused ends + osg::Vec3 average = ((*line1)[fuseEnd1] + (*line2)[fuseEnd2])*0.5f; + newline->push_back(average); + + // copy across from the next point in from fuseEnd2 to the openEnd2. + for(int j=fuseEnd2 + direction2; + j != openEnd2 + direction2; + j += direction2) + { + newline->push_back((*line2)[j]); + } + + // remove line1 from unfused list. + SphereSegment::LineList::iterator fitr = std::find(unfusedLines.begin(), unfusedLines.end(), line1); + if (fitr != unfusedLines.end()) + { + unfusedLines.erase(fitr); + } + + // remove line2 from unfused list. + fitr = std::find(unfusedLines.begin(), unfusedLines.end(), line2); + if (fitr != unfusedLines.end()) + { + unfusedLines.erase(fitr); + } + + // add the newline into the unfused for further processing. + unfusedLines.push_back(newline); + + osg::notify(osg::NOTICE)<<"Fusing two seperate lines "<