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