1 // Copyright (C) 2019-2020 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 email : webmaster.salome@opencascade.com
20 #include "StudyData_Operation.h"
22 #include <Precision.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>
33 #include <TopExp_Explorer.hxx>
34 #include <TopTools_ListOfShape.hxx>
35 #include <GProp_GProps.hxx>
36 #include <BRepGProp.hxx>
41 static const int TopAbs_FLAT = TopAbs_SHAPE+1;
43 static void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M)
45 if (S.ShapeType() != TopAbs_COMPOUND) {
49 TopoDS_Iterator It(S, Standard_True, Standard_True);
50 for (; It.More(); It.Next()) {
51 TopoDS_Shape SS = It.Value();
53 AddFlatSubShapes(SS, L, M);
58 static std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S)
60 // Computing of CentreOfMass
64 if (S.ShapeType() == TopAbs_VERTEX) {
65 GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
66 Len = (double)S.Orientation();
70 if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
71 BRepGProp::LinearProperties(S, GPr);
73 else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
74 BRepGProp::SurfaceProperties(S, GPr);
77 BRepGProp::VolumeProperties(S, GPr);
79 GPoint = GPr.CentreOfMass();
83 double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
84 return std::make_pair(dMidXYZ, Len);
87 /// Sort shapes in the list by their coordinates.
88 struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
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;
96 bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
97 const TopoDS_Shape& theShape2)
99 if (!myMap.IsBound(theShape1)) {
100 myMap.Bind(theShape1, ShapeToDouble(theShape1));
103 if (!myMap.IsBound(theShape2)) {
104 myMap.Bind(theShape2, ShapeToDouble(theShape2));
107 std::pair<double, double> val1 = myMap.Find(theShape1);
108 std::pair<double, double> val2 = myMap.Find(theShape2);
110 double tol = Precision::Confusion();
111 bool exchange = Standard_False;
113 double dMidXYZ = val1.first - val2.first;
114 if (dMidXYZ >= tol) {
115 exchange = Standard_True;
117 else if (Abs(dMidXYZ) < tol) {
118 double dLength = val1.second - val2.second;
119 if (dLength >= tol) {
120 exchange = Standard_True;
122 else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
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;
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;
145 //return val1 < val2;
150 static void SortShapes (TopTools_ListOfShape& SL)
152 std::vector<TopoDS_Shape> aShapesVec;
153 aShapesVec.reserve(SL.Extent());
155 TopTools_ListIteratorOfListOfShape it (SL);
156 for (; it.More(); it.Next()) {
157 aShapesVec.push_back(it.Value());
161 CompareShapes shComp;
162 std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
163 //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp);
165 std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
166 for (; anIter != aShapesVec.end(); ++anIter) {
172 std::list<long> StudyData_Operation::GetAllSubShapesIDs(
173 const long long theShape, const int theShapeType, const bool isSorted)
175 TopoDS_Shape* aShape = (TopoDS_Shape*)theShape;
177 std::list<long> aResult;
178 TopTools_MapOfShape mapShape;
179 TopTools_ListOfShape listShape;
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);
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());
201 if (listShape.IsEmpty()) {
206 SortShapes(listShape);
209 TopTools_IndexedMapOfShape anIndices;
210 TopExp::MapShapes(*aShape, anIndices);
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));
221 std::list<long long> StudyData_Operation::GetSharedShapes(
222 const long long theShape1, const long long theShape2, const int theShapeType)
224 std::list<long long> aResult;
226 TopoDS_Shape* aShape1 = (TopoDS_Shape*)theShape1;
227 TopoDS_Shape* aShape2 = (TopoDS_Shape*)theShape2;
228 if (aShape1->IsNull() || aShape2->IsNull())
230 TopTools_IndexedMapOfShape anIndices;
231 TopExp::MapShapes(*aShape1, anIndices);
232 Handle(TColStd_HArray1OfInteger) anArray;
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);
251 int StudyData_Operation::GetSubShapeIndex(const long long theMainShape, const long long theSubShape)
253 TopoDS_Shape* aMainShape = (TopoDS_Shape*)theMainShape;
254 TopoDS_Shape* aSubShape = (TopoDS_Shape*)theSubShape;
255 if ( !aMainShape || !aSubShape || aMainShape->IsNull() || aSubShape->IsNull())
258 TopTools_IndexedMapOfShape anIndices;
259 TopExp::MapShapes(*aMainShape, anIndices);
260 return anIndices.FindIndex(*aSubShape);
263 int StudyData_Operation::GetTopologyIndex(const long long theMainShape, const long long theSubShape)
265 TopoDS_Shape* aMainShape = (TopoDS_Shape*)theMainShape;
266 TopoDS_Shape* aSubShape = (TopoDS_Shape*)theSubShape;
267 if ( !aMainShape || !aSubShape || aMainShape->IsNull() || aSubShape->IsNull())
270 TopTools_IndexedMapOfShape anIndices;
271 TopExp::MapShapes(*aMainShape, aSubShape->ShapeType(), anIndices);
272 return anIndices.FindIndex(*aSubShape);
275 long long StudyData_Operation::GetSubShape(const long long theMainShape, long theID)
277 TopoDS_Shape* aMainShape = (TopoDS_Shape*)theMainShape;
278 if (aMainShape->IsNull())
280 TopTools_IndexedMapOfShape anIndices;
281 TopExp::MapShapes(*aMainShape, anIndices);
282 if (anIndices.Size() < theID)
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));
290 std::list<long long> StudyData_Operation::ExtractSubShapes(const long long theMainShape,
291 const int theShapeType,
292 const bool theIsSorted)
294 std::list<long long> resultList;
296 TopoDS_Shape* aShape = (TopoDS_Shape*)theMainShape;
297 if ( !aShape || aShape->IsNull())
300 std::list<long> aResult;
301 TopTools_MapOfShape mapShape;
302 TopTools_ListOfShape listShape;
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);
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());
324 if (listShape.IsEmpty()) {
329 SortShapes(listShape);
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)) );
341 std::list<double> StudyData_Operation::PointCoordinates(const long long theVertex)
343 std::list<double> xyz;
345 TopoDS_Shape* aShape = (TopoDS_Shape*)theVertex;
346 if ( !aShape || aShape->IsNull() || aShape->ShapeType() != TopAbs_VERTEX )
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() );
357 double StudyData_Operation::MinDistance(const long long theVertex1, const long long theVertex2)
360 TopoDS_Shape* aShape1 = (TopoDS_Shape*)theVertex1;
361 TopoDS_Shape* aShape2 = (TopoDS_Shape*)theVertex2;
363 if ( !aShape1 || aShape1->IsNull() || aShape1->ShapeType() != TopAbs_VERTEX ||
364 !aShape2 || aShape2->IsNull() || aShape2->ShapeType() != TopAbs_VERTEX )
367 gp_Pnt p1 = BRep_Tool::Pnt( TopoDS::Vertex( *aShape1 ));
368 gp_Pnt p2 = BRep_Tool::Pnt( TopoDS::Vertex( *aShape2 ));
370 result = p1.Distance( p2 );
374 int StudyData_Operation::NumberOfEdges(const long long theShape)
378 TopoDS_Shape* aShape = (TopoDS_Shape*)theShape;
379 if ( !aShape || aShape->IsNull() )
382 TopTools_IndexedMapOfShape anIndices;
383 TopExp::MapShapes(*aShape, TopAbs_EDGE, anIndices);
384 nb = anIndices.Extent();
389 int StudyData_Operation::NumberOfFaces(const long long theShape)
393 TopoDS_Shape* aShape = (TopoDS_Shape*)theShape;
394 if ( !aShape || aShape->IsNull() )
397 TopTools_IndexedMapOfShape anIndices;
398 TopExp::MapShapes(*aShape, TopAbs_FACE, anIndices);
399 nb = anIndices.Extent();
404 double StudyData_Operation::GetTolerance( const long long theVertex )
408 TopoDS_Shape* aShape = (TopoDS_Shape*)theVertex;
409 if ( !aShape || aShape->IsNull() || aShape->ShapeType() != TopAbs_VERTEX )
412 tol = BRep_Tool::Tolerance( TopoDS::Vertex( *aShape ));
417 long long StudyData_Operation::GetVertexByIndex(const long long theEdge,
421 TopoDS_Shape* aShape = (TopoDS_Shape*)theEdge;
422 if ( !aShape || aShape->IsNull() || aShape->ShapeType() != TopAbs_EDGE )
426 aShape->Orientation( TopAbs_FORWARD );
428 TopoDS_Vertex aVertex;
430 aVertex = TopExp::FirstVertex( TopoDS::Edge( *aShape ));
432 aVertex = TopExp::LastVertex( TopoDS::Edge( *aShape ));
434 return (long long)(new TopoDS_Shape( aVertex ));