Salome HOME
Non planar faces 35156
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_NonPlanarFace.cpp
1 // Copyright (C) 2014-2023  CEA, EDF
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <GeomAlgoAPI_NonPlanarFace.h>
21
22 #include <BRep_Builder.hxx>
23 #include <BRep_Tool.hxx>
24 #include <BRepTools_WireExplorer.hxx>
25 #include <BRepBuilderAPI_Copy.hxx>
26 #include <BRepOffsetAPI_MakeFilling.hxx>
27 #include <BRepBuilderAPI_MakeFace.hxx>
28 #include <BOPTools_AlgoTools.hxx>
29
30 #include <GeomAPI_Shape.h>
31 #include <Geom_Surface.hxx>
32
33 #include <ShapeFix_Face.hxx>
34 #include <ShapeAnalysis_FreeBounds.hxx>
35 #include <ShapeFix_ShapeTolerance.hxx>
36 #include <TopTools_HSequenceOfShape.hxx>
37 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Wire.hxx>
40 #include <TopoDS_Face.hxx>
41 #include <TopExp_Explorer.hxx>
42 #include <TopoDS.hxx>
43
44 //==================================================================================================
45 GeomAlgoAPI_NonPlanarFace::GeomAlgoAPI_NonPlanarFace(
46     const ListOfShape& theEdges)
47 {
48     build(theEdges);
49 }
50
51 //==================================================================================================
52 void GeomAlgoAPI_NonPlanarFace::build
53     (const ListOfShape& theEdges)
54 {
55     myResultFaces.clear();
56     setDone(false);
57     if (theEdges.empty())
58     {
59         return;
60     }
61
62     //prepare edges
63     Handle(TopTools_HSequenceOfShape) aSeqEdgesIn = new TopTools_HSequenceOfShape;
64     TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
65     TopTools_MapOfShape aMapEdges;
66     for (auto anEdge: theEdges) 
67     {
68         const TopoDS_Edge& aTEdge = anEdge->impl<TopoDS_Edge>();
69         if (aMapEdges.Add(aTEdge))
70         {
71             BRepBuilderAPI_Copy aCopy(aTEdge, Standard_False, Standard_False);
72             const TopoDS_Shape& aCopyEdge = aCopy.Shape();
73             aSeqEdgesIn->Append(aCopyEdge);
74         }
75     }
76
77     // no edges
78     if (aSeqEdgesIn->IsEmpty()) 
79     {
80         return;
81     }
82
83     // Connect edges to wires of maximum length
84     Handle(TopTools_HSequenceOfShape) aSeqWiresOut;
85     ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdgesIn, Precision::Confusion(), Standard_False, aSeqWiresOut);
86
87     // prepare compound result
88     BRep_Builder aBuilder;
89     TopoDS_Compound aResult;
90     aBuilder.MakeCompound(aResult);
91
92     // try to construct face for each non-planar wire
93     for(int ind = 1; ind <= aSeqWiresOut->Length(); ind++)
94     {
95         if(!aSeqWiresOut->Value(ind).Closed())
96         {
97             continue;
98         }
99         TopoDS_Wire aWire = TopoDS::Wire(aSeqWiresOut->Value(ind));
100
101         // try to construct filling surface
102         BRepOffsetAPI_MakeFilling aMF;
103         BRepTools_WireExplorer aWExp(aWire);
104         for (; aWExp.More(); aWExp.Next()) 
105         {
106             aMF.Add(TopoDS::Edge(aWExp.Current()), GeomAbs_C0);
107         }
108         aMF.Build();
109         if (!aMF.IsDone()) 
110         {
111             return;
112         }
113         // Result of filling
114         TopoDS_Shape aFillRes = aMF.Shape();
115         Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aFillRes));
116         BRepBuilderAPI_MakeFace aMakeFace(aGS, aWire);
117         if (aMakeFace.IsDone()) 
118         {
119             TopoDS_Face aNewFace = aMakeFace.Face();
120             Handle(ShapeFix_Face) aFix = new ShapeFix_Face(aNewFace);
121             aFix->Perform();
122             aFix->FixOrientation();
123             aNewFace = aFix->Face();
124
125             //check and fix pcurves, if necessary
126             TopExp_Explorer aExpE;
127             Standard_Real aT, aTolE, aDMax;
128             ShapeFix_ShapeTolerance sat;
129             aExpE.Init(aNewFace, TopAbs_EDGE);
130             for (; aExpE.More(); aExpE.Next())
131             {
132                 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
133                 if (!BOPTools_AlgoTools::ComputeTolerance(aNewFace, aE, aDMax, aT)) continue;
134                 aTolE = BRep_Tool::Tolerance(aE);
135                 if (aDMax < aTolE) continue;
136
137                 sat.LimitTolerance(aE, aDMax);
138             }
139
140             // store face
141             aBuilder.Add(aResult, aNewFace);
142             std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
143             aResFace->setImpl(new TopoDS_Face(aNewFace));
144             myResultFaces.push_back(aResFace);
145         }
146     }
147     
148     // update results
149     GeomShapePtr aResShape(new GeomAPI_Shape);
150     aResShape->setImpl(new TopoDS_Shape(aResult));
151     setShape(aResShape);
152     setDone(true);
153 }