]> SALOME platform Git repositories - modules/shaper.git/blob - src/GeomAlgoAPI/GeomAlgoAPI_Pipe.cpp
Salome HOME
b0a693cebbea4a10e5e1bccfaeaa90be2a26594c
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_Pipe.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
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_Pipe.h"
21
22 #include "GeomAlgoAPI_DFLoader.h"
23
24 #include <GeomAPI_Dir.h>
25 #include <GeomAPI_Edge.h>
26 #include <GeomAPI_Lin.h>
27
28 #include <BRep_Tool.hxx>
29 #include <BRepExtrema_DistShapeShape.hxx>
30 #include <BRepOffsetAPI_MakePipe.hxx>
31 #include <BRepOffsetAPI_MakePipeShell.hxx>
32 #include <BRepBuilderAPI_MakeWire.hxx>
33 #include <Geom_Curve.hxx>
34 #include <Geom_Line.hxx>
35 #include <gp_Lin.hxx>
36 #include <NCollection_List.hxx>
37 #include <TopExp_Explorer.hxx>
38 #include <TopoDS.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <Precision.hxx>
41
42 static bool getBase(TopoDS_Shape& theBaseOut,
43                     TopAbs_ShapeEnum& theBaseTypeOut,
44                     const GeomShapePtr theBaseShape);
45 static bool getPath(TopoDS_Wire& thePathOut,
46                     const GeomShapePtr thePathShape);
47 static gp_Trsf getPathToBaseTranslation(const TopoDS_Shape& theBase,
48                                         const TopoDS_Shape& thePath);
49 static bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder);
50 static ListOfShape getListFromShape(const TopoDS_Shape& theShape);
51
52 //==================================================================================================
53 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
54                                    const GeomShapePtr thePathShape)
55 {
56   build(theBaseShape, thePathShape);
57 }
58
59 //==================================================================================================
60 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
61                                    const GeomShapePtr thePathShape,
62                                    const GeomShapePtr theBiNormal)
63 {
64   build(theBaseShape, thePathShape, theBiNormal);
65 }
66
67 //==================================================================================================
68 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const ListOfShape& theBaseShapes,
69                                    const ListOfShape& theLocations,
70                                    const GeomShapePtr thePathShape)
71 {
72   build(theBaseShapes, theLocations, thePathShape);
73 }
74
75 //==================================================================================================
76 void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
77                              const GeomShapePtr thePathShape)
78 {
79   // Getting base shape.
80   if(!theBaseShape.get()) {
81     return;
82   }
83   TopoDS_Shape aBaseShape = theBaseShape->impl<TopoDS_Shape>();
84   if(aBaseShape.IsNull()) {
85     return;
86   }
87   TopAbs_ShapeEnum aBaseShapeType = aBaseShape.ShapeType();
88   if(aBaseShapeType != TopAbs_VERTEX && aBaseShapeType != TopAbs_EDGE &&
89      aBaseShapeType != TopAbs_WIRE && aBaseShapeType != TopAbs_FACE &&
90      aBaseShapeType != TopAbs_SHELL && aBaseShapeType != TopAbs_COMPOUND) {
91     return;
92   }
93
94   // Getting path.
95   TopoDS_Wire aPathWire;
96   if(!getPath(aPathWire, thePathShape)) {
97     return;
98   }
99   aPathWire.Move(getPathToBaseTranslation(aBaseShape, aPathWire));
100
101   // Making pipe.
102   BRepOffsetAPI_MakePipe* aPipeBuilder = new BRepOffsetAPI_MakePipe(aPathWire, aBaseShape);
103   if(!aPipeBuilder) {
104     return;
105   }
106   aPipeBuilder->Build();
107
108   // Checking result.
109   if(!aPipeBuilder->IsDone() || aPipeBuilder->Shape().IsNull()) {
110     delete aPipeBuilder;
111     return;
112   }
113   this->initialize(aPipeBuilder);
114
115   // Setting naming.
116   this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
117   this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
118
119   // Setting result.
120   TopoDS_Shape aResult = aPipeBuilder->Shape();
121   aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
122   GeomShapePtr aGeomSh(new GeomAPI_Shape());
123   aGeomSh->setImpl(new TopoDS_Shape(aResult));
124   this->setShape(aGeomSh);
125   this->setDone(true);
126 }
127
128 //==================================================================================================
129 void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
130                              const GeomShapePtr thePathShape,
131                              const GeomShapePtr theBiNormal)
132 {
133   // Getting base shape and path.
134   TopoDS_Shape aBaseShape;
135   TopAbs_ShapeEnum aBaseShapeType;
136   TopoDS_Wire aPathWire;
137   if (!getBase(aBaseShape, aBaseShapeType, theBaseShape) ||
138       !getPath(aPathWire, thePathShape) ||
139       !theBiNormal.get()) {
140     return;
141   }
142
143   aPathWire.Move(getPathToBaseTranslation(theBaseShape->impl<TopoDS_Shape>(), aPathWire));
144
145   // Getting Bi-Normal.
146   TopoDS_Shape aBiNormalShape = theBiNormal->impl<TopoDS_Shape>();
147   if(aBiNormalShape.IsNull() || aBiNormalShape.ShapeType() != TopAbs_EDGE) {
148     return;
149   }
150   TopoDS_Edge aBiNormalEdge = TopoDS::Edge(aBiNormalShape);
151   Standard_Real aFirst, aLast;
152   Handle(Geom_Curve) aBiNormalCurve = BRep_Tool::Curve(aBiNormalEdge, aFirst, aLast);
153   Handle(Geom_Line) aBiNormalLine = Handle(Geom_Line)::DownCast(aBiNormalCurve);
154   if(aBiNormalLine.IsNull()) {
155     return;
156   }
157   gp_Dir aBiNormalDir = aBiNormalLine->Lin().Direction();
158
159   // Making pipe.
160   BRepOffsetAPI_MakePipeShell* aPipeBuilder = new BRepOffsetAPI_MakePipeShell(aPathWire);
161   if(!aPipeBuilder) {
162     return;
163   }
164   aPipeBuilder->Add(aBaseShape);
165   aPipeBuilder->SetMode(aBiNormalDir);
166   if(!buildPipe(aPipeBuilder)) {
167     delete aPipeBuilder;
168     return;
169   }
170   this->initialize(aPipeBuilder);
171
172   // Checking result.
173   if(aBaseShapeType == TopAbs_FACE && !aPipeBuilder->MakeSolid()) {
174     return;
175   }
176   TopoDS_Shape aResult = aPipeBuilder->Shape();
177   if(aResult.IsNull()) {
178     return;
179   }
180
181   // Setting naming.
182   this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
183   this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
184
185   // Setting result.
186   aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
187   GeomShapePtr aGeomSh(new GeomAPI_Shape());
188   aGeomSh->setImpl(new TopoDS_Shape(aResult));
189   this->setShape(aGeomSh);
190   this->setDone(true);
191 }
192
193 //==================================================================================================
194 void GeomAlgoAPI_Pipe::build(const ListOfShape& theBaseShapes,
195                              const ListOfShape& theLocations,
196                              const GeomShapePtr thePathShape)
197 {
198   if(theBaseShapes.empty() ||
199      (!theLocations.empty() && theLocations.size() != theBaseShapes.size())) {
200     return;
201   }
202
203   // Getting base shape and path.
204   TopoDS_Shape aBaseShape;
205   TopAbs_ShapeEnum aBaseShapeType;
206   TopoDS_Wire aPathWire;
207   if (!getBase(aBaseShape, aBaseShapeType, theBaseShapes.front()) ||
208       !getPath(aPathWire, thePathShape)) {
209     return;
210   }
211
212   TopoDS_Shape aReallyBase = theBaseShapes.front()->impl<TopoDS_Shape>();
213   gp_Trsf aTrsf = getPathToBaseTranslation(aReallyBase, aPathWire);
214   aPathWire.Move(aTrsf);
215
216   // Get locations after moving path shape.
217   std::list<TopoDS_Vertex> aLocations;
218   for (ListOfShape::const_iterator aLocIt = theLocations.cbegin();
219        aLocIt != theLocations.cend();
220        ++aLocIt)
221   {
222     GeomShapePtr aLocation = *aLocIt;
223     if (!aLocation.get() || aLocation->shapeType() != GeomAPI_Shape::VERTEX) {
224       return;
225     }
226
227     TopoDS_Vertex aLocationVertex = aLocation->impl<TopoDS_Vertex>();
228     TopoDS_Vertex aMovedVertex;
229     for (TopExp_Explorer anExp(aPathWire, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
230       if (anExp.Current().IsPartner(aLocationVertex)) {
231         aMovedVertex = TopoDS::Vertex(anExp.Current());
232         aLocations.push_back(aMovedVertex);
233         break;
234       }
235     }
236     if (aMovedVertex.IsNull()) {
237       return;
238     }
239   }
240
241   if (theLocations.size() != aLocations.size()) {
242     return;
243   }
244
245   bool aHasLocations = !aLocations.empty();
246
247   // Making pipe.
248   Standard_Boolean isDone = Standard_False;
249   bool anIsSolidNeeded = false;
250   BRepOffsetAPI_MakePipeShell* aPipeBuilder;
251   for(int i = 0; i < 2; ++i) {
252     aPipeBuilder = new BRepOffsetAPI_MakePipeShell(aPathWire);
253     if(!aPipeBuilder) {
254       return;
255     }
256     ListOfShape::const_iterator aBaseIt = theBaseShapes.cbegin();
257     std::list<TopoDS_Vertex>::const_iterator aLocationsIt = aLocations.cbegin();
258     while(aBaseIt != theBaseShapes.cend()) {
259       GeomShapePtr aBase = *aBaseIt;
260       if(!getBase(aBaseShape, aBaseShapeType, aBase)) {
261         delete aPipeBuilder;
262         return;
263       }
264       ++aBaseIt;
265       if(aBaseShapeType == TopAbs_FACE) {
266         anIsSolidNeeded = true;
267       }
268
269       if(aHasLocations) {
270         aPipeBuilder->Add(aBaseShape, *aLocationsIt);
271         ++aLocationsIt;
272       } else {
273         aPipeBuilder->Add(aBaseShape);
274       }
275     }
276
277     if(aPipeBuilder->IsReady() == Standard_False) {
278       delete aPipeBuilder;
279       return;
280     }
281
282     if (i == 1) {
283        // Try to use Descrete Trihedron mode.
284       aPipeBuilder->SetDiscreteMode();
285     }
286     aPipeBuilder->Build();
287     isDone = aPipeBuilder->IsDone();
288
289     if (isDone) {
290       break;
291     }
292
293     delete aPipeBuilder;
294   }
295
296   if (!isDone) {
297     return;
298   }
299
300   this->initialize(aPipeBuilder);
301
302   // Checking result.
303   if(anIsSolidNeeded && !aPipeBuilder->MakeSolid()) {
304     return;
305   }
306   TopoDS_Shape aResult = aPipeBuilder->Shape();
307
308   // Setting naming.
309   GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
310   aFromShape->setImpl(new TopoDS_Shape(aPipeBuilder->FirstShape()));
311   aToShape->setImpl(new TopoDS_Shape(aPipeBuilder->LastShape()));
312   fixOrientation(aFromShape);
313   fixOrientation(aToShape);
314   this->addFromShape(aFromShape);
315   this->addToShape(aToShape);
316
317   // Setting result.
318   if(aResult.IsNull()) {
319     return;
320   }
321   aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
322   GeomShapePtr aGeomSh(new GeomAPI_Shape());
323   aGeomSh->setImpl(new TopoDS_Shape(aResult));
324   this->setShape(aGeomSh);
325   this->setDone(true);
326 }
327
328 //==================================================================================================
329 void GeomAlgoAPI_Pipe::generated(const GeomShapePtr theShape,
330                                  ListOfShape& theHistory)
331 {
332   GeomAlgoAPI_MakeShape::generated(theShape, theHistory);
333 }
334
335 // Auxilary functions:
336 //==================================================================================================
337 bool getBase(TopoDS_Shape& theBaseOut,
338              TopAbs_ShapeEnum& theBaseTypeOut,
339              const GeomShapePtr theBaseShape)
340 {
341   if(!theBaseShape.get()) {
342     return false;
343   }
344
345   theBaseOut = theBaseShape->impl<TopoDS_Shape>();
346   if(theBaseOut.IsNull()) {
347     return false;
348   }
349   theBaseTypeOut = theBaseOut.ShapeType();
350   if(theBaseTypeOut == TopAbs_VERTEX) {
351     // Do nothing.
352   } else if(theBaseTypeOut == TopAbs_EDGE) {
353     theBaseOut = BRepBuilderAPI_MakeWire(TopoDS::Edge(theBaseOut)).Shape();
354   } else if(theBaseTypeOut == TopAbs_WIRE) {
355     // Do nothing.
356   } else if(theBaseTypeOut == TopAbs_FACE) {
357     TopExp_Explorer anExp(theBaseOut, TopAbs_WIRE);
358     theBaseOut = anExp.Current();
359   } else {
360     return false;
361   }
362
363   return true;
364 }
365
366 //==================================================================================================
367 bool getPath(TopoDS_Wire& thePathOut, const GeomShapePtr thePathShape)
368 {
369   if(!thePathShape.get()) {
370     return false;
371   }
372
373   TopoDS_Shape aPathShape = thePathShape->impl<TopoDS_Shape>();
374   if(aPathShape.IsNull()) {
375     return false;
376   }
377   TopAbs_ShapeEnum aPathShapeType = aPathShape.ShapeType();
378   if(aPathShapeType == TopAbs_EDGE) {
379     TopoDS_Edge aPathEdge = TopoDS::Edge(aPathShape);
380     thePathOut = BRepBuilderAPI_MakeWire(aPathEdge).Wire();
381   } else if(aPathShapeType == TopAbs_WIRE) {
382     thePathOut = TopoDS::Wire(aPathShape);
383   } else {
384     return false;
385   }
386
387   return true;
388 }
389
390 //==================================================================================================
391 gp_Trsf getPathToBaseTranslation(const TopoDS_Shape& theBase, const TopoDS_Shape& thePath)
392 {
393   gp_Trsf aTranslation;
394
395   BRepExtrema_DistShapeShape aDist(theBase, thePath);
396   aDist.Perform();
397   if (aDist.IsDone() && aDist.Value() > Precision::Confusion()) {
398     gp_Pnt aPntBase = aDist.PointOnShape1(1);
399     gp_Pnt aPntPath = aDist.PointOnShape2(1);
400     aTranslation.SetTranslation(aPntPath, aPntBase);
401   }
402
403   return aTranslation;
404 }
405
406 //==================================================================================================
407 bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder)
408 {
409   thePipeBuilder->Build();
410
411   Standard_Boolean isDone = thePipeBuilder->IsDone();
412
413   if (!isDone) {
414     // Try to use Descrete Trihedron mode.
415     thePipeBuilder->SetDiscreteMode();
416     thePipeBuilder->Build();
417     isDone = thePipeBuilder->IsDone();
418   }
419
420   return isDone == Standard_True;
421 }
422
423 //==================================================================================================
424 ListOfShape getListFromShape(const TopoDS_Shape& theShape)
425 {
426   ListOfShape aList;
427
428   TopAbs_ShapeEnum aType = theShape.ShapeType();
429   if(aType == TopAbs_WIRE || aType == TopAbs_SHELL || aType == TopAbs_COMPOUND) {
430     for(TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) {
431       GeomShapePtr aGeomShape(new GeomAPI_Shape());
432       aGeomShape->setImpl(new TopoDS_Shape(anIt.Value()));
433       aList.push_back(aGeomShape);
434     }
435   } else {
436     GeomShapePtr aGeomShape(new GeomAPI_Shape());
437     aGeomShape->setImpl(new TopoDS_Shape(theShape));
438     aList.push_back(aGeomShape);
439   }
440
441   return aList;
442 }