1 // Copyright (C) 2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "Selector_NExplode.h"
23 #include <TopoDS_Shape.hxx>
24 #include <BRep_Tool.hxx>
26 #include <GProp_GProps.hxx>
27 #include <BRepGProp.hxx>
28 #include <NCollection_DataMap.hxx>
29 #include <Precision.hxx>
30 #include <Bnd_Box.hxx>
31 #include <BRepBndLib.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TopTools_MapOfShape.hxx>
38 static std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S)
40 // Computing of CentreOfMass
44 if (S.ShapeType() == TopAbs_VERTEX) {
45 GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
46 Len = (double)S.Orientation();
50 if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
51 BRepGProp::LinearProperties(S, GPr);
53 else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
54 BRepGProp::SurfaceProperties(S, GPr);
57 BRepGProp::VolumeProperties(S, GPr);
59 GPoint = GPr.CentreOfMass();
63 double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
64 return std::make_pair(dMidXYZ, Len);
68 * \brief Sort shapes in the list by their coordinates.
70 struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
72 typedef NCollection_DataMap<TopoDS_Shape, std::pair<double, double> > DataMapOfShapeDouble;
74 CompareShapes(DataMapOfShapeDouble* theCashMap) : myMap(theCashMap) {}
76 bool operator() (const TopoDS_Shape& lhs, const TopoDS_Shape& rhs);
78 DataMapOfShapeDouble* myMap;
81 bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
82 const TopoDS_Shape& theShape2)
84 if (!myMap->IsBound(theShape1)) {
85 myMap->Bind(theShape1, ShapeToDouble(theShape1));
88 if (!myMap->IsBound(theShape2)) {
89 myMap->Bind(theShape2, ShapeToDouble(theShape2));
92 std::pair<double, double> val1 = myMap->Find(theShape1);
93 std::pair<double, double> val2 = myMap->Find(theShape2);
95 double tol = Precision::Confusion();
96 bool exchange = Standard_False;
98 double dMidXYZ = val1.first - val2.first;
100 exchange = Standard_True;
102 else if (Abs(dMidXYZ) < tol) {
103 double dLength = val1.second - val2.second;
104 if (dLength >= tol) {
105 exchange = Standard_True;
107 else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
108 // equal values possible on shapes such as two halves of a sphere and
109 // a membrane inside the sphere
111 BRepBndLib::Add(theShape1, box1);
112 if (!box1.IsVoid()) {
113 BRepBndLib::Add(theShape2, box2);
114 Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
115 if (dSquareExtent >= tol) {
116 exchange = Standard_True;
118 else if (Abs(dSquareExtent) < tol) {
119 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
120 box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
121 val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
122 box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
123 val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
124 if ((val1 - val2) >= tol) {
125 exchange = Standard_True;
129 } else // compare adresses if shapes are geometrically equal
130 return theShape1.TShape().get() > theShape2.TShape().get();
133 //return val1 < val2;
137 Selector_NExplode::Selector_NExplode(const TopoDS_ListOfShape& theShapes)
139 std::vector<TopoDS_Shape> aShapesVec;
141 for(TopoDS_ListOfShape::Iterator anIter(theShapes); anIter.More(); anIter.Next()) {
142 aShapesVec.push_back(anIter.Value());
145 CompareShapes::DataMapOfShapeDouble aCash;
146 CompareShapes shComp(&aCash);
147 std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
149 std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
150 for (; anIter != aShapesVec.end(); ++anIter) {
151 mySorted.Append(*anIter);
155 Selector_NExplode::Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType)
157 std::vector<TopoDS_Shape> aShapesVec;
158 TopTools_MapOfShape anAdded; // to avoid same shapes duplication
159 for(TopExp_Explorer anExp(theShape, theType); anExp.More(); anExp.Next()) {
160 if (anAdded.Add(anExp.Current()))
161 aShapesVec.push_back(anExp.Current());
164 CompareShapes::DataMapOfShapeDouble aCash;
165 CompareShapes shComp(&aCash);
166 std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
168 std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
169 for (; anIter != aShapesVec.end(); ++anIter) {
170 mySorted.Append(*anIter);
175 int Selector_NExplode::index(const TopoDS_Shape& theSubShape)
177 TopoDS_ListOfShape::Iterator anIter(mySorted);
178 for(int anIndex = 1; anIter.More(); anIter.Next(), anIndex++) {
179 if (anIter.Value().IsSame(theSubShape))
182 return -1; // not found
185 TopoDS_Shape Selector_NExplode::shape(const int theIndex)
187 TopoDS_ListOfShape::Iterator anIter(mySorted);
188 for(int anIndex = 1; anIter.More(); anIter.Next(), anIndex++) {
189 if (anIndex == theIndex)
190 return anIter.Value();
192 return TopoDS_Shape(); // not found