+ if (theOriginalShape.ShapeType() != TopAbs_WIRE)
+ Standard_TypeMismatch::Raise("Not a wire is given");
+
+ // Tolerances
+ Standard_Real AngTol = Precision::Angular();
+ Standard_Real LinTol = Precision::Confusion();
+ Standard_Real tol;
+ for (TopExp_Explorer ExV (theOriginalShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
+ TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
+ tol = BRep_Tool::Tolerance(Vertex);
+ if (tol > LinTol)
+ LinTol = tol;
+ }
+
+ // 1. Make a copy to prevent the original shape changes.
+ TopoDS_Shape aWire;
+ TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
+ TNaming_CopyShape::CopyTool(theOriginalShape, aMapTShapes, aWire);
+ TopoDS_Wire theWire = TopoDS::Wire(aWire);
+
+ // 2. Sub-shapes of the wire
+ TopTools_MapOfShape aMapToRemove;
+
+ TopTools_IndexedMapOfShape anOldIndices;
+ TopExp::MapShapes(theOriginalShape, anOldIndices);
+
+ TopTools_IndexedMapOfShape aNewIndices;
+ TopExp::MapShapes(theWire, aNewIndices);
+
+ // 3. Collect vertices of the wire, same or equal to the given vertices
+ bool removeAll = false;
+ if (aVerts.IsNull() || aVerts->Length() < 1)
+ removeAll = true;
+
+ if (!removeAll) {
+ for ( int ind = 1; ind <= aVerts->Length(); ind++) {
+ Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aVerts->Value(ind));
+ TopoDS_Shape aShape_i = aRefShape->GetValue();
+ if (aShape_i.IsNull())
+ Standard_NullObject::Raise("Null vertex given");
+ if (aShape_i.ShapeType() != TopAbs_VERTEX)
+ Standard_TypeMismatch::Raise("Shape to suppress is not a vertex");
+
+ // find vertices shared with the initial wire
+ if (anOldIndices.Contains(aShape_i)) {
+ aMapToRemove.Add(aNewIndices.FindKey(anOldIndices.FindIndex(aShape_i)));
+ } else {
+ // try to find by coords in the new wire
+ TopoDS_Vertex aVert = TopoDS::Vertex(aShape_i);
+ gp_Pnt aP = BRep_Tool::Pnt(aVert);
+
+ bool isFound = false;
+ TopTools_MapOfShape mapShape;
+ TopExp_Explorer exp (theWire, TopAbs_VERTEX);
+ for (; exp.More() && !isFound; exp.Next()) {
+ if (mapShape.Add(exp.Current())) {
+ TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
+ gp_Pnt aPi = BRep_Tool::Pnt(aVi);
+ if (aPi.Distance(aP) < LinTol) {
+ aMapToRemove.Add(aVi);
+ isFound = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ BRepLib::BuildCurves3d(theWire);
+ Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(theWire);
+ Fixer->SetPrecision(LinTol);
+ Fixer->SetMaxTolerance(LinTol);
+ Fixer->Perform();
+ theWire = TopoDS::Wire(Fixer->Shape());
+ */
+
+ // Get the ordered list of edges.
+ TopTools_ListOfShape anEdges;
+ TopTools_ListOfShape aCurVertices;
+ BRepTools_WireExplorer aWExp (theWire);
+
+ for (; aWExp.More(); aWExp.Next()) {
+ anEdges.Append(aWExp.Current());
+ aCurVertices.Append(aWExp.CurrentVertex());
+ }
+
+ if (anEdges.IsEmpty()) {
+ Standard_NullObject::Raise("Empty wire given");
+ }
+
+ // Treat the case if the wire is closed and first and last edges are C1.
+ Standard_Boolean isShift = Standard_False;
+
+ if (BRep_Tool::IsClosed(theWire)) {
+ // Wire is closed. Check if there are more than 2 edges in the wire.
+ if (!anEdges.First().IsSame(anEdges.Last())) {
+ isShift = Standard_True;
+ }
+ }
+
+ if (isShift) {
+ // Put first edge to the end of the list while the chain break is reached.
+ TopoDS_Shape aFirstEdge = anEdges.First();
+
+ while (isShift) {
+ isShift = Standard_False;
+
+ // Check if the first vertex should be kept
+ if (aMapToRemove.Contains(aCurVertices.First()) || removeAll) {
+ // Check if first and last edges are C1.
+ TopoDS_Edge anEdge1 = TopoDS::Edge(anEdges.Last());
+ TopoDS_Edge anEdge2 = TopoDS::Edge(anEdges.First());
+
+ if (AreEdgesC1(anEdge1, anEdge2)) {
+ // Make the first edge last.
+ anEdges.Append(anEdge2);
+ anEdges.RemoveFirst();
+ aCurVertices.Append(aCurVertices.First());
+ aCurVertices.RemoveFirst();
+
+ // Check if we reached the first edge again.
+ // Break the loop in this case.
+ isShift = !aFirstEdge.IsSame(anEdges.First());
+ }
+ }
+ }
+ }
+
+ TopTools_ListOfShape finalList, currChain;
+ TopTools_ListIteratorOfListOfShape anEIter(anEdges);
+ TopTools_ListIteratorOfListOfShape aVIter(aCurVertices);
+ TopoDS_Edge prevEdge = TopoDS::Edge(anEIter.Value());
+
+ currChain.Append(prevEdge);
+ anEIter.Next();
+ aVIter.Next();
+
+ for (; anEIter.More(); anEIter.Next(), aVIter.Next()) {
+ TopoDS_Edge anEdge = TopoDS::Edge(anEIter.Value());
+ const TopoDS_Shape &aCurVertex = aVIter.Value();
+
+ bool continueChain = false;
+ if (aMapToRemove.Contains(aCurVertex) || removeAll) {
+ // if C1 -> continue chain
+ if (AreEdgesC1(prevEdge, anEdge)) {
+ continueChain = true;
+ }
+ }
+
+ if (!continueChain) {
+ if (currChain.Extent() == 1) {
+ // add one edge to the final list
+ finalList.Append(currChain.First());
+ }
+ else {
+ // make wire from the list of edges
+ BRep_Builder B;
+ TopoDS_Wire aCurrWire;
+ B.MakeWire(aCurrWire);
+ TopTools_ListIteratorOfListOfShape itEdges (currChain);
+ for (; itEdges.More(); itEdges.Next()) {
+ TopoDS_Shape aValue = itEdges.Value();
+ B.Add(aCurrWire, TopoDS::Edge(aValue));
+ }
+
+ // make edge from the wire
+ TopoDS_Edge anEdge = GEOMImpl_ShapeDriver::MakeEdgeFromWire(aCurrWire, LinTol, AngTol);
+
+ // add this new edge to the final list
+ finalList.Append(anEdge);
+ }
+ currChain.Clear();
+ }
+
+ // add one edge to the chain
+ currChain.Append(anEdge);
+ prevEdge = anEdge;
+ }