Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_ShapeBuilder.cpp
1 // Copyright (C) 2014-2017  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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "GeomAlgoAPI_ShapeBuilder.h"
22
23 #include "GeomAlgoAPI_MakeShapeCustom.h"
24
25 #include <GeomAPI_ShapeIterator.h>
26
27 #include <BRep_Builder.hxx>
28 #include <BRepBuilderAPI_Copy.hxx>
29 #include <BRepExtrema_DistShapeShape.hxx>
30 #include <BRepTools_ReShape.hxx>
31 #include <Precision.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TopoDS.hxx>
34 #include <TopoDS_Edge.hxx>
35 #include <TopoDS_Iterator.hxx>
36 #include <TopoDS_Shape.hxx>
37
38 //==================================================================================================
39 void GeomAlgoAPI_ShapeBuilder::add(std::shared_ptr<GeomAPI_Shape> theShape,
40                                    const std::shared_ptr<GeomAPI_Shape> theShapeToAdd)
41 {
42   if(!theShape.get() || !theShapeToAdd.get()) {
43     return;
44   }
45
46   TopoDS_Shape* aShape = theShape->implPtr<TopoDS_Shape>();
47   const TopoDS_Shape& aShapeToAdd = theShapeToAdd->impl<TopoDS_Shape>();
48
49   BRep_Builder aBuilder;
50   aBuilder.Add(*aShape, aShapeToAdd);
51 }
52
53
54 //==================================================================================================
55 void GeomAlgoAPI_ShapeBuilder::remove(std::shared_ptr<GeomAPI_Shape> theShape,
56                                       const std::shared_ptr<GeomAPI_Shape> theShapeToRemove)
57 {
58   if(!theShape.get() || !theShapeToRemove.get()) {
59     return;
60   }
61
62   TopoDS_Shape* aShape = theShape->implPtr<TopoDS_Shape>();
63   const TopoDS_Shape& aShapeToRemove = theShapeToRemove->impl<TopoDS_Shape>();
64
65   BRep_Builder aBuilder;
66   aBuilder.Remove(*aShape, aShapeToRemove);
67 }
68
69 //==================================================================================================
70 GeomAlgoAPI_ShapeBuilder::GeomAlgoAPI_ShapeBuilder()
71 {
72 }
73
74 //==================================================================================================
75 void GeomAlgoAPI_ShapeBuilder::removeInternal(const std::shared_ptr<GeomAPI_Shape> theShape)
76 {
77   GeomShapePtr aResultShape;
78
79   GeomAPI_Shape::ShapeType aBaseShapeType = theShape->shapeType();
80   if(aBaseShapeType == GeomAPI_Shape::WIRE) {
81     aResultShape = theShape->emptyCopied();
82     std::shared_ptr<GeomAlgoAPI_MakeShapeCustom>
83       aMakeShapeCustom(new GeomAlgoAPI_MakeShapeCustom());
84     for(GeomAPI_ShapeIterator anIter(theShape); anIter.more(); anIter.next()) {
85       GeomShapePtr aSubShape = anIter.current();
86       GeomShapePtr aSubShapeCopy = aSubShape->emptyCopied();
87       for(GeomAPI_ShapeIterator aSubIter(aSubShape); aSubIter.more(); aSubIter.next()) {
88         GeomShapePtr aSubOfSubShape = aSubIter.current();
89         if(aSubOfSubShape->orientation() != GeomAPI_Shape::INTERNAL) {
90           GeomAlgoAPI_ShapeBuilder::add(aSubShapeCopy, aSubOfSubShape);
91         }
92       }
93       aMakeShapeCustom->addModified(aSubShape, aSubShapeCopy);
94       GeomAlgoAPI_ShapeBuilder::add(aResultShape, aSubShapeCopy);
95     }
96     this->appendAlgo(aMakeShapeCustom);
97   } else if(aBaseShapeType == GeomAPI_Shape::FACE) {
98     const TopoDS_Shape& aBaseShape = theShape->impl<TopoDS_Shape>();
99     BRepBuilderAPI_Copy* aCopyBuilder = new BRepBuilderAPI_Copy(aBaseShape);
100     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
101       new GeomAlgoAPI_MakeShape(aCopyBuilder)));
102     if(!aCopyBuilder->IsDone()) {
103       return;
104     }
105     TopoDS_Shape aShape = aCopyBuilder->Shape();
106     TopoDS_Shape aShapeCopy = aShape.EmptyCopied();
107     BRep_Builder aBuilder;
108     for(TopoDS_Iterator anIt(aShape); anIt.More(); anIt.Next()) {
109       const TopoDS_Shape& aSubShape = anIt.Value();
110       if(aSubShape.ShapeType() == TopAbs_WIRE
111           && aSubShape.Orientation() != TopAbs_INTERNAL) {
112         aBuilder.Add(aShapeCopy, aSubShape);
113       }
114     }
115     aResultShape.reset(new GeomAPI_Shape());
116     aResultShape->setImpl(new TopoDS_Shape(aShapeCopy));
117   }
118
119   setShape(aResultShape);
120   setDone(true);
121 }
122
123 //==================================================================================================
124 void GeomAlgoAPI_ShapeBuilder::addInternal(const std::shared_ptr<GeomAPI_Shape> theShape,
125                                            const ListOfShape& theShapesToAdd)
126 {
127   // Get base shape.
128   if(!theShape.get()) {
129     return;
130   }
131   const TopoDS_Shape& aBaseShape = theShape->impl<TopoDS_Shape>();
132   TopAbs_ShapeEnum aBaseShapeType = aBaseShape.ShapeType();
133
134   // Copy base shape.
135   BRepBuilderAPI_Copy* aCopyBuilder = new BRepBuilderAPI_Copy(aBaseShape);
136   this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aCopyBuilder)));
137   if(!aCopyBuilder->IsDone()) {
138     return;
139   }
140   TopoDS_Shape aResultShape = aCopyBuilder->Shape();
141
142   // Copy sub-shapes from list to new shape.
143   BRep_Builder aBuilder;
144   std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMakeShapeCustom(new GeomAlgoAPI_MakeShapeCustom());
145   for(ListOfShape::const_iterator
146       anIt = theShapesToAdd.cbegin(); anIt != theShapesToAdd.cend(); ++anIt) {
147     TopoDS_Shape aShapeToAdd = (*anIt)->impl<TopoDS_Shape>();
148     TopoDS_Shape aModShapeToAdd = aShapeToAdd;
149     aModShapeToAdd.Orientation(TopAbs_INTERNAL);
150     for(TopExp_Explorer aResExp(aResultShape, TopAbs_VERTEX); aResExp.More(); aResExp.Next()) {
151       const TopoDS_Vertex& aVertexInRes = TopoDS::Vertex(aResExp.Current());
152       const gp_Pnt aPntInRes = BRep_Tool::Pnt(aVertexInRes);
153       for(TopExp_Explorer anAddExp(aShapeToAdd, TopAbs_VERTEX); anAddExp.More(); anAddExp.Next()) {
154         const TopoDS_Vertex& aVertexInAdd = TopoDS::Vertex(anAddExp.Current());
155         const gp_Pnt aPntInAdd = BRep_Tool::Pnt(aVertexInAdd);
156         if(aPntInRes.Distance(aPntInAdd) < Precision::Confusion()) {
157           BRepTools_ReShape aReShape;
158           TopoDS_Shape aVertexInResMod = aVertexInRes;
159           aVertexInResMod.Orientation(aVertexInAdd.Orientation());
160           aReShape.Replace(aVertexInAdd, aVertexInResMod);
161           aModShapeToAdd = aReShape.Apply(aModShapeToAdd);
162         }
163       }
164     }
165
166     GeomShapePtr aGeomBaseShape(new GeomAPI_Shape());
167     GeomShapePtr aGeomModShape(new GeomAPI_Shape());
168     aGeomBaseShape->setImpl(new TopoDS_Shape(aShapeToAdd));
169     aGeomModShape->setImpl(new TopoDS_Shape(aModShapeToAdd));
170     aMakeShapeCustom->addModified(aGeomBaseShape, aGeomModShape);
171     aShapeToAdd = aModShapeToAdd;
172
173     TopAbs_ShapeEnum aShapeToAddType = aShapeToAdd.ShapeType();
174     if(aBaseShapeType == TopAbs_WIRE) {
175       if(aShapeToAddType == TopAbs_VERTEX) {
176         // Find on which edge vertex is lie and add to this edge.
177         for(TopExp_Explorer
178             aResultExp(aResultShape, TopAbs_EDGE); aResultExp.More(); aResultExp.Next()) {
179           TopoDS_Shape anEdge = aResultExp.Current();
180           BRepExtrema_DistShapeShape aDist(anEdge, aShapeToAdd);
181           aDist.Perform();
182           if(aDist.IsDone() && aDist.Value() <= Precision::Confusion()) {
183             aShapeToAdd.Orientation(TopAbs_INTERNAL);
184             Standard_Boolean aFreeFlag = anEdge.Free();
185             anEdge.Free(Standard_True);
186             aBuilder.Add(anEdge, aShapeToAdd);
187             anEdge.Free(aFreeFlag);
188             break;
189           }
190         }
191       }
192     } else if(aBaseShapeType == GeomAPI_Shape::FACE) {
193       if(aShapeToAddType == GeomAPI_Shape::EDGE) {
194         aShapeToAdd.Orientation(TopAbs_INTERNAL);
195         TopoDS_Wire aWire;
196         aBuilder.MakeWire(aWire);
197         aBuilder.Add(aWire, aShapeToAdd);
198         aShapeToAdd = aWire;
199         aShapeToAdd.Orientation(TopAbs_INTERNAL);
200       }
201       aBuilder.Add(aResultShape, aShapeToAdd);
202     }
203   }
204   this->appendAlgo(aMakeShapeCustom);
205
206   // Set result.
207   std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
208   aShape->setImpl(new TopoDS_Shape(aResultShape));
209   setShape(aShape);
210   setDone(true);
211 }