1 // Copyright (C) 2014-2019 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "GeomAlgoAPI_Pipe.h"
22 #include "GeomAlgoAPI_DFLoader.h"
24 #include <GeomAPI_Dir.h>
25 #include <GeomAPI_Edge.h>
26 #include <GeomAPI_Lin.h>
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>
36 #include <NCollection_List.hxx>
37 #include <TopExp_Explorer.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <Precision.hxx>
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);
52 //==================================================================================================
53 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
54 const GeomShapePtr thePathShape)
56 build(theBaseShape, thePathShape);
59 //==================================================================================================
60 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
61 const GeomShapePtr thePathShape,
62 const GeomShapePtr theBiNormal)
64 build(theBaseShape, thePathShape, theBiNormal);
67 //==================================================================================================
68 GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const ListOfShape& theBaseShapes,
69 const ListOfShape& theLocations,
70 const GeomShapePtr thePathShape)
72 build(theBaseShapes, theLocations, thePathShape);
75 //==================================================================================================
76 void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
77 const GeomShapePtr thePathShape)
79 // Getting base shape.
80 if(!theBaseShape.get()) {
83 TopoDS_Shape aBaseShape = theBaseShape->impl<TopoDS_Shape>();
84 if(aBaseShape.IsNull()) {
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) {
95 TopoDS_Wire aPathWire;
96 if(!getPath(aPathWire, thePathShape)) {
99 aPathWire.Move(getPathToBaseTranslation(aBaseShape, aPathWire));
102 BRepOffsetAPI_MakePipe* aPipeBuilder = new BRepOffsetAPI_MakePipe(aPathWire, aBaseShape);
106 aPipeBuilder->Build();
109 if(!aPipeBuilder->IsDone() || aPipeBuilder->Shape().IsNull()) {
113 this->initialize(aPipeBuilder);
116 this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
117 this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
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);
128 //==================================================================================================
129 void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
130 const GeomShapePtr thePathShape,
131 const GeomShapePtr theBiNormal)
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()) {
143 aPathWire.Move(getPathToBaseTranslation(theBaseShape->impl<TopoDS_Shape>(), aPathWire));
145 // Getting Bi-Normal.
146 TopoDS_Shape aBiNormalShape = theBiNormal->impl<TopoDS_Shape>();
147 if(aBiNormalShape.IsNull() || aBiNormalShape.ShapeType() != TopAbs_EDGE) {
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()) {
157 gp_Dir aBiNormalDir = aBiNormalLine->Lin().Direction();
160 BRepOffsetAPI_MakePipeShell* aPipeBuilder = new BRepOffsetAPI_MakePipeShell(aPathWire);
164 aPipeBuilder->Add(aBaseShape);
165 aPipeBuilder->SetMode(aBiNormalDir);
166 if(!buildPipe(aPipeBuilder)) {
170 this->initialize(aPipeBuilder);
173 if(aBaseShapeType == TopAbs_FACE && !aPipeBuilder->MakeSolid()) {
176 TopoDS_Shape aResult = aPipeBuilder->Shape();
177 if(aResult.IsNull()) {
182 this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
183 this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
186 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
187 GeomShapePtr aGeomSh(new GeomAPI_Shape());
188 aGeomSh->setImpl(new TopoDS_Shape(aResult));
189 this->setShape(aGeomSh);
193 //==================================================================================================
194 void GeomAlgoAPI_Pipe::build(const ListOfShape& theBaseShapes,
195 const ListOfShape& theLocations,
196 const GeomShapePtr thePathShape)
198 if(theBaseShapes.empty() ||
199 (!theLocations.empty() && theLocations.size() != theBaseShapes.size())) {
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)) {
212 TopoDS_Shape aReallyBase = theBaseShapes.front()->impl<TopoDS_Shape>();
213 gp_Trsf aTrsf = getPathToBaseTranslation(aReallyBase, aPathWire);
214 aPathWire.Move(aTrsf);
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();
222 GeomShapePtr aLocation = *aLocIt;
223 if (!aLocation.get() || aLocation->shapeType() != GeomAPI_Shape::VERTEX) {
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);
236 if (aMovedVertex.IsNull()) {
241 if (theLocations.size() != aLocations.size()) {
245 bool aHasLocations = !aLocations.empty();
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);
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)) {
265 if(aBaseShapeType == TopAbs_FACE) {
266 anIsSolidNeeded = true;
270 aPipeBuilder->Add(aBaseShape, *aLocationsIt);
273 aPipeBuilder->Add(aBaseShape);
277 if(aPipeBuilder->IsReady() == Standard_False) {
283 // Try to use Descrete Trihedron mode.
284 aPipeBuilder->SetDiscreteMode();
286 aPipeBuilder->Build();
287 isDone = aPipeBuilder->IsDone();
300 this->initialize(aPipeBuilder);
303 if(anIsSolidNeeded && !aPipeBuilder->MakeSolid()) {
306 TopoDS_Shape aResult = aPipeBuilder->Shape();
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);
318 if(aResult.IsNull()) {
321 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
322 GeomShapePtr aGeomSh(new GeomAPI_Shape());
323 aGeomSh->setImpl(new TopoDS_Shape(aResult));
324 this->setShape(aGeomSh);
328 //==================================================================================================
329 void GeomAlgoAPI_Pipe::generated(const GeomShapePtr theShape,
330 ListOfShape& theHistory)
332 GeomAlgoAPI_MakeShape::generated(theShape, theHistory);
335 // Auxilary functions:
336 //==================================================================================================
337 bool getBase(TopoDS_Shape& theBaseOut,
338 TopAbs_ShapeEnum& theBaseTypeOut,
339 const GeomShapePtr theBaseShape)
341 if(!theBaseShape.get()) {
345 theBaseOut = theBaseShape->impl<TopoDS_Shape>();
346 if(theBaseOut.IsNull()) {
349 theBaseTypeOut = theBaseOut.ShapeType();
350 if(theBaseTypeOut == TopAbs_VERTEX) {
352 } else if(theBaseTypeOut == TopAbs_EDGE) {
353 theBaseOut = BRepBuilderAPI_MakeWire(TopoDS::Edge(theBaseOut)).Shape();
354 } else if(theBaseTypeOut == TopAbs_WIRE) {
356 } else if(theBaseTypeOut == TopAbs_FACE) {
357 TopExp_Explorer anExp(theBaseOut, TopAbs_WIRE);
358 theBaseOut = anExp.Current();
366 //==================================================================================================
367 bool getPath(TopoDS_Wire& thePathOut, const GeomShapePtr thePathShape)
369 if(!thePathShape.get()) {
373 TopoDS_Shape aPathShape = thePathShape->impl<TopoDS_Shape>();
374 if(aPathShape.IsNull()) {
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);
390 //==================================================================================================
391 gp_Trsf getPathToBaseTranslation(const TopoDS_Shape& theBase, const TopoDS_Shape& thePath)
393 gp_Trsf aTranslation;
395 BRepExtrema_DistShapeShape aDist(theBase, thePath);
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);
406 //==================================================================================================
407 bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder)
409 thePipeBuilder->Build();
411 Standard_Boolean isDone = thePipeBuilder->IsDone();
414 // Try to use Descrete Trihedron mode.
415 thePipeBuilder->SetDiscreteMode();
416 thePipeBuilder->Build();
417 isDone = thePipeBuilder->IsDone();
420 return isDone == Standard_True;
423 //==================================================================================================
424 ListOfShape getListFromShape(const TopoDS_Shape& theShape)
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);
436 GeomShapePtr aGeomShape(new GeomAPI_Shape());
437 aGeomShape->setImpl(new TopoDS_Shape(theShape));
438 aList.push_back(aGeomShape);