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 "GeomAlgoAPI_SortListOfShapes.h"
23 #include <Bnd_Box.hxx>
24 #include <Bnd_Box2d.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepBndLib.hxx>
27 #include <BRepTools.hxx>
29 #include <Precision.hxx>
31 #include <TopoDS_Edge.hxx>
32 #include <TopoDS_Face.hxx>
39 std::map<TopoDS_TShape*, Bnd_Box> myShapes;
40 std::map<TopoDS_TShape*, Bnd_Box2d> myUVBounds;
42 bool compareEdges(const GeomShapePtr& theLHS, const GeomShapePtr& theRHS)
44 const TopoDS_Edge& aLHSEdge = TopoDS::Edge(theLHS->impl<TopoDS_Shape>());
45 const TopoDS_Edge& aRHSEdge = TopoDS::Edge(theRHS->impl<TopoDS_Shape>());
47 double aLF, aLE, aRF, aRE;
48 Handle(Geom_Curve) aLHSCurve = BRep_Tool::Curve(aLHSEdge, aLF, aLE);
49 Handle(Geom_Curve) aRHSCurve = BRep_Tool::Curve(aRHSEdge, aRF, aRE);
51 if (aLHSCurve == aRHSCurve) {
52 // compare by first parameter
53 if (isLessWithTol(aLF, aRF, Precision::PConfusion()))
55 else if (isLessWithTol(aRF, aLF, Precision::PConfusion()))
57 // compare by last parameter
58 return isLessWithTol(aLE, aRE, Precision::PConfusion());
60 // different underlying curves => compare bounding boxe
61 return compareByBoundingBox(theLHS, theRHS);
64 bool compareFaces(const GeomShapePtr& theLHS, const GeomShapePtr& theRHS)
66 const TopoDS_Face& aLHSFace = TopoDS::Face(theLHS->impl<TopoDS_Shape>());
67 const TopoDS_Face& aRHSFace = TopoDS::Face(theRHS->impl<TopoDS_Shape>());
69 Handle(Geom_Surface) aLHSSurf = BRep_Tool::Surface(aLHSFace);
70 Handle(Geom_Surface) aRHSSurf = BRep_Tool::Surface(aRHSFace);
72 if (aLHSSurf == aRHSSurf) {
73 // compare parametric space for faces on the same surface
74 Bnd_Box2d aLHSBox = boundingBoxUV(aLHSFace);
75 Bnd_Box2d aRHSBox = boundingBoxUV(aRHSFace);
77 double aLHSBB[4], aRHSBB[4];
78 aLHSBox.Get(aLHSBB[0], aLHSBB[1], aLHSBB[2], aLHSBB[3]);
79 aRHSBox.Get(aRHSBB[0], aRHSBB[1], aRHSBB[2], aRHSBB[3]);
80 for (int anIndex = 0; anIndex < 4; ++anIndex) {
81 if (isLessWithTol(aLHSBB[anIndex], aRHSBB[anIndex], Precision::PConfusion()))
83 else if (isLessWithTol(aRHSBB[anIndex], aLHSBB[anIndex], Precision::PConfusion()))
86 // equal parametric boxes
89 // different underlying surfaces => compare bounding boxes
90 return compareByBoundingBox(theLHS, theRHS);
93 bool compareByBoundingBox(const GeomShapePtr& theLHS, const GeomShapePtr& theRHS)
95 Bnd_Box aLHSBox = boundingBox(theLHS);
96 Bnd_Box aRHSBox = boundingBox(theRHS);
98 gp_Pnt aLHSMin = aLHSBox.CornerMin();
99 gp_Pnt aLHSMax = aLHSBox.CornerMax();
101 gp_Pnt aRHSMin = aRHSBox.CornerMin();
102 gp_Pnt aRHSMax = aRHSBox.CornerMax();
104 if (isLess(aLHSMin, aRHSMin))
106 else if (isLess(aRHSMin, aLHSMin))
109 return isLess(aLHSMax, aRHSMax);
112 bool isLessWithTol(const double theLHS, const double theRHS, const double theTolerance)
114 return theLHS + theTolerance < theRHS;
117 bool isLess(const gp_Pnt& theLHS, const gp_Pnt& theRHS)
119 static const double aTol = 10. * Precision::Confusion();
120 for (int anIndex = 1; anIndex <= 3; ++anIndex) {
121 if (isLessWithTol(theLHS.Coord(anIndex), theRHS.Coord(anIndex), aTol))
123 else if (isLessWithTol(theRHS.Coord(anIndex), theLHS.Coord(anIndex), aTol))
130 Bnd_Box boundingBox(const GeomShapePtr& theShape)
132 const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
133 TopoDS_TShape* aS = aShape.TShape().get();
134 std::map<TopoDS_TShape*, Bnd_Box>::iterator aFound = myShapes.find(aS);
135 if (aFound == myShapes.end()) {
137 BRepBndLib::AddOptimal(aShape, aBB, false);
139 aFound = myShapes.find(aS);
141 return aFound->second;
144 Bnd_Box2d boundingBoxUV(const TopoDS_Face& theFace)
146 TopoDS_TShape* aFacePtr = theFace.TShape().get();
147 std::map<TopoDS_TShape*, Bnd_Box2d>::iterator aFound = myUVBounds.find(aFacePtr);
148 if (aFound == myUVBounds.end()) {
150 BRepTools::AddUVBounds(theFace, aBB);
151 myUVBounds[aFacePtr] = aBB;
152 aFound = myUVBounds.find(aFacePtr);
154 return aFound->second;
158 // Verify theLHS is less than theRHS
159 bool operator() (const GeomShapePtr& theLHS, const GeomShapePtr& theRHS)
161 if (theLHS->shapeType() == theRHS->shapeType()) {
162 // edges and faces are compared by geometric properties
163 if (theLHS->shapeType() == GeomAPI_Shape::EDGE)
164 return compareEdges(theLHS, theRHS);
165 else if (theLHS->shapeType() == GeomAPI_Shape::FACE)
166 return compareFaces(theLHS, theRHS);
167 // all other comparisons are made by bounding boxes
168 return compareByBoundingBox(theLHS, theRHS);
171 // shapes of different types are compared by the type
172 return theLHS->shapeType() < theRHS->shapeType();
177 void GeomAlgoAPI_SortListOfShapes::sort(ListOfShape& theShapes)
179 CompareShapes aComparator;
180 theShapes.sort(aComparator);