+
+
+//============ Auxiliary functions ========================================================
+
+static std::pair<GeomPointPtr, GeomPointPtr> edgeBoundaries(const GeomEdgePtr& theEdge)
+{
+ GeomPointPtr aStart = theEdge->firstPoint();
+ GeomPointPtr anEnd = theEdge->lastPoint();
+ if (theEdge->orientation() == GeomAPI_Shape::REVERSED)
+ std::swap(aStart, anEnd);
+ return std::pair<GeomPointPtr, GeomPointPtr>(aStart, anEnd);
+}
+
+static void edgePoints(const GeomEdgePtr& theEdge, std::list<GeomPointPtr>& thePoints)
+{
+ GeomAPI_Curve aCurve(theEdge);
+ static const int aNbSegments = 10;
+ double aStart = aCurve.startParam();
+ double aEnd = aCurve.endParam();
+ for (int i = 0; i <= aNbSegments; ++i)
+ thePoints.push_back(aCurve.getPoint(aStart * (1.0 - (double)i / aNbSegments) +
+ aEnd * (double)i / aNbSegments ));
+ if (theEdge->orientation() == GeomAPI_Shape::REVERSED)
+ thePoints.reverse();
+}
+
+bool isReverseClosedCurve(const GeomEdgePtr& theEdge1,
+ const GeomEdgePtr& theEdge2)
+{
+ std::list<GeomPointPtr> anEdge1Points, anEdge2Points;
+ edgePoints(theEdge1, anEdge1Points);
+ edgePoints(theEdge2, anEdge2Points);
+
+ double d1 = 0.0;
+ double d2 = 0.0;
+ std::list<GeomPointPtr>::const_iterator anIt1 = anEdge1Points.begin();
+ std::list<GeomPointPtr>::const_iterator anIt2 = anEdge2Points.begin();
+ std::list<GeomPointPtr>::const_reverse_iterator anIt2Rev = anEdge2Points.rbegin();
+ for (; anIt1 != anEdge1Points.end(); ++anIt1, ++anIt2, ++anIt2Rev) {
+ d1 += (*anIt1)->distance(*anIt2);
+ d2 += (*anIt1)->distance(*anIt2Rev);
+ }
+ return d2 < d1;
+}
+
+bool isReverseOpenedCurve(const GeomEdgePtr& theEdge1,
+ const GeomEdgePtr& theEdge2,
+ const double theTolerance)
+{
+ std::pair<GeomPointPtr, GeomPointPtr> anEdge1Points = edgeBoundaries(theEdge1);
+ std::pair<GeomPointPtr, GeomPointPtr> anEdge2Points = edgeBoundaries(theEdge2);
+ double d1 = anEdge1Points.first->distance(anEdge2Points.first)
+ + anEdge1Points.second->distance(anEdge2Points.second);
+ double d2 = anEdge1Points.first->distance(anEdge2Points.second)
+ + anEdge1Points.second->distance(anEdge2Points.first);
+ if (fabs(d1 - d2) < theTolerance) {
+ // undefined case => check distance to start point only
+ d1 = anEdge1Points.first->distance(anEdge2Points.first);
+ d2 = anEdge1Points.first->distance(anEdge2Points.second);
+ }
+ return d2 < d1;
+}
+
+void shiftStartPoint(GeomWirePtr& theWire, const GeomEdgePtr& theRefEdge, const double theTolerance)
+{
+ if (!theWire->isClosed()) {
+ GeomVertexPtr aV1, aV2;
+ GeomAlgoAPI_ShapeTools::findBounds(theWire, aV1, aV2);
+ if (aV1->point()->distance(aV2->point()) > theTolerance)
+ return;
+ }
+
+ // find closest vertex on the wire to the start point on the edge
+ GeomPointPtr aFirstRefPnt = theRefEdge->firstPoint();
+ ListOfShape aBegin, aEnd;
+ double aMinDist = 1.e100;
+ for (GeomAPI_WireExplorer anExp(theWire); anExp.more(); anExp.next()) {
+ double aDist = anExp.currentVertex()->point()->distance(aFirstRefPnt);
+ if (aDist < aMinDist) {
+ aMinDist = aDist;
+ aEnd.insert(aEnd.end(), aBegin.begin(), aBegin.end());
+ aBegin.clear();
+ }
+ aBegin.push_back(anExp.current());
+ }
+ aBegin.insert(aBegin.end(), aEnd.begin(), aEnd.end());
+
+ GeomShapePtr aShape = GeomAlgoAPI_WireBuilder::wire(aBegin);
+ theWire.reset(new GeomAPI_Wire(aShape));
+}