]> SALOME platform Git repositories - modules/shaper.git/blob - src/Selector/Selector_NExplode.cpp
Salome HOME
Issue #19058: Error in sketch projection when changing parameter
[modules/shaper.git] / src / Selector / Selector_NExplode.cpp
1 // Copyright (C) 2017-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 "Selector_NExplode.h"
21
22 #include <GeomAPI_Pnt.h>
23
24 #include <TopoDS_Shape.hxx>
25 #include <BRep_Tool.hxx>
26 #include <TopoDS.hxx>
27 #include <GProp_GProps.hxx>
28 #include <BRepGProp.hxx>
29 #include <NCollection_DataMap.hxx>
30 #include <Precision.hxx>
31 #include <Bnd_Box.hxx>
32 #include <BRepBndLib.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <TopTools_MapOfShape.hxx>
35
36 #include <vector>
37 #include <algorithm>
38
39 static std::pair<gp_Pnt, double> ShapeToDouble (const TopoDS_Shape& S)
40 {
41   // Computing of CentreOfMass
42   gp_Pnt GPoint;
43   double Len;
44
45   if (S.ShapeType() == TopAbs_VERTEX) {
46     GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
47     Len = (double)S.Orientation();
48   }
49   else {
50     GProp_GProps GPr;
51     if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
52       BRepGProp::LinearProperties(S, GPr);
53     }
54     else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
55       BRepGProp::SurfaceProperties(S, GPr);
56     }
57     else {
58       BRepGProp::VolumeProperties(S, GPr);
59     }
60     GPoint = GPr.CentreOfMass();
61     Len = GPr.Mass();
62   }
63
64   return std::make_pair(GPoint, Len);
65 }
66
67 /*!
68 * \brief Sort shapes in the list by their coordinates.
69 */
70 struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
71 {
72   typedef NCollection_DataMap<TopoDS_Shape, std::pair<gp_Pnt, double> > DataMapOfShapeDouble;
73
74   CompareShapes(DataMapOfShapeDouble* theCashMap) : myMap(theCashMap) {}
75
76   bool operator() (const TopoDS_Shape& lhs, const TopoDS_Shape& rhs);
77
78   DataMapOfShapeDouble* myMap;
79 };
80
81 bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
82   const TopoDS_Shape& theShape2)
83 {
84   if (!myMap->IsBound(theShape1)) {
85     myMap->Bind(theShape1, ShapeToDouble(theShape1));
86   }
87
88   if (!myMap->IsBound(theShape2)) {
89     myMap->Bind(theShape2, ShapeToDouble(theShape2));
90   }
91
92   const std::pair<gp_Pnt, double>& val1 = myMap->Find(theShape1);
93   const std::pair<gp_Pnt, double>& val2 = myMap->Find(theShape2);
94
95   double tol = 10.0 * Precision::Confusion();
96   bool exchange = Standard_False;
97
98   // compare coordinates of center points
99   GeomPointPtr aPnt1(new GeomAPI_Pnt(val1.first.X(), val1.first.Y(), val1.first.Z()));
100   GeomPointPtr aPnt2(new GeomAPI_Pnt(val2.first.X(), val2.first.Y(), val2.first.Z()));
101   if (aPnt2->isLess(aPnt1, tol)) {
102     exchange = Standard_True;
103   }
104   else if (!aPnt1->isLess(aPnt2, tol)) {
105     double dLength = val1.second - val2.second;
106     if (dLength >= tol) {
107       exchange = Standard_True;
108     }
109     else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
110       // equal values possible on shapes such as two halves of a sphere and
111       // a membrane inside the sphere
112 // LCOV_EXCL_START
113       // this part of code is taken from GEOM module, but can not reproduce in SHAPER
114       Bnd_Box box1,box2;
115       BRepBndLib::Add(theShape1, box1);
116       if (!box1.IsVoid()) {
117         BRepBndLib::Add(theShape2, box2);
118         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
119         if (dSquareExtent >= tol) {
120           exchange = Standard_True;
121         }
122         else if (Abs(dSquareExtent) < tol) {
123           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
124           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
125           val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
126           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
127           val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
128           if ((val1 - val2) >= tol) {
129             exchange = Standard_True;
130           }
131         }
132       }
133 // LCOV_EXCL_STOP
134     } else // compare addresses if shapes are geometrically equal
135       return theShape1.TShape().get() > theShape2.TShape().get();
136   }
137
138   //return val1 < val2;
139   return !exchange;
140 }
141
142 Selector_NExplode::Selector_NExplode(const TopoDS_ListOfShape& theShapes)
143 {
144   std::vector<TopoDS_Shape> aShapesVec;
145
146   for(TopoDS_ListOfShape::Iterator anIter(theShapes); anIter.More(); anIter.Next()) {
147       aShapesVec.push_back(anIter.Value());
148   }
149
150   CompareShapes::DataMapOfShapeDouble aCash;
151   CompareShapes shComp(&aCash);
152   std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
153
154   std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
155   for (; anIter != aShapesVec.end(); ++anIter) {
156     mySorted.Append(*anIter);
157   }
158 }
159
160 Selector_NExplode::Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType)
161 {
162   std::vector<TopoDS_Shape> aShapesVec;
163   TopTools_MapOfShape anAdded; // to avoid same shapes duplication
164   for(TopExp_Explorer anExp(theShape, theType); anExp.More(); anExp.Next()) {
165     if (anAdded.Add(anExp.Current()))
166      aShapesVec.push_back(anExp.Current());
167   }
168
169   CompareShapes::DataMapOfShapeDouble aCash;
170   CompareShapes shComp(&aCash);
171   std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
172
173   std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
174   for (; anIter != aShapesVec.end(); ++anIter) {
175     mySorted.Append(*anIter);
176   }
177 }
178
179
180 int Selector_NExplode::index(const TopoDS_Shape& theSubShape)
181 {
182   TopoDS_ListOfShape::Iterator anIter(mySorted);
183   for(int anIndex = 1; anIter.More(); anIter.Next(), anIndex++) {
184     if (anIter.Value().IsSame(theSubShape))
185       return anIndex;
186   }
187   return -1; // not found
188 }
189
190 TopoDS_Shape Selector_NExplode::shape(const int theIndex)
191 {
192   TopoDS_ListOfShape::Iterator anIter(mySorted);
193   for(int anIndex = 1; anIter.More(); anIter.Next(), anIndex++) {
194     if (anIndex == theIndex)
195       return anIter.Value();
196   }
197   return TopoDS_Shape(); // not found
198 }