Salome HOME
Fix for issue #1000
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_ShapeTools.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        GeomAlgoAPI_ShapeTools.h
4 // Created:     3 August 2015
5 // Author:      Dmitry Bobylev
6
7 #include <GeomAlgoAPI_ShapeTools.h>
8
9 #include <GeomAlgoAPI_CompoundBuilder.h>
10
11 #include <gp_Pln.hxx>
12
13 #include <BOPTools.hxx>
14 #include <BRepBuilderAPI_MakeFace.hxx>
15 #include <BRepGProp.hxx>
16 #include <BRepTools.hxx>
17 #include <BRep_Tool.hxx>
18 #include <Geom_Plane.hxx>
19 #include <GProp_GProps.hxx>
20 #include <NCollection_Vector.hxx>
21 #include <TCollection_AsciiString.hxx>
22 #include <TopoDS_Builder.hxx>
23 #include <TopoDS_Face.hxx>
24 #include <TopoDS_Shape.hxx>
25 #include <TopoDS_Shell.hxx>
26 #include <TopoDS.hxx>
27
28
29 //=================================================================================================
30 double GeomAlgoAPI_ShapeTools::volume(std::shared_ptr<GeomAPI_Shape> theShape)
31 {
32   GProp_GProps aGProps;
33   if(!theShape) {
34     return 0.0;
35   }
36   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
37   if(aShape.IsNull()) {
38     return 0.0;
39   }
40   BRepGProp::VolumeProperties(aShape, aGProps);
41   return aGProps.Mass();
42 }
43
44 //=================================================================================================
45 std::shared_ptr<GeomAPI_Pnt> GeomAlgoAPI_ShapeTools::centreOfMass(std::shared_ptr<GeomAPI_Shape> theShape)
46 {
47   GProp_GProps aGProps;
48   if(!theShape) {
49     return std::shared_ptr<GeomAPI_Pnt>();
50   }
51   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
52   if(aShape.IsNull()) {
53     return std::shared_ptr<GeomAPI_Pnt>();
54   }
55   BRepGProp::SurfaceProperties(aShape, aGProps);
56   gp_Pnt aCentre = aGProps.CentreOfMass();
57   return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z()));
58 }
59
60 //=================================================================================================
61 void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr<GeomAPI_Shape> theCompound,
62                                            const GeomAPI_Shape::ShapeType theType,
63                                            ListOfShape& theCombinedShapes,
64                                            ListOfShape& theFreeShapes)
65 {
66   if(!theCompound.get()) {
67     return;
68   }
69
70   if(theType != GeomAPI_Shape::SHELL && theType != GeomAPI_Shape::COMPSOLID) {
71     return;
72   }
73
74   TopAbs_ShapeEnum aTS = TopAbs_EDGE;
75   TopAbs_ShapeEnum aTA = TopAbs_FACE;
76   if(theType == GeomAPI_Shape::COMPSOLID) {
77     aTS = TopAbs_FACE;
78     aTA = TopAbs_SOLID;
79   }
80
81   // Map subshapes and shapes.
82   const TopoDS_Shape& aShapesComp = theCompound->impl<TopoDS_Shape>();
83   BOPCol_IndexedDataMapOfShapeListOfShape aMapEF;
84   BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapEF);
85   if(aMapEF.IsEmpty()) {
86     return;
87   }
88
89   // Get all shapes with common subshapes and free shapes.
90   NCollection_Map<TopoDS_Shape> aFreeShapes;
91   NCollection_Vector<NCollection_Map<TopoDS_Shape>> aShapesWithCommonSubshapes;
92   for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapEF); anIter.More(); anIter.Next()) {
93     const TopoDS_Shape& aShape = anIter.Key();
94     BOPCol_ListOfShape& aListOfShape = anIter.ChangeValue();
95     if(aListOfShape.IsEmpty()) {
96       continue;
97     }
98     else if(aListOfShape.Size() == 1) {
99       const TopoDS_Shape& aF = aListOfShape.First();
100       aFreeShapes.Add(aF);
101       aListOfShape.Clear();
102     } else {
103       NCollection_List<TopoDS_Shape> aTempList;
104       NCollection_Map<TopoDS_Shape> aTempMap;
105       const TopoDS_Shape& aF = aListOfShape.First();
106       const TopoDS_Shape& aL = aListOfShape.Last();
107       aTempList.Append(aF);
108       aTempList.Append(aL);
109       aTempMap.Add(aF);
110       aTempMap.Add(aL);
111       aFreeShapes.Remove(aF);
112       aFreeShapes.Remove(aL);
113       aListOfShape.Clear();
114       for(NCollection_List<TopoDS_Shape>::Iterator aTempIter(aTempList); aTempIter.More(); aTempIter.Next()) {
115         const TopoDS_Shape& aTempShape = aTempIter.Value();
116         for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapEF); anIter.More(); anIter.Next()) {
117           BOPCol_ListOfShape& aTempListOfShape = anIter.ChangeValue();
118           if(aTempListOfShape.IsEmpty()) {
119             continue;
120           } else if(aTempListOfShape.Size() == 1 && aTempListOfShape.First() == aTempShape) {
121             aTempListOfShape.Clear();
122           } else if(aTempListOfShape.Size() > 1) {
123             if(aTempListOfShape.First() == aTempShape) {
124               const TopoDS_Shape& aTL = aTempListOfShape.Last();
125               if(aTempMap.Add(aTL)) {
126                 aTempList.Append(aTL);
127                 aFreeShapes.Remove(aTL);
128               }
129               aTempListOfShape.Clear();
130             } else if(aTempListOfShape.Last() == aTempShape) {
131               const TopoDS_Shape& aTF = aTempListOfShape.First();
132               if(aTempMap.Add(aTF)) {
133                 aTempList.Append(aTF);
134                 aFreeShapes.Remove(aTF);
135               }
136               aTempListOfShape.Clear();
137             }
138           }
139         }
140       }
141       aShapesWithCommonSubshapes.Append(aTempMap);
142     }
143   }
144
145   // Combine shapes with common subshapes.
146   for(NCollection_Vector<NCollection_Map<TopoDS_Shape>>::Iterator anIter(aShapesWithCommonSubshapes); anIter.More(); anIter.Next()) {
147     TopoDS_Shell aShell;
148     TopoDS_CompSolid aCSolid;
149     TopoDS_Builder aBuilder;
150     theType == GeomAPI_Shape::COMPSOLID ? aBuilder.MakeCompSolid(aCSolid) : aBuilder.MakeShell(aShell);
151     const NCollection_Map<TopoDS_Shape>& aShapesMap = anIter.Value();
152     for(NCollection_Map<TopoDS_Shape>::Iterator aShIter(aShapesMap); aShIter.More(); aShIter.Next()) {
153       const TopoDS_Shape& aShape = aShIter.Value();
154       theType == GeomAPI_Shape::COMPSOLID ? aBuilder.Add(aCSolid, aShape) : aBuilder.Add(aShell, aShape);
155     }
156     std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
157     TopoDS_Shape* aSh = theType == GeomAPI_Shape::COMPSOLID ? new TopoDS_Shape(aCSolid) : new TopoDS_Shape(aShell);
158     aGeomShape->setImpl<TopoDS_Shape>(aSh);
159     theCombinedShapes.push_back(aGeomShape);
160   }
161
162   // Adding free shapes.
163   for(NCollection_Map<TopoDS_Shape>::Iterator aShIter(aFreeShapes); aShIter.More(); aShIter.Next()) {
164     const TopoDS_Shape& aShape = aShIter.Value();
165     std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
166     aGeomShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
167     theFreeShapes.push_back(aGeomShape);
168   }
169 }
170
171 //=================================================================================================
172 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const std::shared_ptr<GeomAPI_Shape>& theFace)
173 {
174   if (!theFace.get())
175     return std::shared_ptr<GeomAPI_Shape>();
176
177   TopoDS_Face aPlaneFace = TopoDS::Face(theFace->impl<TopoDS_Shape>());
178   if (aPlaneFace.IsNull())
179     return std::shared_ptr<GeomAPI_Shape>();
180
181   Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(aPlaneFace));
182   if (aPlane.IsNull())
183     return std::shared_ptr<GeomAPI_Shape>();
184
185   // make an infinity face on the plane
186   TopoDS_Shape anInfiniteFace = BRepBuilderAPI_MakeFace(aPlane->Pln()).Shape();
187
188   std::shared_ptr<GeomAPI_Shape> aResult(new GeomAPI_Shape);
189   aResult->setImpl(new TopoDS_Shape(anInfiniteFace));
190   return aResult;
191 }