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