+}
+
+//==================================================================================================
+static TopoDS_Wire fixParametricGaps(const TopoDS_Wire& theWire)
+{
+ TopoDS_Wire aFixedWire;
+ Handle(Geom_Curve) aPrevCurve;
+ double aPrevLastParam = 0.0;
+
+ BRep_Builder aBuilder;
+ aBuilder.MakeWire(aFixedWire);
+
+ BRepTools_WireExplorer aWExp(theWire);
+ for (; aWExp.More(); aWExp.Next()) {
+ TopoDS_Edge anEdge = aWExp.Current();
+ double aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+ if (aCurve == aPrevCurve) {
+ // if parametric gap occurs, create new edge based on the copied curve
+ aCurve = Handle(Geom_Curve)::DownCast(aCurve->Copy());
+ TopoDS_Vertex aV1, aV2;
+ TopExp::Vertices(anEdge, aV1, aV2);
+ anEdge = TopoDS::Edge(anEdge.EmptyCopied());
+ aBuilder.UpdateEdge(anEdge, aCurve, BRep_Tool::Tolerance(anEdge));
+ aBuilder.Add(anEdge, aV1);
+ aBuilder.Add(anEdge, aV2);
+ }
+
+ aBuilder.Add(aFixedWire, anEdge);
+
+ aPrevCurve = aCurve;
+ aPrevLastParam = aLast;
+ }
+
+ return aFixedWire;
+}
+
+std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_ShapeTools::wireToEdge(
+ const std::shared_ptr<GeomAPI_Wire>& theWire)
+{
+ GeomEdgePtr anEdge;
+ if (theWire) {
+ TopoDS_Wire aWire = theWire->impl<TopoDS_Wire>();
+ // Workaround: when concatenate a wire consisting of two edges based on the same B-spline curve
+ // (non-periodic, but having equal start and end points), first of which is placed at the end
+ // on the curve and second is placed at the start, this workaround copies second curve to avoid
+ // treating these edges as a single curve by setting trim parameters.
+ aWire = fixParametricGaps(aWire);
+ TopoDS_Edge aNewEdge = BRepAlgo::ConcatenateWireC0(aWire);
+ anEdge = GeomEdgePtr(new GeomAPI_Edge);
+ anEdge->setImpl(new TopoDS_Edge(aNewEdge));
+ }
+ return anEdge;
+}
+
+ListOfShape GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(const GeomShapePtr& theShape)
+{
+ ListOfShape aSubShapes;
+
+ if (!theShape->isCompound() && !theShape->isCompSolid() &&
+ !theShape->isShell() && !theShape->isWire()) {
+ return aSubShapes;
+ }
+
+ for (GeomAPI_ShapeIterator anIt(theShape); anIt.more(); anIt.next()) {
+ GeomShapePtr aSubShape = anIt.current();
+ if (aSubShape->isVertex() || aSubShape->isEdge() ||
+ aSubShape->isFace() || aSubShape->isSolid()) {
+ aSubShapes.push_back(aSubShape);
+ } else {
+ aSubShapes.splice(aSubShapes.end(), getLowLevelSubShapes(aSubShape));
+ }
+ }
+
+ return aSubShapes;