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