Salome HOME
Merge branch 'BR_internationalization'
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_Pipe.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        GeomAlgoAPI_Pipe.cpp
4 // Created:     16 March 2016
5 // Author:      Dmitry Bobylev
6
7 #include "GeomAlgoAPI_Pipe.h"
8
9 #include "GeomAlgoAPI_DFLoader.h"
10
11 #include <GeomAPI_Dir.h>
12 #include <GeomAPI_Edge.h>
13 #include <GeomAPI_Lin.h>
14
15 #include <BRep_Tool.hxx>
16 #include <BRepOffsetAPI_MakePipe.hxx>
17 #include <BRepOffsetAPI_MakePipeShell.hxx>
18 #include <BRepBuilderAPI_MakeWire.hxx>
19 #include <Geom_Curve.hxx>
20 #include <Geom_Line.hxx>
21 #include <gp_Lin.hxx>
22 #include <NCollection_List.hxx>
23 #include <TopExp_Explorer.hxx>
24 #include <TopoDS.hxx>
25 #include <TopoDS_Shape.hxx>
26
27 static bool getBase(TopoDS_Shape& theBaseOut,
28                     TopAbs_ShapeEnum& theBaseTypeOut,
29                     const GeomShapePtr theBaseShape);
30 static bool getPath(TopoDS_Wire& thePathOut,
31                     const GeomShapePtr thePathShape);
32 static bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder);
33 static ListOfShape getListFromShape(const TopoDS_Shape& theShape);
34
35 //==================================================================================================
36 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
37                                    const GeomShapePtr thePathShape)
38 {
39   build(theBaseShape, thePathShape);
40 }
41
42 //==================================================================================================
43 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
44                                    const GeomShapePtr thePathShape,
45                                    const GeomShapePtr theBiNormal)
46 {
47   build(theBaseShape, thePathShape, theBiNormal);
48 }
49
50 //==================================================================================================
51 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const ListOfShape& theBaseShapes,
52                                    const ListOfShape& theLocations,
53                                    const GeomShapePtr thePathShape)
54 {
55   build(theBaseShapes, theLocations, thePathShape);
56 }
57
58 //==================================================================================================
59 void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
60                              const GeomShapePtr thePathShape)
61 {
62   // Getting base shape.
63   if(!theBaseShape.get()) {
64     return;
65   }
66   TopoDS_Shape aBaseShape = theBaseShape->impl<TopoDS_Shape>();
67   if(aBaseShape.IsNull()) {
68     return;
69   }
70   TopAbs_ShapeEnum aBaseShapeType = aBaseShape.ShapeType();
71   if(aBaseShapeType != TopAbs_VERTEX && aBaseShapeType != TopAbs_EDGE &&
72      aBaseShapeType != TopAbs_WIRE && aBaseShapeType != TopAbs_FACE &&
73      aBaseShapeType != TopAbs_SHELL && aBaseShapeType != TopAbs_COMPOUND) {
74     return;
75   }
76
77   // Getting path.
78   TopoDS_Wire aPathWire;
79   if(!getPath(aPathWire, thePathShape)) {
80     return;
81   }
82
83   // Making pipe.
84   BRepOffsetAPI_MakePipe* aPipeBuilder = new BRepOffsetAPI_MakePipe(aPathWire, aBaseShape);
85   if(!aPipeBuilder) {
86     return;
87   }
88   aPipeBuilder->Build();
89
90   // Checking result.
91   if(!aPipeBuilder->IsDone() || aPipeBuilder->Shape().IsNull()) {
92     delete aPipeBuilder;
93     return;
94   }
95   this->initialize(aPipeBuilder);
96
97   // Setting naming.
98   this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
99   this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
100
101   // Setting result.
102   TopoDS_Shape aResult = aPipeBuilder->Shape();
103   aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
104   GeomShapePtr aGeomSh(new GeomAPI_Shape());
105   aGeomSh->setImpl(new TopoDS_Shape(aResult));
106   this->setShape(aGeomSh);
107   this->setDone(true);
108 }
109
110 //==================================================================================================
111 void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
112                              const GeomShapePtr thePathShape,
113                              const GeomShapePtr theBiNormal)
114 {
115   // Getting base shape.
116   TopoDS_Shape aBaseShape;
117   TopAbs_ShapeEnum aBaseShapeType;
118   if(!getBase(aBaseShape, aBaseShapeType, theBaseShape)) {
119     return;
120   }
121
122   // Getting path.
123   TopoDS_Wire aPathWire;
124   if(!getPath(aPathWire, thePathShape)) {
125     return;
126   }
127
128   // Getting Bi-Normal.
129   if(!theBiNormal.get()) {
130     return;
131   }
132   TopoDS_Shape aBiNormalShape = theBiNormal->impl<TopoDS_Shape>();
133   if(aBiNormalShape.IsNull() || aBiNormalShape.ShapeType() != TopAbs_EDGE) {
134     return;
135   }
136   TopoDS_Edge aBiNormalEdge = TopoDS::Edge(aBiNormalShape);
137   Standard_Real aFirst, aLast;
138   Handle(Geom_Curve) aBiNormalCurve = BRep_Tool::Curve(aBiNormalEdge, aFirst, aLast);
139   Handle(Geom_Line) aBiNormalLine = Handle(Geom_Line)::DownCast(aBiNormalCurve);
140   if(aBiNormalLine.IsNull()) {
141     return;
142   }
143   gp_Dir aBiNormalDir = aBiNormalLine->Lin().Direction();
144
145   // Making pipe.
146   BRepOffsetAPI_MakePipeShell* aPipeBuilder = new BRepOffsetAPI_MakePipeShell(aPathWire);
147   if(!aPipeBuilder) {
148     return;
149   }
150   aPipeBuilder->Add(aBaseShape);
151   aPipeBuilder->SetMode(aBiNormalDir);
152   if(!buildPipe(aPipeBuilder)) {
153     delete aPipeBuilder;
154     return;
155   }
156   this->initialize(aPipeBuilder);
157
158   // Checking result.
159   if(aBaseShapeType == TopAbs_FACE) {
160     if(aPipeBuilder->MakeSolid() == Standard_False) {
161       return;
162     }
163   }
164   TopoDS_Shape aResult = aPipeBuilder->Shape();
165   if(aResult.IsNull()) {
166     return;
167   }
168
169   // Setting naming.
170   this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
171   this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
172
173   // Setting result.
174   aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
175   GeomShapePtr aGeomSh(new GeomAPI_Shape());
176   aGeomSh->setImpl(new TopoDS_Shape(aResult));
177   this->setShape(aGeomSh);
178   this->setDone(true);
179 }
180
181 //==================================================================================================
182 void GeomAlgoAPI_Pipe::build(const ListOfShape& theBaseShapes,
183                              const ListOfShape& theLocations,
184                              const GeomShapePtr thePathShape)
185 {
186   if(theBaseShapes.empty() || (!theLocations.empty() && theLocations.size() != theBaseShapes.size())) {
187     return;
188   }
189
190   bool aHasLocations = false;
191   if(!theLocations.empty()) {
192     aHasLocations = true;
193   }
194
195   // Getting path.
196   TopoDS_Wire aPathWire;
197   if(!getPath(aPathWire, thePathShape)) {
198     return;
199   }
200
201   // Making pipe.
202   BRepOffsetAPI_MakePipeShell* aPipeBuilder = new BRepOffsetAPI_MakePipeShell(aPathWire);
203   if(!aPipeBuilder) {
204     return;
205   }
206   bool anIsSolidNeeded = false;
207   ListOfShape::const_iterator aBaseIt = theBaseShapes.cbegin();
208   ListOfShape::const_iterator aLocIt = theLocations.cbegin();
209   while(aBaseIt != theBaseShapes.cend()) {
210     GeomShapePtr aBase = *aBaseIt;
211     TopoDS_Shape aBaseShape;
212     TopAbs_ShapeEnum aBaseShapeType;
213     if(!getBase(aBaseShape, aBaseShapeType, aBase)) {
214       delete aPipeBuilder;
215       return;
216     }
217     ++aBaseIt;
218     if(aBaseShapeType == TopAbs_FACE) {
219       anIsSolidNeeded = true;
220     }
221
222     if(aHasLocations) {
223       GeomShapePtr aLocation = *aLocIt;
224       if(!aLocation.get() || aLocation->shapeType() != GeomAPI_Shape::VERTEX) {
225         delete aPipeBuilder;
226         return;
227       }
228       TopoDS_Vertex aLocationVertex = aLocation->impl<TopoDS_Vertex>();
229       ++aLocIt;
230       aPipeBuilder->Add(aBaseShape, aLocationVertex);
231     } else {
232       aPipeBuilder->Add(aBaseShape);
233     }
234   }
235
236   if(aPipeBuilder->IsReady() == Standard_False) {
237     delete aPipeBuilder;
238     return;
239   }
240
241   if(!buildPipe(aPipeBuilder)) {
242     delete aPipeBuilder;
243     return;
244   }
245   this->initialize(aPipeBuilder);
246
247   // Checking result.
248   if(anIsSolidNeeded) {
249     if(aPipeBuilder->MakeSolid() == Standard_False) {
250       return;
251     }
252   }
253   TopoDS_Shape aResult = aPipeBuilder->Shape();
254
255   // Setting naming.
256   GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
257   aFromShape->setImpl(new TopoDS_Shape(aPipeBuilder->FirstShape()));
258   aToShape->setImpl(new TopoDS_Shape(aPipeBuilder->LastShape()));
259   this->addFromShape(aFromShape);
260   this->addToShape(aToShape);
261
262   // Setting result.
263   if(aResult.IsNull()) {
264     return;
265   }
266   aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
267   GeomShapePtr aGeomSh(new GeomAPI_Shape());
268   aGeomSh->setImpl(new TopoDS_Shape(aResult));
269   this->setShape(aGeomSh);
270   this->setDone(true);
271 }
272
273 //==================================================================================================
274 void GeomAlgoAPI_Pipe::generated(const GeomShapePtr theShape,
275                                  ListOfShape& theHistory)
276 {
277   GeomAlgoAPI_MakeShape::generated(theShape, theHistory);
278 }
279
280 // Auxilary functions:
281 //==================================================================================================
282 bool getBase(TopoDS_Shape& theBaseOut,
283              TopAbs_ShapeEnum& theBaseTypeOut,
284              const GeomShapePtr theBaseShape)
285 {
286   if(!theBaseShape.get()) {
287     return false;
288   }
289
290   theBaseOut = theBaseShape->impl<TopoDS_Shape>();
291   if(theBaseOut.IsNull()) {
292     return false;
293   }
294   theBaseTypeOut = theBaseOut.ShapeType();
295   if(theBaseTypeOut == TopAbs_VERTEX) {
296     // Do nothing.
297   } else if(theBaseTypeOut == TopAbs_EDGE) {
298     theBaseOut = BRepBuilderAPI_MakeWire(TopoDS::Edge(theBaseOut)).Shape();
299   } else if(theBaseTypeOut == TopAbs_WIRE) {
300     // Do nothing.
301   } else if(theBaseTypeOut == TopAbs_FACE) {
302     TopExp_Explorer anExp(theBaseOut, TopAbs_WIRE);
303     theBaseOut = anExp.Current();
304   } else {
305     return false;
306   }
307
308   return true;
309 }
310
311 //==================================================================================================
312 bool getPath(TopoDS_Wire& thePathOut,
313              const GeomShapePtr thePathShape)
314 {
315   if(!thePathShape.get()) {
316     return false;
317   }
318
319   TopoDS_Shape aPathShape = thePathShape->impl<TopoDS_Shape>();
320   if(aPathShape.IsNull()) {
321     return false;
322   }
323   TopAbs_ShapeEnum aPathShapeType = aPathShape.ShapeType();
324   if(aPathShapeType == TopAbs_EDGE) {
325     TopoDS_Edge aPathEdge = TopoDS::Edge(aPathShape);
326     thePathOut = BRepBuilderAPI_MakeWire(aPathEdge).Wire();
327   } else if(aPathShapeType == TopAbs_WIRE) {
328     thePathOut = TopoDS::Wire(aPathShape);
329   } else {
330     return false;
331   }
332
333   return true;
334 }
335
336 //==================================================================================================
337 bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder)
338 {
339   thePipeBuilder->Build();
340
341   Standard_Boolean isDone = thePipeBuilder->IsDone();
342
343   if (!isDone) {
344     // Try to use Descrete Trihedron mode.
345     thePipeBuilder->SetDiscreteMode();
346     thePipeBuilder->Build();
347     isDone = thePipeBuilder->IsDone();
348   }
349
350   return isDone == Standard_True;
351 }
352
353 //==================================================================================================
354 ListOfShape getListFromShape(const TopoDS_Shape& theShape)
355 {
356   ListOfShape aList;
357
358   TopAbs_ShapeEnum aType = theShape.ShapeType();
359   if(aType == TopAbs_WIRE || aType == TopAbs_SHELL || aType == TopAbs_COMPOUND) {
360     for(TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) {
361       GeomShapePtr aGeomShape(new GeomAPI_Shape());
362       aGeomShape->setImpl(new TopoDS_Shape(anIt.Value()));
363       aList.push_back(aGeomShape);
364     }
365   } else {
366     GeomShapePtr aGeomShape(new GeomAPI_Shape());
367     aGeomShape->setImpl(new TopoDS_Shape(theShape));
368     aList.push_back(aGeomShape);
369   }
370
371   return aList;
372 }