1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: GeomAlgoAPI_SketchBuilder.cpp
4 // Created: 02 Jun 2014
5 // Author: Artem ZHIDKOV
7 #include <GeomAlgoAPI_SketchBuilder.h>
8 #include <GeomAPI_PlanarEdges.h>
10 #include <BOPAlgo_Builder.hxx>
11 #include <BRep_Builder.hxx>
12 #include <BRepTopAdaptor_FClass2d.hxx>
13 #include <Geom_Plane.hxx>
14 #include <Geom_TrimmedCurve.hxx>
15 #include <Precision.hxx>
17 #include <TopExp_Explorer.hxx>
19 #include <TopoDS_Edge.hxx>
20 #include <TopTools_ListIteratorOfListOfShape.hxx>
26 static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape)
28 static const double aTol = Precision::PConfusion();
30 TopExp_Explorer anExp(theShape, TopAbs_VERTEX);
31 TopoDS_Vertex aStart = TopoDS::Vertex(anExp.Current());
32 gp_Pnt aStartPnt(BRep_Tool::Pnt(aStart));
33 TopoDS_Vertex aCurrent;
36 for (anExp.Next(); anExp.More(); anExp.Next()) {
37 aCurrent = TopoDS::Vertex(anExp.Current());
38 aCurrentPnt = BRep_Tool::Pnt(aCurrent);
39 if ((aCurrentPnt.X() > aStartPnt.X() + aTol) ||
40 (aCurrentPnt.X() > aStartPnt.X() - aTol && aCurrentPnt.Y() > aStartPnt.Y() + aTol) ||
41 (aCurrentPnt.X() > aStartPnt.X() - aTol && aCurrentPnt.Y() > aStartPnt.Y() - aTol &&
42 aCurrentPnt.Z() > aStartPnt.Z() + aTol)) {
44 aStartPnt = aCurrentPnt;
50 static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape,
51 const std::list<std::shared_ptr<GeomAPI_Shape> >& theInitialShapes)
53 // Try to find edge lying on the one of original edges.
54 // First found edge will be taken as a start edge for the result wire
55 std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theInitialShapes.begin();
56 for (; aFeatIt != theInitialShapes.end(); aFeatIt++) {
57 std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
58 const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
59 if (anEdge.ShapeType() != TopAbs_EDGE)
63 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
64 if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
65 aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
67 TopExp_Explorer anExp(theShape, TopAbs_EDGE);
68 for (; anExp.More(); anExp.Next()) {
69 const TopoDS_Edge& aShapeEdge = TopoDS::Edge(anExp.Current());
71 Handle(Geom_Curve) aShapeCurve = BRep_Tool::Curve(aShapeEdge, aF, aL);
72 if (aShapeCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
73 aShapeCurve = Handle(Geom_TrimmedCurve)::DownCast(aShapeCurve)->BasisCurve();
75 if (aCurve != aShapeCurve)
78 // the edge is found, search vertex
79 TopoDS_Vertex aV1, aV2;
80 TopExp::Vertices(aShapeEdge, aV1, aV2);
81 return fabs(aF - aFirst) <= fabs(aL - aFirst) ? aV1 : aV2;
85 // start vertex is not found, use algorithm to search vertex with the greatest coordinates
86 return findStartVertex(theShape);
89 void GeomAlgoAPI_SketchBuilder::createFaces(
90 const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
91 const std::shared_ptr<GeomAPI_Dir>& theDirX,
92 const std::shared_ptr<GeomAPI_Dir>& theNorm,
93 const std::list<std::shared_ptr<GeomAPI_Shape> >& theFeatures,
94 std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
96 if (theFeatures.empty())
99 BRep_Builder aBuilder;
100 // Planar face, where the sketch was built
101 Handle(Geom_Surface) aPlane(new Geom_Plane(theOrigin->impl<gp_Pnt>(), theNorm->impl<gp_Dir>()));
102 TopoDS_Face aPlnFace;
103 aBuilder.MakeFace(aPlnFace, aPlane, Precision::Confusion());
105 // Use General Fuse algorithm to prepare all subfaces, bounded by given list of edges
107 aBB.AddArgument(aPlnFace);
109 BOPCol_ListOfShape anEdges;
110 BOPCol_ListIteratorOfListOfShape aShapeIt;
111 std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theFeatures.begin();
112 for (; aFeatIt != theFeatures.end(); aFeatIt++) {
113 std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
114 const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
115 if (anEdge.ShapeType() == TopAbs_EDGE)
116 aBB.AddArgument(anEdge);
119 if (aBB.ErrorStatus())
123 const TopTools_ListOfShape& anAreas = aBB.Modified(aPlnFace);
124 TopTools_ListIteratorOfListOfShape anIt(anAreas);
125 for (; anIt.More(); anIt.Next()) {
126 TopoDS_Face aFace = TopoDS::Face(anIt.Value());
127 // avoid infinite faces
128 BRepTopAdaptor_FClass2d aFClass(aFace, Precision::Confusion());
129 if (aFClass.PerformInfinitePoint() == TopAbs_IN)
133 TopoDS_Face aNewFace;
134 aBuilder.MakeFace(aNewFace, aPlane, Precision::Confusion());
137 TopExp_Explorer aWireExp(aFace, TopAbs_WIRE);
138 for (; aWireExp.More(); aWireExp.Next()) {
139 TopoDS_Wire aWire = TopoDS::Wire(aWireExp.Current());
141 // to make faces equal on different platforms, we will find
142 // a vertex lying on an edge with the lowest index in the list of initial edges
143 TopoDS_Vertex aStartVertex = findStartVertex(aWire, theFeatures);
145 TopoDS_Wire aNewWire;
146 aBuilder.MakeWire(aNewWire);
147 std::list<TopoDS_Edge> aSkippedEdges;
148 bool aStartFound = false;
150 // remove internal edges from faces and make wire start from found vertex
151 TopExp_Explorer anExp(aWire, TopAbs_EDGE);
152 for (; anExp.More(); anExp.Next()) {
153 if (anExp.Current().Orientation() == TopAbs_INTERNAL)
156 const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
157 TopoDS_Vertex aV1, aV2;
158 TopExp::Vertices(anEdge, aV1, aV2, Standard_True);
159 if (aV1.IsSame(aStartVertex) == Standard_True)
162 aSkippedEdges.push_back(anEdge);
165 aBuilder.Add(aNewWire, anExp.Current());
167 // add skipped edges to the end of wire
168 std::list<TopoDS_Edge>::const_iterator aSkIt = aSkippedEdges.begin();
169 for (; aSkIt != aSkippedEdges.end(); ++aSkIt)
170 aBuilder.Add(aNewWire, *aSkIt);
172 // check the wire is empty
173 anExp.Init(aNewWire, TopAbs_EDGE);
175 aBuilder.Add(aNewFace, aNewWire);
180 std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
181 aResFace->setImpl(new TopoDS_Face(aFace));
182 theResultFaces.push_back(aResFace);
186 void GeomAlgoAPI_SketchBuilder::createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
187 const std::shared_ptr<GeomAPI_Dir>& theDirX,
188 const std::shared_ptr<GeomAPI_Dir>& theNorm,
189 const std::shared_ptr<GeomAPI_Shape>& theWire,
190 std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
192 std::shared_ptr<GeomAPI_PlanarEdges> aWire =
193 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theWire);
195 // Filter wires, return only faces.
196 createFaces(theOrigin, theDirX, theNorm, aWire->getEdges(), theResultFaces);
197 } else { // it may be only one circle
198 std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(theWire);
200 std::list<std::shared_ptr<GeomAPI_Shape> > aList;
201 aList.push_back(anEdge);
202 createFaces(theOrigin, theDirX, theNorm, aList, theResultFaces);