]> SALOME platform Git repositories - modules/shaper.git/blob - src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp
Salome HOME
f156e3d58e42dc2e4e5a48c0a496375d19604a8b
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_MakeShape.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_MakeShape.h"
22
23 #include <BOPAlgo_Builder.hxx>
24 #include <BRep_Tool.hxx>
25 #include <BRepBuilderAPI_MakeShape.hxx>
26 #include <BRepCheck_Analyzer.hxx>
27 #include <BRepGProp.hxx>
28 #include <GProp_GProps.hxx>
29 #include <Precision.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopTools_ListOfShape.hxx>
32 #include <TopTools_ListIteratorOfListOfShape.hxx>
33 #include <GeomAPI_ShapeExplorer.h>
34 #include <GeomAPI_ShapeIterator.h>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Builder.hxx>
37 #include <TopoDS_Edge.hxx>
38
39 // new shape -> old shapes -> index in the old shape
40 typedef NCollection_DataMap<TopoDS_Shape,
41   NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>, TopTools_ShapeMapHasher>
42   MapNewToOld;
43 typedef
44   NCollection_DataMap<int, NCollection_DataMap<TopoDS_Shape, MapNewToOld, TopTools_ShapeMapHasher> >
45   HistoryMap;
46
47 //==================================================================================================
48 GeomAlgoAPI_MakeShape::GeomAlgoAPI_MakeShape()
49 : myBuilderType(Unknown),
50   myDone(false)
51 {
52   myHist = 0;
53 }
54
55 //==================================================================================================
56 GeomAlgoAPI_MakeShape::~GeomAlgoAPI_MakeShape()
57 {
58   if (myHist) {
59     delete (HistoryMap*)myHist;
60   }
61 }
62
63 //==================================================================================================
64 bool GeomAlgoAPI_MakeShape::isDone() const
65 {
66   return myDone;
67 }
68
69 //==================================================================================================
70 const GeomShapePtr GeomAlgoAPI_MakeShape::shape() const
71 {
72   return myShape;
73 }
74
75 //==================================================================================================
76 bool GeomAlgoAPI_MakeShape::isValid() const
77 {
78   BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
79   return (aChecker.IsValid() == Standard_True);
80 }
81
82 //==================================================================================================
83 std::shared_ptr<GeomAPI_DataMapOfShapeShape> GeomAlgoAPI_MakeShape::mapOfSubShapes() const
84 {
85   return myMap;
86 }
87
88 //==================================================================================================
89 void GeomAlgoAPI_MakeShape::generated(const GeomShapePtr theOldShape,
90                                       ListOfShape& theNewShapes)
91 {
92   TopTools_ListOfShape aList;
93   if(myBuilderType == OCCT_BRepBuilderAPI_MakeShape) {
94     BRepBuilderAPI_MakeShape* aMakeShape = implPtr<BRepBuilderAPI_MakeShape>();
95     aList = aMakeShape->Generated(theOldShape->impl<TopoDS_Shape>());
96   } else if(myBuilderType == OCCT_BOPAlgo_Builder) {
97     BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
98     aList = aBOPBuilder->Generated(theOldShape->impl<TopoDS_Shape>());
99   }
100   for(TopTools_ListIteratorOfListOfShape anIt(aList); anIt.More(); anIt.Next()) {
101     GeomShapePtr aShape(new GeomAPI_Shape());
102     aShape->setImpl(new TopoDS_Shape(anIt.Value()));
103     if (!isValidForHistory(aShape)) continue;
104     fixOrientation(aShape);
105     theNewShapes.push_back(aShape);
106   }
107 }
108
109 //==================================================================================================
110 void GeomAlgoAPI_MakeShape::modified(const GeomShapePtr theOldShape,
111                                      ListOfShape& theNewShapes)
112 {
113   TopTools_ListOfShape aList;
114   if(myBuilderType == OCCT_BRepBuilderAPI_MakeShape) {
115     BRepBuilderAPI_MakeShape* aMakeShape = implPtr<BRepBuilderAPI_MakeShape>();
116     try {
117       aList = aMakeShape->Modified(theOldShape->impl<TopoDS_Shape>());
118     } catch(Standard_NoSuchObject) {
119     }
120   } else if(myBuilderType == OCCT_BOPAlgo_Builder) {
121     BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
122     aList = aBOPBuilder->Modified(theOldShape->impl<TopoDS_Shape>());
123   }
124   for(TopTools_ListIteratorOfListOfShape anIt(aList); anIt.More(); anIt.Next()) {
125     GeomShapePtr aShape(new GeomAPI_Shape());
126     aShape->setImpl(new TopoDS_Shape(anIt.Value()));
127     if (!isValidForHistory(aShape)) continue;
128     fixOrientation(aShape);
129     theNewShapes.push_back(aShape);
130   }
131 }
132
133 //==================================================================================================
134 bool GeomAlgoAPI_MakeShape::isDeleted(const GeomShapePtr theOldShape)
135 {
136   bool isDeleted = false;
137   if(myBuilderType == OCCT_BRepBuilderAPI_MakeShape) {
138     BRepBuilderAPI_MakeShape* aMakeShape = implPtr<BRepBuilderAPI_MakeShape>();
139     isDeleted = aMakeShape->IsDeleted(theOldShape->impl<TopoDS_Shape>()) == Standard_True;
140   } else if(myBuilderType == OCCT_BOPAlgo_Builder) {
141     BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
142     isDeleted = aBOPBuilder->IsDeleted(theOldShape->impl<TopoDS_Shape>()) == Standard_True;
143   }
144
145   return isDeleted;
146 }
147
148 //==================================================================================================
149 void GeomAlgoAPI_MakeShape::setBuilderType(const BuilderType theBuilderType)
150 {
151   myBuilderType = theBuilderType;
152 }
153
154 //==================================================================================================
155 void GeomAlgoAPI_MakeShape::setDone(const bool theFlag)
156 {
157   myDone = theFlag;
158 }
159
160 //==================================================================================================
161 void GeomAlgoAPI_MakeShape::setShape(const GeomShapePtr theShape)
162 {
163   if(myShape.get() && myShape->isEqual(theShape)) {
164     return;
165   }
166
167   myShape = theShape;
168
169   // Filling data map to keep correct orientation of sub-shapes.
170   if(myShape.get()) {
171     if(myMap.get()) {
172       myMap->clear();
173     } else {
174       myMap.reset(new GeomAPI_DataMapOfShapeShape);
175     }
176
177     const TopoDS_Shape& aTopoDSShape = myShape->impl<TopoDS_Shape>();
178     for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_VERTEX); anExp.More(); anExp.Next()) {
179       GeomShapePtr aCurrentShape(new GeomAPI_Shape());
180       aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current()));
181       myMap->bind(aCurrentShape, aCurrentShape);
182     }
183     for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_EDGE); anExp.More(); anExp.Next()) {
184       GeomShapePtr aCurrentShape(new GeomAPI_Shape());
185       aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current()));
186       myMap->bind(aCurrentShape, aCurrentShape);
187     }
188     for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_FACE); anExp.More(); anExp.Next()) {
189       GeomShapePtr aCurrentShape(new GeomAPI_Shape());
190       aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current()));
191       myMap->bind(aCurrentShape, aCurrentShape);
192     }
193   } else {
194     if(myMap.get()) {
195       myMap->clear();
196     }
197   }
198 }
199
200 //==================================================================================================
201 bool GeomAlgoAPI_MakeShape::isValidForHistory(const GeomShapePtr theShape)
202 {
203   if (!theShape.get()) return false;
204
205   const TopoDS_Shape& aShape_ = theShape->impl<TopoDS_Shape>();
206   if (aShape_.IsNull()) return false;
207
208   if (aShape_.ShapeType() == TopAbs_EDGE) {
209     TopoDS_Edge anEdge_ = TopoDS::Edge(aShape_);
210     if (BRep_Tool::Degenerated(anEdge_)) return false;
211   }
212
213   return true;
214 }
215
216 //==================================================================================================
217 void GeomAlgoAPI_MakeShape::fixOrientation(GeomShapePtr& theShape) {
218   if (myMap->isBound(theShape)) theShape = myMap->find(theShape);
219 }
220
221 //==================================================================================================
222 void GeomAlgoAPI_MakeShape::initialize()
223 {
224   switch (myBuilderType) {
225     case OCCT_BRepBuilderAPI_MakeShape: {
226       myDone = implPtr<BRepBuilderAPI_MakeShape>()->IsDone() == Standard_True;
227       myShape.reset(new GeomAPI_Shape());
228       myShape->setImpl(new TopoDS_Shape(implPtr<BRepBuilderAPI_MakeShape>()->Shape()));
229       break;
230     }
231     case OCCT_BOPAlgo_Builder: {
232       myDone = true;
233       myShape.reset(new GeomAPI_Shape());
234       myShape->setImpl(new TopoDS_Shape(implPtr<BOPAlgo_Builder>()->Shape()));
235       break;
236     }
237   }
238
239   if(myMap.get()) {
240     myMap->clear();
241   } else {
242     myMap.reset(new GeomAPI_DataMapOfShapeShape);
243   }
244
245   const TopoDS_Shape& aTopoDSShape = myShape->impl<TopoDS_Shape>();
246   for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_FACE); anExp.More(); anExp.Next()) {
247     GeomShapePtr aCurrentShape(new GeomAPI_Shape());
248     aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current()));
249     myMap->bind(aCurrentShape, aCurrentShape);
250   }
251   myHist = 0;
252 }
253
254
255 //==================================================================================================
256 void GeomAlgoAPI_MakeShape::prepareNamingFaces()
257 {
258   long long index = 1;
259   GeomAPI_ShapeExplorer anExp(shape(), GeomAPI_Shape::FACE);
260   for(GeomAPI_ShapeExplorer anExp(shape(), GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {
261     GeomShapePtr aFace = anExp.current();
262     myCreatedFaces["Face_" + std::to_string(index++)] = aFace;
263   }
264 }
265
266
267 //==================================================================================================
268 bool GeomAlgoAPI_MakeShape::checkValid(std::string theMessage)
269 {
270   // isValid() is called from this method
271   if (!isValid()) {
272     myError = theMessage + " :: resulting shape is not valid.";
273     return false;
274   }
275
276   // Check the number of volumes in myShape, make sure there's one and only one.
277   TopoDS_Shape aTopoDSShape = myShape->impl<TopoDS_Shape>();
278   int aNbVolumes = 0;
279   for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_SOLID); anExp.More(); anExp.Next()) {
280     aNbVolumes ++;
281   }
282
283   if (aNbVolumes != 1) {
284     myError = theMessage +
285       " :: connexity error, the resulting shape is made of several separate solids.";
286     return false;
287   }
288
289   return true ;
290 }
291
292 //==================================================================================================
293 bool GeomAlgoAPI_MakeShape::isNewShapesCollected(GeomShapePtr theWholeOld,
294                                                  const int theShapeType)
295 {
296   if (!myHist)
297     return false;
298   HistoryMap* aHist = (HistoryMap*)myHist;
299   if (!aHist->IsBound(theShapeType))
300     return false;
301   return aHist->Find(theShapeType).IsBound(theWholeOld->impl<TopoDS_Shape>());
302 }
303
304 void GeomAlgoAPI_MakeShape::collectNewShapes(
305   GeomShapePtr theWholeOld, const int theShapeType)
306 {
307   if (!myHist)
308     myHist = new HistoryMap;
309   HistoryMap* aHist = (HistoryMap*)myHist;
310   if (!aHist->IsBound(theShapeType))
311     aHist->Bind(
312       theShapeType, NCollection_DataMap<TopoDS_Shape, MapNewToOld, TopTools_ShapeMapHasher>());
313   aHist->ChangeFind(theShapeType). // add a new in anyway
314     Bind(theWholeOld->impl<TopoDS_Shape>(), MapNewToOld());
315   MapNewToOld& aCurrent =
316     aHist->ChangeFind(theShapeType).ChangeFind(theWholeOld->impl<TopoDS_Shape>());
317   ListOfShape aNewList;
318   TopTools_MapOfShape aViewed; //avoid same shapes
319   GeomAPI_ShapeExplorer anExp(theWholeOld, GeomAPI_Shape::ShapeType(theShapeType));
320   for(int anIndexInWholeOld = 0; anExp.more(); anExp.next(), anIndexInWholeOld++) {
321     if (!aViewed.Add(anExp.current()->impl<TopoDS_Shape>()))
322       continue;
323     aNewList.clear();
324     modified(anExp.current(), aNewList);
325     for(ListOfShape::iterator aNew = aNewList.begin(); aNew != aNewList.end(); aNew++) {
326       const TopoDS_Shape& aNewShape = (*aNew)->impl<TopoDS_Shape>();
327       if (!aCurrent.IsBound(aNewShape)) {
328         aCurrent.Bind(
329           aNewShape, NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>());
330       }
331       aCurrent.ChangeFind(aNewShape).Bind(anExp.current()->impl<TopoDS_Shape>(), anIndexInWholeOld);
332     }
333   }
334 }
335
336 static void addAllSubs(const TopoDS_Shape& theNewShape,
337   MapNewToOld& theCurrent, std::map<int, TopoDS_Shape>& theResMap)
338 {
339   if (theCurrent.IsBound(theNewShape)) {
340     NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>::Iterator
341       anOldIter(theCurrent.Find(theNewShape));
342     for(; anOldIter.More(); anOldIter.Next()) {
343       theResMap[anOldIter.Value()] = anOldIter.Key();
344     }
345   }
346
347   TopoDS_Iterator anIter(theNewShape);
348   for(; anIter.More(); anIter.Next()) {
349     //if (anIter.Value().ShapeType() != TopAbs_VERTEX)
350     addAllSubs(anIter.Value(), theCurrent, theResMap); // add recursively
351   }
352 }
353
354 //==================================================================================================
355 GeomShapePtr GeomAlgoAPI_MakeShape::oldShapesForNew(GeomShapePtr theWholeOld,
356                                                     GeomShapePtr theNewShape,
357                                                     const int theShapeType)
358 {
359   GeomShapePtr aResult(new GeomAPI_Shape);
360   TopoDS_Compound aResComp;
361   TopoDS_Builder aBuilder;
362   aBuilder.MakeCompound(aResComp);
363   aResult->setImpl<TopoDS_Shape>(new TopoDS_Shape(aResComp));
364
365   HistoryMap* aHist = (HistoryMap*)myHist;
366   if (!aHist->IsBound(theShapeType))
367     return aResult; // not found, empty compound
368   const TopoDS_Shape& aWholeOld = theWholeOld->impl<TopoDS_Shape>();
369   if (!aHist->Find(theShapeType).IsBound(aWholeOld))
370     return aResult; // not found, empty compound
371   std::map<int, TopoDS_Shape> aResMap; // map with all results, ordered by index in whole old
372   MapNewToOld& aCurrent = aHist->ChangeFind(theShapeType).ChangeFind(aWholeOld);
373   // we don't know what type of new shapes were produced by the old theShapeType, so, iterate all
374   addAllSubs(theNewShape->impl<TopoDS_Shape>(), aCurrent, aResMap);
375
376   std::map<int, TopoDS_Shape>::iterator anOldIter = aResMap.begin();
377   for(; anOldIter != aResMap.end(); anOldIter++) {
378     if (anOldIter->second.ShapeType() == (TopAbs_ShapeEnum)theShapeType)
379       aBuilder.Add(aResComp, anOldIter->second);
380   }
381   aResult->setImpl<TopoDS_Shape>(new TopoDS_Shape(aResComp));
382   return aResult;
383 }