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 <BRepBuilderAPI_MakeShape.hxx>
25 #include <BRepCheck_Analyzer.hxx>
26 #include <BRepGProp.hxx>
27 #include <GProp_GProps.hxx>
28 #include <Precision.hxx>
29 #include <TopExp_Explorer.hxx>
30 #include <TopTools_ListOfShape.hxx>
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32 #include <GeomAPI_ShapeExplorer.h>
33 #include <GeomAPI_ShapeIterator.h>
34 #include <TopoDS_Builder.hxx>
36 // new shape -> old shapes -> index in the old shape
37 typedef NCollection_DataMap<TopoDS_Shape,
38 NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>, TopTools_ShapeMapHasher>
41 NCollection_DataMap<int, NCollection_DataMap<TopoDS_Shape, MapNewToOld, TopTools_ShapeMapHasher> >
44 //=================================================================================================
45 GeomAlgoAPI_MakeShape::GeomAlgoAPI_MakeShape()
46 : myBuilderType(Unknown),
52 GeomAlgoAPI_MakeShape::~GeomAlgoAPI_MakeShape() {
54 delete (HistoryMap*)myHist;
58 //=================================================================================================
59 bool GeomAlgoAPI_MakeShape::isDone() const
64 //=================================================================================================
65 const std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_MakeShape::shape() const
70 //=================================================================================================
71 bool GeomAlgoAPI_MakeShape::isValid() const
73 BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
74 return (aChecker.IsValid() == Standard_True);
77 //=================================================================================================
78 bool GeomAlgoAPI_MakeShape::hasVolume() const
80 bool hasVolume = false;
82 const TopoDS_Shape& aRShape = myShape->impl<TopoDS_Shape>();
84 BRepGProp::VolumeProperties(aRShape, aGProp);
85 if(aGProp.Mass() > Precision::Confusion())
91 //=================================================================================================
92 std::shared_ptr<GeomAPI_DataMapOfShapeShape> GeomAlgoAPI_MakeShape::mapOfSubShapes() const
97 //=================================================================================================
98 void GeomAlgoAPI_MakeShape::generated(const std::shared_ptr<GeomAPI_Shape> theShape,
99 ListOfShape& theHistory)
101 TopTools_ListOfShape aList;
102 if(myBuilderType == OCCT_BRepBuilderAPI_MakeShape) {
103 BRepBuilderAPI_MakeShape* aMakeShape = implPtr<BRepBuilderAPI_MakeShape>();
104 aList = aMakeShape->Generated(theShape->impl<TopoDS_Shape>());
105 } else if(myBuilderType == OCCT_BOPAlgo_Builder) {
106 BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
107 aList = aBOPBuilder->Generated(theShape->impl<TopoDS_Shape>());
109 for(TopTools_ListIteratorOfListOfShape anIt(aList); anIt.More(); anIt.Next()) {
110 if(anIt.Value().IsNull()) {
113 std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
114 aShape->setImpl(new TopoDS_Shape(anIt.Value()));
115 theHistory.push_back(aShape);
119 //=================================================================================================
120 void GeomAlgoAPI_MakeShape::modified(const std::shared_ptr<GeomAPI_Shape> theShape,
121 ListOfShape& theHistory)
123 TopTools_ListOfShape aList;
124 if(myBuilderType == OCCT_BRepBuilderAPI_MakeShape) {
125 BRepBuilderAPI_MakeShape* aMakeShape = implPtr<BRepBuilderAPI_MakeShape>();
127 aList = aMakeShape->Modified(theShape->impl<TopoDS_Shape>());
128 } catch(Standard_NoSuchObject) {
130 } else if(myBuilderType == OCCT_BOPAlgo_Builder) {
131 BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
132 aList = aBOPBuilder->Modified(theShape->impl<TopoDS_Shape>());
134 for(TopTools_ListIteratorOfListOfShape anIt(aList); anIt.More(); anIt.Next()) {
135 if(anIt.Value().IsNull()) {
138 std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
139 aShape->setImpl(new TopoDS_Shape(anIt.Value()));
140 theHistory.push_back(aShape);
144 //=================================================================================================
145 bool GeomAlgoAPI_MakeShape::isDeleted(const std::shared_ptr<GeomAPI_Shape> theShape)
147 bool isDeleted = false;
148 if(myBuilderType == OCCT_BRepBuilderAPI_MakeShape) {
149 BRepBuilderAPI_MakeShape* aMakeShape = implPtr<BRepBuilderAPI_MakeShape>();
150 isDeleted = aMakeShape->IsDeleted(theShape->impl<TopoDS_Shape>()) == Standard_True;
151 } else if(myBuilderType == OCCT_BOPAlgo_Builder) {
152 BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
153 isDeleted = aBOPBuilder->IsDeleted(theShape->impl<TopoDS_Shape>()) == Standard_True;
159 //=================================================================================================
160 void GeomAlgoAPI_MakeShape::setBuilderType(const BuilderType theBuilderType)
162 myBuilderType = theBuilderType;
165 //=================================================================================================
166 void GeomAlgoAPI_MakeShape::setDone(const bool theFlag)
171 //=================================================================================================
172 void GeomAlgoAPI_MakeShape::setShape(const std::shared_ptr<GeomAPI_Shape> theShape)
174 if(myShape.get() && myShape->isEqual(theShape)) {
180 // Filling data map to keep correct orientation of sub-shapes.
185 myMap.reset(new GeomAPI_DataMapOfShapeShape);
188 const TopoDS_Shape& aTopoDSShape = myShape->impl<TopoDS_Shape>();
189 for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_VERTEX); anExp.More(); anExp.Next()) {
190 std::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
191 aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current()));
192 myMap->bind(aCurrentShape, aCurrentShape);
194 for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_EDGE); anExp.More(); anExp.Next()) {
195 std::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
196 aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current()));
197 myMap->bind(aCurrentShape, aCurrentShape);
199 for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_FACE); anExp.More(); anExp.Next()) {
200 std::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
201 aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current()));
202 myMap->bind(aCurrentShape, aCurrentShape);
211 //=================================================================================================
212 void GeomAlgoAPI_MakeShape::initialize() {
213 switch (myBuilderType) {
214 case OCCT_BRepBuilderAPI_MakeShape: {
215 myDone = implPtr<BRepBuilderAPI_MakeShape>()->IsDone() == Standard_True;
216 myShape.reset(new GeomAPI_Shape());
217 myShape->setImpl(new TopoDS_Shape(implPtr<BRepBuilderAPI_MakeShape>()->Shape()));
220 case OCCT_BOPAlgo_Builder: {
222 myShape.reset(new GeomAPI_Shape());
223 myShape->setImpl(new TopoDS_Shape(implPtr<BOPAlgo_Builder>()->Shape()));
231 myMap.reset(new GeomAPI_DataMapOfShapeShape);
234 const TopoDS_Shape& aTopoDSShape = myShape->impl<TopoDS_Shape>();
235 for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_FACE); anExp.More(); anExp.Next()) {
236 std::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
237 aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current()));
238 myMap->bind(aCurrentShape, aCurrentShape);
244 //=================================================================================================
245 void GeomAlgoAPI_MakeShape::prepareNamingFaces()
248 GeomAPI_ShapeExplorer anExp(shape(), GeomAPI_Shape::FACE);
249 for(GeomAPI_ShapeExplorer anExp(shape(), GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {
250 std::shared_ptr<GeomAPI_Shape> aFace = anExp.current();
251 myCreatedFaces["Face_" + std::to_string(index++)] = aFace;
256 //=================================================================================================
257 bool GeomAlgoAPI_MakeShape::checkValid(std::string theMessage){
259 // isValid() is called from this method
261 myError = theMessage + " :: resulting shape is not valid.";
265 // Check the number of volumes in myShape, make sure there's one and only one.
266 TopoDS_Shape aTopoDSShape = myShape->impl<TopoDS_Shape>();
268 for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_SOLID); anExp.More(); anExp.Next()) {
272 if (aNbVolumes != 1) {
273 myError = theMessage +
274 " :: connexity error, the resulting shape is made of several separate solids.";
281 bool GeomAlgoAPI_MakeShape::newShapesCollected(
282 std::shared_ptr<GeomAPI_Shape> theWholeOld, const int theShapeType)
286 HistoryMap* aHist = (HistoryMap*)myHist;
287 if (!aHist->IsBound(theShapeType))
289 return aHist->Find(theShapeType).IsBound(theWholeOld->impl<TopoDS_Shape>());
292 void GeomAlgoAPI_MakeShape::collectNewShapes(
293 std::shared_ptr<GeomAPI_Shape> theWholeOld, const int theShapeType)
296 myHist = new HistoryMap;
297 HistoryMap* aHist = (HistoryMap*)myHist;
298 if (!aHist->IsBound(theShapeType))
300 theShapeType, NCollection_DataMap<TopoDS_Shape, MapNewToOld, TopTools_ShapeMapHasher>());
301 aHist->ChangeFind(theShapeType). // add a new in anyway
302 Bind(theWholeOld->impl<TopoDS_Shape>(), MapNewToOld());
303 MapNewToOld& aCurrent =
304 aHist->ChangeFind(theShapeType).ChangeFind(theWholeOld->impl<TopoDS_Shape>());
305 ListOfShape aNewList;
306 TopTools_MapOfShape aViewed; //avoid same shapes
307 GeomAPI_ShapeExplorer anExp(theWholeOld, GeomAPI_Shape::ShapeType(theShapeType));
308 for(int anIndexInWholeOld = 0; anExp.more(); anExp.next(), anIndexInWholeOld++) {
309 if (!aViewed.Add(anExp.current()->impl<TopoDS_Shape>()))
312 modified(anExp.current(), aNewList);
313 for(ListOfShape::iterator aNew = aNewList.begin(); aNew != aNewList.end(); aNew++) {
314 const TopoDS_Shape& aNewShape = (*aNew)->impl<TopoDS_Shape>();
315 if (!aCurrent.IsBound(aNewShape)) {
317 aNewShape, NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>());
319 aCurrent.ChangeFind(aNewShape).Bind(anExp.current()->impl<TopoDS_Shape>(), anIndexInWholeOld);
324 static void addAllSubs(const TopoDS_Shape& theNewShape,
325 MapNewToOld& theCurrent, std::map<int, TopoDS_Shape>& theResMap)
327 if (theCurrent.IsBound(theNewShape)) {
328 NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>::Iterator
329 anOldIter(theCurrent.Find(theNewShape));
330 for(; anOldIter.More(); anOldIter.Next()) {
331 theResMap[anOldIter.Value()] = anOldIter.Key();
335 TopoDS_Iterator anIter(theNewShape);
336 for(; anIter.More(); anIter.Next()) {
337 //if (anIter.Value().ShapeType() != TopAbs_VERTEX)
338 addAllSubs(anIter.Value(), theCurrent, theResMap); // add recursively
342 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_MakeShape::oldShapesForNew(
343 std::shared_ptr<GeomAPI_Shape> theWholeOld,
344 std::shared_ptr<GeomAPI_Shape> theNewShape, const int theShapeType)
346 GeomShapePtr aResult(new GeomAPI_Shape);
347 TopoDS_Compound aResComp;
348 TopoDS_Builder aBuilder;
349 aBuilder.MakeCompound(aResComp);
350 aResult->setImpl<TopoDS_Shape>(new TopoDS_Shape(aResComp));
352 HistoryMap* aHist = (HistoryMap*)myHist;
353 if (!aHist->IsBound(theShapeType))
354 return aResult; // not found, empty compound
355 const TopoDS_Shape& aWholeOld = theWholeOld->impl<TopoDS_Shape>();
356 if (!aHist->Find(theShapeType).IsBound(aWholeOld))
357 return aResult; // not found, empty compound
358 std::map<int, TopoDS_Shape> aResMap; // map with all results, ordered by index in whole old
359 MapNewToOld& aCurrent = aHist->ChangeFind(theShapeType).ChangeFind(aWholeOld);
360 // we don't know what type of new shapes were produced by the old theShapeType, so, iterate all
361 addAllSubs(theNewShape->impl<TopoDS_Shape>(), aCurrent, aResMap);
363 std::map<int, TopoDS_Shape>::iterator anOldIter = aResMap.begin();
364 for(; anOldIter != aResMap.end(); anOldIter++) {
365 if (anOldIter->second.ShapeType() == (TopAbs_ShapeEnum)theShapeType)
366 aBuilder.Add(aResComp, anOldIter->second);
368 aResult->setImpl<TopoDS_Shape>(new TopoDS_Shape(aResComp));