Salome HOME
cb44690b36c8caba8b4caaa3576ae7fc6e6bf44a
[modules/shaper_study.git] / src / StudyData / StudyData_Operation.cpp
1 // Copyright (C) 2019-2020  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include "StudyData_Operation.h"
21
22 #include <Precision.hxx>
23 #include <TopoDS.hxx>
24 #include <TopoDS_Shape.hxx>
25 #include <TopoDS_Iterator.hxx>
26 #include <BRep_Builder.hxx>
27 #include <BRepTools.hxx>
28 #include <Bnd_Box.hxx>
29 #include <BRepBndLib.hxx>
30 #include <TopTools_MapOfShape.hxx>
31 #include <TColStd_HArray1OfInteger.hxx>
32 #include <TopExp.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <TopTools_ListOfShape.hxx>
35 #include <GProp_GProps.hxx>
36 #include <BRepGProp.hxx>
37
38 #include <vector>
39 #include <algorithm>
40
41 static const int TopAbs_FLAT = TopAbs_SHAPE+1;
42
43 static void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M)
44 {
45   if (S.ShapeType() != TopAbs_COMPOUND) {
46     L.Append(S);
47   }
48   else {
49     TopoDS_Iterator It(S, Standard_True, Standard_True);
50     for (; It.More(); It.Next()) {
51       TopoDS_Shape SS = It.Value();
52       if (M.Add(SS))
53         AddFlatSubShapes(SS, L, M);
54     }
55   }
56 }
57
58 static std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S)
59 {
60   // Computing of CentreOfMass
61   gp_Pnt GPoint;
62   double Len;
63
64   if (S.ShapeType() == TopAbs_VERTEX) {
65     GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
66     Len = (double)S.Orientation();
67   }
68   else {
69     GProp_GProps GPr;
70     if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
71       BRepGProp::LinearProperties(S, GPr);
72     }
73     else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
74       BRepGProp::SurfaceProperties(S, GPr);
75     }
76     else {
77       BRepGProp::VolumeProperties(S, GPr);
78     }
79     GPoint = GPr.CentreOfMass();
80     Len = GPr.Mass();
81   }
82
83   double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
84   return std::make_pair(dMidXYZ, Len);
85 }
86
87 /// Sort shapes in the list by their coordinates.
88 struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
89 {
90   CompareShapes () {}
91   bool operator() (const TopoDS_Shape& lhs, const TopoDS_Shape& rhs);
92   typedef NCollection_DataMap<TopoDS_Shape, std::pair<double, double> > GEOMUtils_DataMapOfShapeDouble;
93   GEOMUtils_DataMapOfShapeDouble myMap;
94 };
95
96 bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
97   const TopoDS_Shape& theShape2)
98 {
99   if (!myMap.IsBound(theShape1)) {
100     myMap.Bind(theShape1, ShapeToDouble(theShape1));
101   }
102
103   if (!myMap.IsBound(theShape2)) {
104     myMap.Bind(theShape2, ShapeToDouble(theShape2));
105   }
106
107   std::pair<double, double> val1 = myMap.Find(theShape1);
108   std::pair<double, double> val2 = myMap.Find(theShape2);
109
110   double tol = Precision::Confusion();
111   bool exchange = Standard_False;
112
113   double dMidXYZ = val1.first - val2.first;
114   if (dMidXYZ >= tol) {
115     exchange = Standard_True;
116   }
117   else if (Abs(dMidXYZ) < tol) {
118     double dLength = val1.second - val2.second;
119     if (dLength >= tol) {
120       exchange = Standard_True;
121     }
122     else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
123       Bnd_Box box1,box2;
124       BRepBndLib::Add(theShape1, box1);
125       if (!box1.IsVoid()) {
126         BRepBndLib::Add(theShape2, box2);
127         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
128         if (dSquareExtent >= tol) {
129           exchange = Standard_True;
130         }
131         else if (Abs(dSquareExtent) < tol) {
132           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
133           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
134           val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
135           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
136           val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
137           if ((val1 - val2) >= tol) {
138             exchange = Standard_True;
139           }
140         }
141       }
142     }
143   }
144
145   //return val1 < val2;
146   return !exchange;
147 }
148
149
150 static void SortShapes (TopTools_ListOfShape& SL)
151 {
152   std::vector<TopoDS_Shape> aShapesVec;
153   aShapesVec.reserve(SL.Extent());
154
155   TopTools_ListIteratorOfListOfShape it (SL);
156   for (; it.More(); it.Next()) {
157     aShapesVec.push_back(it.Value());
158   }
159   SL.Clear();
160
161   CompareShapes shComp;
162   std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
163   //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp);
164
165   std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
166   for (; anIter != aShapesVec.end(); ++anIter) {
167     SL.Append(*anIter);
168   }
169 }
170
171
172 std::list<long> StudyData_Operation::GetAllSubShapesIDs(
173   const long long theShape, const int theShapeType, const bool isSorted)
174 {
175   TopoDS_Shape* aShape = (TopoDS_Shape*)theShape;
176
177   std::list<long> aResult;
178   TopTools_MapOfShape mapShape;
179   TopTools_ListOfShape listShape;
180
181   if (aShape->ShapeType() == TopAbs_COMPOUND &&
182     (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND)) {
183     TopoDS_Iterator It (*aShape, Standard_True, Standard_True);
184     for (; It.More(); It.Next()) {
185       TopoDS_Shape SS = It.Value();
186       if (mapShape.Add(SS)) {
187         if (theShapeType == TopAbs_FLAT) {
188           AddFlatSubShapes(SS, listShape, mapShape);
189         } else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
190           listShape.Append(SS);
191         }
192       }
193     }
194   } else {
195     TopExp_Explorer exp (*aShape, TopAbs_ShapeEnum(theShapeType));
196     for (; exp.More(); exp.Next())
197       if (mapShape.Add(exp.Current()))
198         listShape.Append(exp.Current());
199   }
200
201   if (listShape.IsEmpty()) {
202     return aResult;
203   }
204
205   if (isSorted) {
206     SortShapes(listShape);
207   }
208
209   TopTools_IndexedMapOfShape anIndices;
210   TopExp::MapShapes(*aShape, anIndices);
211
212   TopTools_ListIteratorOfListOfShape itSub (listShape);
213   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
214     TopoDS_Shape aValue = itSub.Value();
215     aResult.push_back(anIndices.FindIndex(aValue));
216   }
217
218   return aResult;
219 }
220
221 std::list<long long> StudyData_Operation::GetSharedShapes(
222   const long long theShape1, const long long theShape2, const int theShapeType)
223 {
224   std::list<long long> aResult;
225
226   TopoDS_Shape* aShape1 = (TopoDS_Shape*)theShape1;
227   TopoDS_Shape* aShape2 = (TopoDS_Shape*)theShape2;
228   if (aShape1->IsNull() || aShape2->IsNull())
229     return aResult;
230   TopTools_IndexedMapOfShape anIndices;
231   TopExp::MapShapes(*aShape1, anIndices);
232   Handle(TColStd_HArray1OfInteger) anArray;
233
234   TopTools_IndexedMapOfShape mapShape1;
235   TopExp::MapShapes(*aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
236   TopTools_MapOfShape mapShape2;
237   TopExp_Explorer exp (*aShape2, TopAbs_ShapeEnum(theShapeType));
238   for (; exp.More(); exp.Next()) {
239     TopoDS_Shape aSS = exp.Current();
240     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
241       // for the current moment there are no sub-shape managed in the SHAPER-STUDY, so,
242       // store just shape in heap and return pointer to it (otherwise it will be disappeared)
243       long long aNewShapePointer = (long long)(new TopoDS_Shape(aSS));
244       aResult.push_back(aNewShapePointer);
245     }
246   }
247
248   return aResult;
249 }
250
251 int StudyData_Operation::GetSubShapeIndex(const long long theMainShape, const long long theSubShape)
252 {
253   TopoDS_Shape* aMainShape = (TopoDS_Shape*)theMainShape;
254   TopoDS_Shape* aSubShape = (TopoDS_Shape*)theSubShape;
255   if ( !aMainShape || !aSubShape || aMainShape->IsNull() || aSubShape->IsNull())
256     return 0;
257
258   TopTools_IndexedMapOfShape anIndices;
259   TopExp::MapShapes(*aMainShape, anIndices);
260   return anIndices.FindIndex(*aSubShape);
261 }
262
263 int StudyData_Operation::GetTopologyIndex(const long long theMainShape, const long long theSubShape)
264 {
265   TopoDS_Shape* aMainShape = (TopoDS_Shape*)theMainShape;
266   TopoDS_Shape* aSubShape = (TopoDS_Shape*)theSubShape;
267   if ( !aMainShape || !aSubShape || aMainShape->IsNull() || aSubShape->IsNull())
268     return 0;
269
270   TopTools_IndexedMapOfShape anIndices;
271   TopExp::MapShapes(*aMainShape, aSubShape->ShapeType(), anIndices);
272   return anIndices.FindIndex(*aSubShape);
273 }
274
275 long long StudyData_Operation::GetSubShape(const long long theMainShape, long theID)
276 {
277   TopoDS_Shape* aMainShape = (TopoDS_Shape*)theMainShape;
278   if (aMainShape->IsNull())
279     return 0;
280   TopTools_IndexedMapOfShape anIndices;
281   TopExp::MapShapes(*aMainShape, anIndices);
282   if (anIndices.Size() < theID)
283     return 0;
284   const TopoDS_Shape& aFound = anIndices.FindKey(theID);
285   // for the current moment there are no sub-shape managed in the SHAPER-STUDY, so,
286   // store just shape in heap and return pointer to it (otherwise it will be disappeared)
287   return (long long)(new TopoDS_Shape(aFound));
288 }
289
290 std::list<long long> StudyData_Operation::ExtractSubShapes(const long long theMainShape,
291                                                            const int       theShapeType,
292                                                            const bool      theIsSorted)
293 {
294   std::list<long long> resultList;
295
296   TopoDS_Shape* aShape = (TopoDS_Shape*)theMainShape;
297   if ( !aShape || aShape->IsNull())
298     return resultList;
299
300   std::list<long> aResult;
301   TopTools_MapOfShape mapShape;
302   TopTools_ListOfShape listShape;
303
304   if (aShape->ShapeType() == TopAbs_COMPOUND &&
305     (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND)) {
306     TopoDS_Iterator It (*aShape, Standard_True, Standard_True);
307     for (; It.More(); It.Next()) {
308       TopoDS_Shape SS = It.Value();
309       if (mapShape.Add(SS)) {
310         if (theShapeType == TopAbs_FLAT) {
311           AddFlatSubShapes(SS, listShape, mapShape);
312         } else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
313           listShape.Append(SS);
314         }
315       }
316     }
317   } else {
318     TopExp_Explorer exp (*aShape, TopAbs_ShapeEnum(theShapeType));
319     for (; exp.More(); exp.Next())
320       if (mapShape.Add(exp.Current()))
321         listShape.Append(exp.Current());
322   }
323
324   if (listShape.IsEmpty()) {
325     return resultList;
326   }
327
328   if (theIsSorted) {
329     SortShapes(listShape);
330   }
331
332   TopTools_ListIteratorOfListOfShape itSub (listShape);
333   for ( ; itSub.More(); itSub.Next() ) {
334     TopoDS_Shape aValue = itSub.Value();
335     resultList.push_back( (long long)(new TopoDS_Shape(aValue)) );
336   }
337
338   return resultList;
339 }
340
341 std::list<double> StudyData_Operation::PointCoordinates(const long long theVertex)
342 {
343   std::list<double> xyz;
344
345   TopoDS_Shape* aShape = (TopoDS_Shape*)theVertex;
346   if ( !aShape || aShape->IsNull() || aShape->ShapeType() != TopAbs_VERTEX )
347     return xyz;
348
349   gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( *aShape ));
350   xyz.push_back( p.X() );
351   xyz.push_back( p.Y() );
352   xyz.push_back( p.Z() );
353
354   return xyz;
355 }
356
357 double StudyData_Operation::MinDistance(const long long theVertex1, const long long theVertex2)
358 {
359   double result = -1;
360   TopoDS_Shape* aShape1 = (TopoDS_Shape*)theVertex1;
361   TopoDS_Shape* aShape2 = (TopoDS_Shape*)theVertex2;
362
363   if ( !aShape1 || aShape1->IsNull() || aShape1->ShapeType() != TopAbs_VERTEX ||
364        !aShape2 || aShape2->IsNull() || aShape2->ShapeType() != TopAbs_VERTEX )
365     return result;
366
367   gp_Pnt p1 = BRep_Tool::Pnt( TopoDS::Vertex( *aShape1 ));
368   gp_Pnt p2 = BRep_Tool::Pnt( TopoDS::Vertex( *aShape2 ));
369
370   result = p1.Distance( p2 );
371   return result;
372 }
373
374 int StudyData_Operation::NumberOfEdges(const long long theShape)
375 {
376   int nb = -1;
377
378   TopoDS_Shape* aShape = (TopoDS_Shape*)theShape;
379   if ( !aShape || aShape->IsNull() )
380     return nb;
381
382   TopTools_IndexedMapOfShape anIndices;
383   TopExp::MapShapes(*aShape, TopAbs_EDGE, anIndices);
384   nb = anIndices.Extent();
385
386   return nb;
387 }
388   
389 int StudyData_Operation::NumberOfFaces(const long long theShape)
390 {
391   int nb = -1;
392
393   TopoDS_Shape* aShape = (TopoDS_Shape*)theShape;
394   if ( !aShape || aShape->IsNull() )
395     return nb;
396
397   TopTools_IndexedMapOfShape anIndices;
398   TopExp::MapShapes(*aShape, TopAbs_FACE, anIndices);
399   nb = anIndices.Extent();
400
401   return nb;
402 }
403   
404 double StudyData_Operation::GetTolerance( const long long theVertex )
405 {
406   double tol = -1;
407
408   TopoDS_Shape* aShape = (TopoDS_Shape*)theVertex;
409   if ( !aShape || aShape->IsNull() || aShape->ShapeType() != TopAbs_VERTEX )
410     return tol;
411
412   tol = BRep_Tool::Tolerance( TopoDS::Vertex( *aShape ));
413
414   return tol;
415 }
416
417 long long StudyData_Operation::GetVertexByIndex(const long long theEdge,
418                                                 int             theIndex,
419                                                 bool            theUseOri )
420 {
421   TopoDS_Shape* aShape = (TopoDS_Shape*)theEdge;
422   if ( !aShape || aShape->IsNull() || aShape->ShapeType() != TopAbs_EDGE )
423     return 0;
424
425   if ( !theUseOri )
426     aShape->Orientation( TopAbs_FORWARD );
427
428   TopoDS_Vertex aVertex;
429   if ( theIndex == 0 )
430     aVertex = TopExp::FirstVertex( TopoDS::Edge( *aShape ));
431   else
432     aVertex = TopExp::LastVertex( TopoDS::Edge( *aShape ));
433
434   return (long long)(new TopoDS_Shape( aVertex ));
435 }