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