1 // Copyright (C) 2014-2017 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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "GeomAlgoAPI_MakeShape.h"
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>
36 #include <TopoDS_Builder.hxx>
37 #include <TopoDS_Edge.hxx>
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>
44 NCollection_DataMap<int, NCollection_DataMap<TopoDS_Shape, MapNewToOld, TopTools_ShapeMapHasher> >
47 //==================================================================================================
48 GeomAlgoAPI_MakeShape::GeomAlgoAPI_MakeShape()
49 : myBuilderType(Unknown),
55 //==================================================================================================
56 GeomAlgoAPI_MakeShape::~GeomAlgoAPI_MakeShape()
59 delete (HistoryMap*)myHist;
63 //==================================================================================================
64 bool GeomAlgoAPI_MakeShape::isDone() const
69 //==================================================================================================
70 const GeomShapePtr GeomAlgoAPI_MakeShape::shape() const
75 //==================================================================================================
76 bool GeomAlgoAPI_MakeShape::isValid() const
78 BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
79 return (aChecker.IsValid() == Standard_True);
82 //==================================================================================================
83 bool GeomAlgoAPI_MakeShape::hasVolume() const
85 bool hasVolume = false;
87 const TopoDS_Shape& aRShape = myShape->impl<TopoDS_Shape>();
89 BRepGProp::VolumeProperties(aRShape, aGProp);
90 if(aGProp.Mass() > Precision::Confusion())
96 //==================================================================================================
97 std::shared_ptr<GeomAPI_DataMapOfShapeShape> GeomAlgoAPI_MakeShape::mapOfSubShapes() const
102 //==================================================================================================
103 void GeomAlgoAPI_MakeShape::generated(const GeomShapePtr theOldShape,
104 ListOfShape& theNewShapes)
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>());
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);
123 //==================================================================================================
124 void GeomAlgoAPI_MakeShape::modified(const GeomShapePtr theOldShape,
125 ListOfShape& theNewShapes)
127 TopTools_ListOfShape aList;
128 if(myBuilderType == OCCT_BRepBuilderAPI_MakeShape) {
129 BRepBuilderAPI_MakeShape* aMakeShape = implPtr<BRepBuilderAPI_MakeShape>();
131 aList = aMakeShape->Modified(theOldShape->impl<TopoDS_Shape>());
132 } catch(Standard_NoSuchObject) {
134 } else if(myBuilderType == OCCT_BOPAlgo_Builder) {
135 BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
136 aList = aBOPBuilder->Modified(theOldShape->impl<TopoDS_Shape>());
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);
147 //==================================================================================================
148 bool GeomAlgoAPI_MakeShape::isDeleted(const GeomShapePtr theOldShape)
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;
162 //==================================================================================================
163 void GeomAlgoAPI_MakeShape::setBuilderType(const BuilderType theBuilderType)
165 myBuilderType = theBuilderType;
168 //==================================================================================================
169 void GeomAlgoAPI_MakeShape::setDone(const bool theFlag)
174 //==================================================================================================
175 void GeomAlgoAPI_MakeShape::setShape(const GeomShapePtr theShape)
177 if(myShape.get() && myShape->isEqual(theShape)) {
183 // Filling data map to keep correct orientation of sub-shapes.
188 myMap.reset(new GeomAPI_DataMapOfShapeShape);
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);
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);
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);
214 //==================================================================================================
215 bool GeomAlgoAPI_MakeShape::isValidForHistory(const GeomShapePtr theShape)
217 if (!theShape.get()) return false;
219 const TopoDS_Shape& aShape_ = theShape->impl<TopoDS_Shape>();
220 if (aShape_.IsNull()) return false;
222 if (aShape_.ShapeType() == TopAbs_EDGE) {
223 TopoDS_Edge anEdge_ = TopoDS::Edge(aShape_);
224 if (BRep_Tool::Degenerated(anEdge_)) return false;
230 //==================================================================================================
231 void GeomAlgoAPI_MakeShape::fixOrientation(GeomShapePtr& theShape) {
232 if (myMap->isBound(theShape)) theShape = myMap->find(theShape);
235 //==================================================================================================
236 void GeomAlgoAPI_MakeShape::initialize()
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()));
245 case OCCT_BOPAlgo_Builder: {
247 myShape.reset(new GeomAPI_Shape());
248 myShape->setImpl(new TopoDS_Shape(implPtr<BOPAlgo_Builder>()->Shape()));
256 myMap.reset(new GeomAPI_DataMapOfShapeShape);
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);
269 //==================================================================================================
270 void GeomAlgoAPI_MakeShape::prepareNamingFaces()
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;
281 //==================================================================================================
282 bool GeomAlgoAPI_MakeShape::checkValid(std::string theMessage)
284 // isValid() is called from this method
286 myError = theMessage + " :: resulting shape is not valid.";
290 // Check the number of volumes in myShape, make sure there's one and only one.
291 TopoDS_Shape aTopoDSShape = myShape->impl<TopoDS_Shape>();
293 for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_SOLID); anExp.More(); anExp.Next()) {
297 if (aNbVolumes != 1) {
298 myError = theMessage +
299 " :: connexity error, the resulting shape is made of several separate solids.";
306 //==================================================================================================
307 bool GeomAlgoAPI_MakeShape::isNewShapesCollected(GeomShapePtr theWholeOld,
308 const int theShapeType)
312 HistoryMap* aHist = (HistoryMap*)myHist;
313 if (!aHist->IsBound(theShapeType))
315 return aHist->Find(theShapeType).IsBound(theWholeOld->impl<TopoDS_Shape>());
318 void GeomAlgoAPI_MakeShape::collectNewShapes(
319 GeomShapePtr theWholeOld, const int theShapeType)
322 myHist = new HistoryMap;
323 HistoryMap* aHist = (HistoryMap*)myHist;
324 if (!aHist->IsBound(theShapeType))
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>()))
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)) {
343 aNewShape, NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>());
345 aCurrent.ChangeFind(aNewShape).Bind(anExp.current()->impl<TopoDS_Shape>(), anIndexInWholeOld);
350 static void addAllSubs(const TopoDS_Shape& theNewShape,
351 MapNewToOld& theCurrent, std::map<int, TopoDS_Shape>& theResMap)
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();
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
368 //==================================================================================================
369 GeomShapePtr GeomAlgoAPI_MakeShape::oldShapesForNew(GeomShapePtr theWholeOld,
370 GeomShapePtr theNewShape,
371 const int theShapeType)
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));
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);
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);
395 aResult->setImpl<TopoDS_Shape>(new TopoDS_Shape(aResComp));