1 // Copyright (C) 2014-2017 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<mailto:webmaster.salome@opencascade.com>
20 #include <GeomAlgoAPI_SketchBuilder.h>
21 #include <GeomAPI_PlanarEdges.h>
23 #include <BOPAlgo_Builder.hxx>
24 #include <BRep_Builder.hxx>
25 #include <BRepTopAdaptor_FClass2d.hxx>
26 #include <Geom_Plane.hxx>
27 #include <Geom_TrimmedCurve.hxx>
28 #include <Precision.hxx>
30 #include <TopExp_Explorer.hxx>
32 #include <TopoDS_Edge.hxx>
33 #include <TopTools_ListIteratorOfListOfShape.hxx>
39 static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape)
41 static const double aTol = Precision::PConfusion();
43 TopExp_Explorer anExp(theShape, TopAbs_VERTEX);
44 TopoDS_Vertex aStart = TopoDS::Vertex(anExp.Current());
45 gp_Pnt aStartPnt(BRep_Tool::Pnt(aStart));
46 TopoDS_Vertex aCurrent;
49 for (anExp.Next(); anExp.More(); anExp.Next()) {
50 aCurrent = TopoDS::Vertex(anExp.Current());
51 aCurrentPnt = BRep_Tool::Pnt(aCurrent);
52 if ((aCurrentPnt.X() > aStartPnt.X() + aTol) ||
53 (aCurrentPnt.X() > aStartPnt.X() - aTol && aCurrentPnt.Y() > aStartPnt.Y() + aTol) ||
54 (aCurrentPnt.X() > aStartPnt.X() - aTol && aCurrentPnt.Y() > aStartPnt.Y() - aTol &&
55 aCurrentPnt.Z() > aStartPnt.Z() + aTol)) {
57 aStartPnt = aCurrentPnt;
63 static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape,
64 const std::list<std::shared_ptr<GeomAPI_Shape> >& theInitialShapes)
66 // Try to find edge lying on the one of original edges.
67 // First found edge will be taken as a start edge for the result wire
68 std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theInitialShapes.begin();
69 for (; aFeatIt != theInitialShapes.end(); aFeatIt++) {
70 std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
71 const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
72 if (anEdge.ShapeType() != TopAbs_EDGE)
76 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
77 if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
78 aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
80 TopExp_Explorer anExp(theShape, TopAbs_EDGE);
81 for (; anExp.More(); anExp.Next()) {
82 const TopoDS_Edge& aShapeEdge = TopoDS::Edge(anExp.Current());
84 Handle(Geom_Curve) aShapeCurve = BRep_Tool::Curve(aShapeEdge, aF, aL);
85 if (aShapeCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
86 aShapeCurve = Handle(Geom_TrimmedCurve)::DownCast(aShapeCurve)->BasisCurve();
88 if (aCurve != aShapeCurve)
91 // the edge is found, search vertex
92 TopoDS_Vertex aV1, aV2;
93 TopExp::Vertices(aShapeEdge, aV1, aV2);
94 return fabs(aF - aFirst) <= fabs(aL - aFirst) ? aV1 : aV2;
98 // start vertex is not found, use algorithm to search vertex with the greatest coordinates
99 return findStartVertex(theShape);
102 void GeomAlgoAPI_SketchBuilder::createFaces(
103 const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
104 const std::shared_ptr<GeomAPI_Dir>& theDirX,
105 const std::shared_ptr<GeomAPI_Dir>& theNorm,
106 const std::list<std::shared_ptr<GeomAPI_Shape> >& theFeatures,
107 std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
109 if (theFeatures.empty())
112 BRep_Builder aBuilder;
113 // Planar face, where the sketch was built
114 Handle(Geom_Surface) aPlane(new Geom_Plane(theOrigin->impl<gp_Pnt>(), theNorm->impl<gp_Dir>()));
115 TopoDS_Face aPlnFace;
116 aBuilder.MakeFace(aPlnFace, aPlane, Precision::Confusion());
118 // Use General Fuse algorithm to prepare all subfaces, bounded by given list of edges
120 aBB.AddArgument(aPlnFace);
122 BOPCol_ListOfShape anEdges;
123 BOPCol_ListIteratorOfListOfShape aShapeIt;
124 std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theFeatures.begin();
125 for (; aFeatIt != theFeatures.end(); aFeatIt++) {
126 std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
127 const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
128 if (anEdge.ShapeType() == TopAbs_EDGE)
129 aBB.AddArgument(anEdge);
132 if (aBB.ErrorStatus())
136 const TopTools_ListOfShape& anAreas = aBB.Modified(aPlnFace);
137 TopTools_ListIteratorOfListOfShape anIt(anAreas);
138 for (; anIt.More(); anIt.Next()) {
139 TopoDS_Face aFace = TopoDS::Face(anIt.Value());
140 // avoid infinite faces
141 BRepTopAdaptor_FClass2d aFClass(aFace, Precision::Confusion());
142 if (aFClass.PerformInfinitePoint() == TopAbs_IN)
146 TopoDS_Face aNewFace;
147 aBuilder.MakeFace(aNewFace, aPlane, Precision::Confusion());
150 TopExp_Explorer aWireExp(aFace, TopAbs_WIRE);
151 for (; aWireExp.More(); aWireExp.Next()) {
152 TopoDS_Wire aWire = TopoDS::Wire(aWireExp.Current());
154 // to make faces equal on different platforms, we will find
155 // a vertex lying on an edge with the lowest index in the list of initial edges
156 TopoDS_Vertex aStartVertex = findStartVertex(aWire, theFeatures);
158 TopoDS_Wire aNewWire;
159 aBuilder.MakeWire(aNewWire);
160 std::list<TopoDS_Edge> aSkippedEdges;
161 bool aStartFound = false;
163 // remove internal edges from faces and make wire start from found vertex
164 TopExp_Explorer anExp(aWire, TopAbs_EDGE);
165 for (; anExp.More(); anExp.Next()) {
166 if (anExp.Current().Orientation() == TopAbs_INTERNAL)
169 const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
170 TopoDS_Vertex aV1, aV2;
171 TopExp::Vertices(anEdge, aV1, aV2, Standard_True);
172 if (aV1.IsSame(aStartVertex) == Standard_True)
175 aSkippedEdges.push_back(anEdge);
178 aBuilder.Add(aNewWire, anExp.Current());
180 // add skipped edges to the end of wire
181 std::list<TopoDS_Edge>::const_iterator aSkIt = aSkippedEdges.begin();
182 for (; aSkIt != aSkippedEdges.end(); ++aSkIt)
183 aBuilder.Add(aNewWire, *aSkIt);
185 // check the wire is empty
186 anExp.Init(aNewWire, TopAbs_EDGE);
188 aBuilder.Add(aNewFace, aNewWire);
193 std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
194 aResFace->setImpl(new TopoDS_Face(aFace));
195 theResultFaces.push_back(aResFace);
199 void GeomAlgoAPI_SketchBuilder::createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
200 const std::shared_ptr<GeomAPI_Dir>& theDirX,
201 const std::shared_ptr<GeomAPI_Dir>& theNorm,
202 const std::shared_ptr<GeomAPI_Shape>& theWire,
203 std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
205 std::shared_ptr<GeomAPI_PlanarEdges> aWire =
206 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theWire);
208 // Filter wires, return only faces.
209 createFaces(theOrigin, theDirX, theNorm, aWire->getEdges(), theResultFaces);
210 } else { // it may be only one circle
211 std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(theWire);
213 std::list<std::shared_ptr<GeomAPI_Shape> > aList;
214 aList.push_back(anEdge);
215 createFaces(theOrigin, theDirX, theNorm, aList, theResultFaces);