Salome HOME
Invalid shape after extrusion (issue #1203)
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_SketchBuilder.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        GeomAlgoAPI_SketchBuilder.cpp
4 // Created:     02 Jun 2014
5 // Author:      Artem ZHIDKOV
6
7 #include <GeomAlgoAPI_SketchBuilder.h>
8 #include <GeomAPI_PlanarEdges.h>
9
10 #include <BOPAlgo_Builder.hxx>
11 #include <BRep_Builder.hxx>
12 #include <BRepTopAdaptor_FClass2d.hxx>
13 #include <Geom_Plane.hxx>
14 #include <Precision.hxx>
15 #include <TopExp_Explorer.hxx>
16 #include <TopoDS.hxx>
17 #include <TopoDS_Edge.hxx>
18 #include <TopTools_ListIteratorOfListOfShape.hxx>
19
20
21 void GeomAlgoAPI_SketchBuilder::createFaces(
22     const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
23     const std::shared_ptr<GeomAPI_Dir>& theDirX,
24     const std::shared_ptr<GeomAPI_Dir>& theNorm,
25     const std::list<std::shared_ptr<GeomAPI_Shape> >& theFeatures,
26     std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
27 {
28   if (theFeatures.empty())
29     return;
30
31   BRep_Builder aBuilder;
32   // Planar face, where the sketch was built
33   Handle(Geom_Surface) aPlane(new Geom_Plane(theOrigin->impl<gp_Pnt>(), theNorm->impl<gp_Dir>()));
34   TopoDS_Face aPlnFace;
35   aBuilder.MakeFace(aPlnFace, aPlane, Precision::Confusion());
36
37   // Use General Fuse algorithm to prepare all subfaces, bounded by given list of edges
38   BOPAlgo_Builder aBB;
39   aBB.AddArgument(aPlnFace);
40
41   BOPCol_ListOfShape anEdges;
42   BOPCol_ListIteratorOfListOfShape aShapeIt;
43   std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theFeatures.begin();
44   for (; aFeatIt != theFeatures.end(); aFeatIt++) {
45     std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
46     const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
47     if (anEdge.ShapeType() == TopAbs_EDGE)
48       aBB.AddArgument(anEdge);
49   }
50   aBB.Perform();
51   if (aBB.ErrorStatus())
52     return;
53
54   // Collect faces
55   const TopTools_ListOfShape& anAreas = aBB.Modified(aPlnFace);
56   TopTools_ListIteratorOfListOfShape anIt(anAreas);
57   for (; anIt.More(); anIt.Next()) {
58     TopoDS_Face aFace = TopoDS::Face(anIt.Value());
59     // avoid infinite faces
60     BRepTopAdaptor_FClass2d aFClass(aFace, Precision::Confusion());
61     if (aFClass.PerformInfinitePoint() == TopAbs_IN)
62       continue;
63
64     // remove internal edges from faces
65     TopExp_Explorer anExp(aFace, TopAbs_EDGE);
66     for (; anExp.More(); anExp.Next())
67       if (anExp.Current().Orientation() == TopAbs_INTERNAL)
68         break;
69     if (anExp.More()) {
70       TopoDS_Face aNewFace;
71       aBuilder.MakeFace(aNewFace, aPlane, Precision::Confusion());
72       TopoDS_Wire aWire;
73       aBuilder.MakeWire(aWire);
74       for (anExp.ReInit(); anExp.More(); anExp.Next())
75         if (anExp.Current().Orientation() != TopAbs_INTERNAL)
76           aBuilder.Add(aWire, anExp.Current());
77       aBuilder.Add(aNewFace, aWire);
78       aFace = aNewFace;
79     }
80
81     // Store face
82     std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
83     aResFace->setImpl(new TopoDS_Face(aFace));
84     theResultFaces.push_back(aResFace);
85   }
86 }
87
88 void GeomAlgoAPI_SketchBuilder::createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
89                                             const std::shared_ptr<GeomAPI_Dir>& theDirX,
90                                             const std::shared_ptr<GeomAPI_Dir>& theNorm,
91                                             const std::shared_ptr<GeomAPI_Shape>& theWire,
92                                             std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
93 {
94   std::shared_ptr<GeomAPI_PlanarEdges> aWire = 
95     std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theWire);
96   if(aWire) {
97     // Filter wires, return only faces.
98     createFaces(theOrigin, theDirX, theNorm, aWire->getEdges(), theResultFaces);
99   } else { // it may be only one circle
100     std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(theWire);
101     if (anEdge) {
102       std::list<std::shared_ptr<GeomAPI_Shape> > aList;
103       aList.push_back(anEdge);
104       createFaces(theOrigin, theDirX, theNorm, aList, theResultFaces);
105     }
106   }
107 }