1 // Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "StudyData_Operation.h"
25 #include <Precision.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>
36 #include <TopExp_Explorer.hxx>
37 #include <TopTools_ListOfShape.hxx>
38 #include <GProp_GProps.hxx>
39 #include <BRepGProp.hxx>
44 static const int TopAbs_FLAT = TopAbs_SHAPE+1;
46 static void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M)
48 if (S.ShapeType() != TopAbs_COMPOUND) {
52 TopoDS_Iterator It(S, Standard_True, Standard_True);
53 for (; It.More(); It.Next()) {
54 TopoDS_Shape SS = It.Value();
56 AddFlatSubShapes(SS, L, M);
61 static std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S)
63 // Computing of CentreOfMass
67 if (S.ShapeType() == TopAbs_VERTEX) {
68 GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
69 Len = (double)S.Orientation();
73 if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
74 BRepGProp::LinearProperties(S, GPr);
76 else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
77 BRepGProp::SurfaceProperties(S, GPr);
80 BRepGProp::VolumeProperties(S, GPr);
82 GPoint = GPr.CentreOfMass();
86 double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
87 return std::make_pair(dMidXYZ, Len);
90 /// Sort shapes in the list by their coordinates.
91 struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
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;
99 bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
100 const TopoDS_Shape& theShape2)
102 if (!myMap.IsBound(theShape1)) {
103 myMap.Bind(theShape1, ShapeToDouble(theShape1));
106 if (!myMap.IsBound(theShape2)) {
107 myMap.Bind(theShape2, ShapeToDouble(theShape2));
110 std::pair<double, double> val1 = myMap.Find(theShape1);
111 std::pair<double, double> val2 = myMap.Find(theShape2);
113 double tol = Precision::Confusion();
114 bool exchange = Standard_False;
116 double dMidXYZ = val1.first - val2.first;
117 if (dMidXYZ >= tol) {
118 exchange = Standard_True;
120 else if (Abs(dMidXYZ) < tol) {
121 double dLength = val1.second - val2.second;
122 if (dLength >= tol) {
123 exchange = Standard_True;
125 else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
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;
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;
148 //return val1 < val2;
153 static void SortShapes (TopTools_ListOfShape& SL)
155 std::vector<TopoDS_Shape> aShapesVec;
156 aShapesVec.reserve(SL.Extent());
158 TopTools_ListIteratorOfListOfShape it (SL);
159 for (; it.More(); it.Next()) {
160 aShapesVec.push_back(it.Value());
164 CompareShapes shComp;
165 std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
166 //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp);
168 std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
169 for (; anIter != aShapesVec.end(); ++anIter) {
175 std::list<long> StudyData_Operation::GetAllSubShapesIDs(
176 const long long theShape, const int theShapeType, const bool isSorted)
178 TopoDS_Shape* aShape = (TopoDS_Shape*)theShape;
180 std::list<long> aResult;
181 TopTools_MapOfShape mapShape;
182 TopTools_ListOfShape listShape;
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);
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());
204 if (listShape.IsEmpty()) {
209 SortShapes(listShape);
212 TopTools_IndexedMapOfShape anIndices;
213 TopExp::MapShapes(*aShape, anIndices);
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));
224 std::list<long long> StudyData_Operation::GetSharedShapes(
225 const long long theShape1, const long long theShape2, const int theShapeType)
227 std::list<long long> aResult;
229 TopoDS_Shape* aShape1 = (TopoDS_Shape*)theShape1;
230 TopoDS_Shape* aShape2 = (TopoDS_Shape*)theShape2;
231 if (aShape1->IsNull() || aShape2->IsNull())
233 TopTools_IndexedMapOfShape anIndices;
234 TopExp::MapShapes(*aShape1, anIndices);
235 Handle(TColStd_HArray1OfInteger) anArray;
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);
254 int StudyData_Operation::GetSubShapeIndex(const long long theMainShape, const long long theSubShape)
256 TopoDS_Shape* aMainShape = (TopoDS_Shape*)theMainShape;
257 TopoDS_Shape* aSubShape = (TopoDS_Shape*)theSubShape;
258 if ( !aMainShape || !aSubShape || aMainShape->IsNull() || aSubShape->IsNull())
261 TopTools_IndexedMapOfShape anIndices;
262 TopExp::MapShapes(*aMainShape, anIndices);
263 return anIndices.FindIndex(*aSubShape);
266 int StudyData_Operation::GetTopologyIndex(const long long theMainShape, const long long theSubShape)
268 TopoDS_Shape* aMainShape = (TopoDS_Shape*)theMainShape;
269 TopoDS_Shape* aSubShape = (TopoDS_Shape*)theSubShape;
270 if ( !aMainShape || !aSubShape || aMainShape->IsNull() || aSubShape->IsNull())
273 TopTools_IndexedMapOfShape anIndices;
274 TopExp::MapShapes(*aMainShape, aSubShape->ShapeType(), anIndices);
275 return anIndices.FindIndex(*aSubShape);
278 long long StudyData_Operation::GetSubShape(const long long theMainShape, long theID)
280 TopoDS_Shape* aMainShape = (TopoDS_Shape*)theMainShape;
281 if (aMainShape->IsNull())
283 TopTools_IndexedMapOfShape anIndices;
284 TopExp::MapShapes(*aMainShape, anIndices);
285 if (anIndices.Size() < theID)
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));
293 std::list<long long> StudyData_Operation::ExtractSubShapes(const long long theMainShape,
294 const int theShapeType,
295 const bool theIsSorted)
297 std::list<long long> resultList;
299 TopoDS_Shape* aShape = (TopoDS_Shape*)theMainShape;
300 if ( !aShape || aShape->IsNull())
303 std::list<long> aResult;
304 TopTools_MapOfShape mapShape;
305 TopTools_ListOfShape listShape;
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);
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());
327 if (listShape.IsEmpty()) {
332 SortShapes(listShape);
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)) );
344 std::list<double> StudyData_Operation::PointCoordinates(const long long theVertex)
346 std::list<double> xyz;
348 TopoDS_Shape* aShape = (TopoDS_Shape*)theVertex;
349 if ( !aShape || aShape->IsNull() || aShape->ShapeType() != TopAbs_VERTEX )
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() );
360 double StudyData_Operation::MinDistance(const long long theVertex1, const long long theVertex2)
363 TopoDS_Shape* aShape1 = (TopoDS_Shape*)theVertex1;
364 TopoDS_Shape* aShape2 = (TopoDS_Shape*)theVertex2;
366 if ( !aShape1 || aShape1->IsNull() || aShape1->ShapeType() != TopAbs_VERTEX ||
367 !aShape2 || aShape2->IsNull() || aShape2->ShapeType() != TopAbs_VERTEX )
370 gp_Pnt p1 = BRep_Tool::Pnt( TopoDS::Vertex( *aShape1 ));
371 gp_Pnt p2 = BRep_Tool::Pnt( TopoDS::Vertex( *aShape2 ));
373 result = p1.Distance( p2 );
377 int StudyData_Operation::NumberOfEdges(const long long theShape)
381 TopoDS_Shape* aShape = (TopoDS_Shape*)theShape;
382 if ( !aShape || aShape->IsNull() )
385 TopTools_IndexedMapOfShape anIndices;
386 TopExp::MapShapes(*aShape, TopAbs_EDGE, anIndices);
387 nb = anIndices.Extent();
392 int StudyData_Operation::NumberOfFaces(const long long theShape)
396 TopoDS_Shape* aShape = (TopoDS_Shape*)theShape;
397 if ( !aShape || aShape->IsNull() )
400 TopTools_IndexedMapOfShape anIndices;
401 TopExp::MapShapes(*aShape, TopAbs_FACE, anIndices);
402 nb = anIndices.Extent();
407 double StudyData_Operation::GetTolerance( const long long theVertex )
411 TopoDS_Shape* aShape = (TopoDS_Shape*)theVertex;
412 if ( !aShape || aShape->IsNull() || aShape->ShapeType() != TopAbs_VERTEX )
415 tol = BRep_Tool::Tolerance( TopoDS::Vertex( *aShape ));
420 long long StudyData_Operation::GetVertexByIndex(const long long theEdge,
424 TopoDS_Shape* aShape = (TopoDS_Shape*)theEdge;
425 if ( !aShape || aShape->IsNull() || aShape->ShapeType() != TopAbs_EDGE )
429 aShape->Orientation( TopAbs_FORWARD );
431 TopoDS_Vertex aVertex;
433 aVertex = TopExp::FirstVertex( TopoDS::Edge( *aShape ));
435 aVertex = TopExp::LastVertex( TopoDS::Edge( *aShape ));
437 return (long long)(new TopoDS_Shape( aVertex ));