1 // Copyright (C) 2014-2019 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "GeomAlgoAPI_WireBuilder.h"
22 #include <GeomAPI_Edge.h>
23 #include <GeomAPI_Pnt.h>
24 #include <GeomAPI_Vertex.h>
25 #include <GeomAPI_ShapeExplorer.h>
27 #include <BRep_Builder.hxx>
28 #include <BRep_Tool.hxx>
29 #include <BRepBuilderAPI_MakeWire.hxx>
30 #include <BRepTools_ReShape.hxx>
31 #include <Geom_Curve.hxx>
33 #include <TopoDS_Wire.hxx>
35 #include <TopExp_Explorer.hxx>
37 static GeomShapePtr fromTopoDS(const TopoDS_Shape& theShape)
39 GeomShapePtr aResultShape(new GeomAPI_Shape());
40 aResultShape->setImpl(new TopoDS_Shape(theShape));
44 GeomAlgoAPI_WireBuilder::GeomAlgoAPI_WireBuilder(const ListOfShape& theShapes,
45 const bool theForceOpenWire)
47 TopTools_ListOfShape aListOfEdges;
49 ListOfShape::const_iterator anIt = theShapes.cbegin();
50 for (; anIt != theShapes.cend(); ++anIt) {
51 const TopoDS_Shape& aShape = (*anIt)->impl<TopoDS_Shape>();
52 switch (aShape.ShapeType()) {
54 aListOfEdges.Append(aShape);
58 for (TopExp_Explorer anExp(aShape, TopAbs_EDGE); anExp.More(); anExp.Next()) {
59 aListOfEdges.Append(anExp.Current());
68 bool isSplitWire = false;
70 if (theForceOpenWire && aListOfEdges.Size() > 1) {
71 // find a vertex to split the wire
73 TopExp::Vertices(TopoDS::Edge(aListOfEdges.First()), V1[0], V1[1]);
75 TopExp::Vertices(TopoDS::Edge(aListOfEdges.Last()), V2[0], V2[1]);
76 gp_Pnt P1[2] = { BRep_Tool::Pnt(V1[0]), BRep_Tool::Pnt(V1[1]) };
77 gp_Pnt P2[2] = { BRep_Tool::Pnt(V2[0]), BRep_Tool::Pnt(V2[1]) };
78 double Tol1[2] = { BRep_Tool::Tolerance(V1[0]), BRep_Tool::Tolerance(V1[1]) };
79 double Tol2[2] = { BRep_Tool::Tolerance(V2[0]), BRep_Tool::Tolerance(V2[1]) };
80 for (int i = 0; i < 2 && !isSplitWire; ++i)
81 for (int j = 0; j < 2 && !isSplitWire; ++j)
82 if (P1[i].Distance(P2[j]) < Max(Tol1[i], Tol2[j])) {
88 BRepBuilderAPI_MakeWire* aWireBuilder = new BRepBuilderAPI_MakeWire;
89 aWireBuilder->Add(aListOfEdges);
90 if (aWireBuilder->Error() == BRepBuilderAPI_WireDone) {
91 setImpl(aWireBuilder);
92 setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
94 // split the result wire
95 TopoDS_Wire aWire = aWireBuilder->Wire();
96 if (isSplitWire && BRep_Tool::IsClosed(aWire)) {
98 BRep_Builder aBuilder;
99 aBuilder.MakeWire(aNewWire);
100 for (TopExp_Explorer anExp(aWire, TopAbs_EDGE); anExp.More(); anExp.Next()) {
101 TopoDS_Edge aNewCurrent = TopoDS::Edge(anExp.Current());
103 bool isToReshape = false;
104 BRepTools_ReShape aReshape;
105 TopoDS_Vertex aVF, aVL;
106 TopExp::Vertices(aNewCurrent, aVF, aVL);
107 gp_Pnt aPF = BRep_Tool::Pnt(aVF);
108 double aTolF = BRep_Tool::Tolerance(aVF);
109 gp_Pnt aPL = BRep_Tool::Pnt(aVL);
110 double aTolL = BRep_Tool::Tolerance(aVL);
111 if (aSplitPoint.SquareDistance(aPF) < aTolF * aTolF) {
112 aReshape.Replace(aVF, aReshape.CopyVertex(aVF));
115 else if (aSplitPoint.SquareDistance(aPL) < aTolL * aTolL) {
116 aReshape.Replace(aVL, aReshape.CopyVertex(aVL));
120 aNewCurrent = TopoDS::Edge(aReshape.Apply(aNewCurrent));
121 isSplitWire = false; // no need to continue splitting
124 aBuilder.Add(aNewWire, aNewCurrent);
129 // store generated/modified shapes
130 for (TopTools_ListOfShape::Iterator aBaseIt(aListOfEdges); aBaseIt.More(); aBaseIt.Next()) {
131 TopoDS_Edge aBaseCurrent = TopoDS::Edge(aBaseIt.Value());
132 Standard_Real aFirst, aLast;
133 Handle(Geom_Curve) aBaseCurve = BRep_Tool::Curve(aBaseCurrent, aFirst, aLast);
135 for (TopExp_Explorer anExp(aWire, TopAbs_EDGE); anExp.More(); anExp.Next()) {
136 TopoDS_Edge aNewCurrent = TopoDS::Edge(anExp.Current());
137 Handle(Geom_Curve) aNewCurve = BRep_Tool::Curve(aNewCurrent, aFirst, aLast);
138 if (aBaseCurve == aNewCurve) {
139 GeomShapePtr aBaseShape = fromTopoDS(aBaseCurrent);
140 GeomShapePtr aNewShape = fromTopoDS(aNewCurrent);
141 addGenerated(aBaseShape, aNewShape);
142 addModified(aBaseShape, aNewShape);
147 setShape(fromTopoDS(aWire));
152 //=================================================================================================
153 GeomShapePtr GeomAlgoAPI_WireBuilder::wire(const ListOfShape& theShapes)
155 return GeomAlgoAPI_WireBuilder(theShapes).shape();
158 //=================================================================================================
159 bool GeomAlgoAPI_WireBuilder::isSelfIntersected(const GeomShapePtr& theWire)
164 GeomAPI_ShapeExplorer anExp(theWire, GeomAPI_Shape::EDGE);
165 for (; anExp.more(); anExp.next()) {
166 GeomShapePtr anEdge = anExp.current();
167 anEdges.push_back(anEdge);
170 // Check intersections between edges pair-wise
171 int aNbEdges = (int)anEdges.size();
172 std::list<GeomShapePtr>::const_iterator anEdgesIt = anEdges.begin();
173 for (int i = 0; anEdgesIt != anEdges.end(); ++anEdgesIt, i++) {
174 GeomEdgePtr anEdge1(new GeomAPI_Edge(*anEdgesIt));
176 std::list<GeomShapePtr>::const_iterator anOtherEdgesIt = std::next(anEdgesIt);
177 for (int j = i + 1; anOtherEdgesIt != anEdges.end(); ++anOtherEdgesIt, j++) {
178 GeomEdgePtr anEdge2(new GeomAPI_Edge(*anOtherEdgesIt));
179 GeomShapePtr anInter = anEdge1->intersect(anEdge2);
180 if (!anInter.get()) {
186 if (anInter->isVertex()) {
187 GeomVertexPtr aVertex(new GeomAPI_Vertex(anInter));
188 GeomPointPtr aPnt = aVertex->point();
190 GeomPointPtr aFirstPnt1 = anEdge1->orientation() == GeomAPI_Shape::FORWARD ?
191 anEdge1->firstPoint() : anEdge1->lastPoint();
192 GeomPointPtr aLastPnt1 = anEdge1->orientation() == GeomAPI_Shape::FORWARD ?
193 anEdge1->lastPoint() : anEdge1->firstPoint();
194 GeomPointPtr aFirstPnt2 = anEdge2->orientation() == GeomAPI_Shape::FORWARD ?
195 anEdge2->firstPoint() : anEdge2->lastPoint();
196 GeomPointPtr aLastPnt2 = anEdge2->orientation() == GeomAPI_Shape::FORWARD ?
197 anEdge2->lastPoint() : anEdge2->firstPoint();
199 GeomPointPtr aCommonEndPnt;
200 if (aFirstPnt1->isEqual(aLastPnt2)) {
201 aCommonEndPnt = aFirstPnt1;
202 } else if(aLastPnt1->isEqual(aFirstPnt2)) {
203 aCommonEndPnt = aLastPnt1;
206 isOk = aCommonEndPnt && aPnt->isEqual(aCommonEndPnt);