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