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 <Precision.hxx>
16 #include <TopExp_Explorer.hxx>
18 #include <TopoDS_Edge.hxx>
19 #include <TopTools_ListIteratorOfListOfShape.hxx>
25 static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape)
27 static const double aTol = Precision::PConfusion();
29 TopExp_Explorer anExp(theShape, TopAbs_VERTEX);
30 TopoDS_Vertex aStart = TopoDS::Vertex(anExp.Current());
31 gp_Pnt aStartPnt(BRep_Tool::Pnt(aStart));
32 TopoDS_Vertex aCurrent;
35 for (anExp.Next(); anExp.More(); anExp.Next()) {
36 aCurrent = TopoDS::Vertex(anExp.Current());
37 aCurrentPnt = BRep_Tool::Pnt(aCurrent);
38 if ((aCurrentPnt.X() > aStartPnt.X() + aTol) ||
39 (aCurrentPnt.X() > aStartPnt.X() - aTol && aCurrentPnt.Y() > aStartPnt.Y() + aTol) ||
40 (aCurrentPnt.X() > aStartPnt.X() - aTol && aCurrentPnt.Y() > aStartPnt.Y() - aTol &&
41 aCurrentPnt.Z() > aStartPnt.Z() + aTol)) {
43 aStartPnt = aCurrentPnt;
49 void GeomAlgoAPI_SketchBuilder::createFaces(
50 const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
51 const std::shared_ptr<GeomAPI_Dir>& theDirX,
52 const std::shared_ptr<GeomAPI_Dir>& theNorm,
53 const std::list<std::shared_ptr<GeomAPI_Shape> >& theFeatures,
54 std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
56 if (theFeatures.empty())
59 BRep_Builder aBuilder;
60 // Planar face, where the sketch was built
61 Handle(Geom_Surface) aPlane(new Geom_Plane(theOrigin->impl<gp_Pnt>(), theNorm->impl<gp_Dir>()));
63 aBuilder.MakeFace(aPlnFace, aPlane, Precision::Confusion());
65 // Use General Fuse algorithm to prepare all subfaces, bounded by given list of edges
67 aBB.AddArgument(aPlnFace);
69 BOPCol_ListOfShape anEdges;
70 BOPCol_ListIteratorOfListOfShape aShapeIt;
71 std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theFeatures.begin();
72 for (; aFeatIt != theFeatures.end(); aFeatIt++) {
73 std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
74 const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
75 if (anEdge.ShapeType() == TopAbs_EDGE)
76 aBB.AddArgument(anEdge);
79 if (aBB.ErrorStatus())
83 const TopTools_ListOfShape& anAreas = aBB.Modified(aPlnFace);
84 TopTools_ListIteratorOfListOfShape anIt(anAreas);
85 for (; anIt.More(); anIt.Next()) {
86 TopoDS_Face aFace = TopoDS::Face(anIt.Value());
87 // avoid infinite faces
88 BRepTopAdaptor_FClass2d aFClass(aFace, Precision::Confusion());
89 if (aFClass.PerformInfinitePoint() == TopAbs_IN)
94 aBuilder.MakeFace(aNewFace, aPlane, Precision::Confusion());
97 TopExp_Explorer aWireExp(aFace, TopAbs_WIRE);
98 for (; aWireExp.More(); aWireExp.Next()) {
99 TopoDS_Wire aWire = TopoDS::Wire(aWireExp.Current());
101 // to make faces equal on different platforms, we will find
102 // a vertex with greater coordinates and start wire from it
103 TopoDS_Vertex aStartVertex = findStartVertex(aWire);
105 TopoDS_Wire aNewWire;
106 aBuilder.MakeWire(aNewWire);
107 std::list<TopoDS_Edge> aSkippedEdges;
108 bool aStartFound = false;
110 // remove internal edges from faces and make wire start from found vertex
111 TopExp_Explorer anExp(aWire, TopAbs_EDGE);
112 for (; anExp.More(); anExp.Next()) {
113 if (anExp.Current().Orientation() == TopAbs_INTERNAL)
116 const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
117 TopoDS_Vertex aV1, aV2;
118 TopExp::Vertices(anEdge, aV1, aV2, Standard_True);
119 if (aV1.IsSame(aStartVertex) == Standard_True)
122 aSkippedEdges.push_back(anEdge);
125 aBuilder.Add(aNewWire, anExp.Current());
127 // add skipped edges to the end of wire
128 std::list<TopoDS_Edge>::const_iterator aSkIt = aSkippedEdges.begin();
129 for (; aSkIt != aSkippedEdges.end(); ++aSkIt)
130 aBuilder.Add(aNewWire, *aSkIt);
132 // check the wire is empty
133 anExp.Init(aNewWire, TopAbs_EDGE);
135 aBuilder.Add(aNewFace, aNewWire);
140 std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
141 aResFace->setImpl(new TopoDS_Face(aFace));
142 theResultFaces.push_back(aResFace);
146 void GeomAlgoAPI_SketchBuilder::createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
147 const std::shared_ptr<GeomAPI_Dir>& theDirX,
148 const std::shared_ptr<GeomAPI_Dir>& theNorm,
149 const std::shared_ptr<GeomAPI_Shape>& theWire,
150 std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
152 std::shared_ptr<GeomAPI_PlanarEdges> aWire =
153 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theWire);
155 // Filter wires, return only faces.
156 createFaces(theOrigin, theDirX, theNorm, aWire->getEdges(), theResultFaces);
157 } else { // it may be only one circle
158 std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(theWire);
160 std::list<std::shared_ptr<GeomAPI_Shape> > aList;
161 aList.push_back(anEdge);
162 createFaces(theOrigin, theDirX, theNorm, aList, theResultFaces);