1 // Copyright (C) 2014-2022 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 "GeomAlgoAPI_SolidClassifier.h"
22 #include <GeomAPI_Pnt.h>
23 #include <GeomAPI_Shape.h>
24 #include <GeomAPI_Solid.h>
26 #include <BRep_Tool.hxx>
27 #include <BRepAdaptor_Curve.hxx>
28 #include <BRepAdaptor_Surface.hxx>
29 #include <BRepBuilderAPI_MakeVertex.hxx>
30 #include <BRepClass_FaceClassifier.hxx>
31 #include <BRepClass3d_SolidClassifier.hxx>
32 #include <BRepExtrema_DistShapeShape.hxx>
36 static GeomAlgoAPI_SolidClassifier::State stateToState(const TopAbs_State theState)
38 GeomAlgoAPI_SolidClassifier::State aResult;
42 aResult = GeomAlgoAPI_SolidClassifier::State_IN;
45 aResult = GeomAlgoAPI_SolidClassifier::State_ON;
48 aResult = GeomAlgoAPI_SolidClassifier::State_OUT;
51 aResult = GeomAlgoAPI_SolidClassifier::State_ALL;
57 static GeomAlgoAPI_SolidClassifier::State
58 classifyMiddlePoint(BRepClass3d_SolidClassifier& theClassifier,
59 const GeomShapePtr& theShape,
60 const double theTolerance)
62 GeomPointPtr aMiddlePoint = theShape->middlePoint();
63 gp_Pnt aPointOnFace = aMiddlePoint->impl<gp_Pnt>();
64 if (theShape->shapeType() == GeomAPI_Shape::FACE) {
65 // middle point may be out of face (within a hole),
66 // in this case, find the nearest point on the face
67 const TopoDS_Face& aFace = theShape->impl<TopoDS_Face>();
68 BRepClass_FaceClassifier aFaceClassifier(aFace, aPointOnFace, theTolerance);
69 if (aFaceClassifier.State() == TopAbs_OUT) {
70 BRepBuilderAPI_MakeVertex aVertex(aPointOnFace);
71 BRepExtrema_DistShapeShape aDistance(aVertex.Vertex(), aFace);
72 if (aDistance.NbSolution())
73 aPointOnFace = aDistance.PointOnShape2(1);
76 theClassifier.Perform(aPointOnFace, theTolerance);
77 return stateToState(theClassifier.State());
80 static GeomAlgoAPI_SolidClassifier::State
81 classifyVertices(BRepClass3d_SolidClassifier& theClassifier,
82 const GeomShapePtr& theShape,
83 const double theTolerance)
85 GeomAlgoAPI_SolidClassifier::State aResult = GeomAlgoAPI_SolidClassifier::State_UNKNOWN;
86 TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
87 for (TopExp_Explorer anExp(aShape, TopAbs_VERTEX);
88 anExp.More() && aResult != GeomAlgoAPI_SolidClassifier::State_ALL;
90 TopoDS_Vertex aCurV = TopoDS::Vertex(anExp.Current());
91 theClassifier.Perform(BRep_Tool::Pnt(aCurV), theTolerance);
92 aResult |= stateToState(theClassifier.State());
97 static GeomAlgoAPI_SolidClassifier::State
98 classifyVicinityOnEdge(BRepClass3d_SolidClassifier& theClassifier,
99 const TopoDS_Edge& theEdge,
100 const double theParameter,
101 const double theTolerance)
103 // coefficient to step out of the vicinity of theParameter
104 static const double THE_STEP_COEFF = 2.0;
106 BRepAdaptor_Curve aCurve(theEdge);
107 double aParStep = aCurve.Resolution(theTolerance) * THE_STEP_COEFF;
108 double aParams[2] = { theParameter - aParStep, theParameter + aParStep };
110 GeomAlgoAPI_SolidClassifier::State aResult = GeomAlgoAPI_SolidClassifier::State_UNKNOWN;
111 for (double* anIt = std::begin(aParams); anIt != std::end(aParams); ++anIt) {
112 if (*anIt < aCurve.FirstParameter())
113 *anIt = aCurve.FirstParameter();
114 else if (*anIt > aCurve.LastParameter())
115 *anIt = aCurve.LastParameter();
117 gp_Pnt aPnt = aCurve.Value(*anIt);
118 theClassifier.Perform(aPnt, theTolerance);
119 aResult |= stateToState(theClassifier.State());
124 static GeomAlgoAPI_SolidClassifier::State
125 classifyVicinityOnFace(BRepClass3d_SolidClassifier& theClassifier,
126 const TopoDS_Face& theFace,
129 const double theTolerance)
131 // coefficient to step out of the vicinity of parameters
132 static const double THE_STEP_COEFF = 2.0;
134 BRepAdaptor_Surface aSurf(theFace);
135 double aStepU = aSurf.UResolution(theTolerance) * THE_STEP_COEFF;
136 double aStepV = aSurf.VResolution(theTolerance) * THE_STEP_COEFF;
137 double aParamsU[3] = { theU - aStepU, theU, theU + aStepU };
138 double aParamsV[3] = { theV - aStepV, theV, theV + aStepV };
139 for (double* aU = std::begin(aParamsU); aU != std::end(aParamsU); ++aU) {
140 if (*aU < aSurf.FirstUParameter())
141 *aU = aSurf.FirstUParameter();
142 else if (*aU > aSurf.LastUParameter())
143 *aU = aSurf.LastUParameter();
145 for (double* aV = std::begin(aParamsV); aV != std::end(aParamsV); ++aV) {
146 if (*aV < aSurf.FirstVParameter())
147 *aV = aSurf.FirstVParameter();
148 else if (*aV > aSurf.LastVParameter())
149 *aV = aSurf.LastVParameter();
152 GeomAlgoAPI_SolidClassifier::State aResult = GeomAlgoAPI_SolidClassifier::State_UNKNOWN;
153 for (double* aU = std::begin(aParamsU); aU != std::end(aParamsU); ++aU)
154 for (double* aV = std::begin(aParamsV); aV != std::end(aParamsV); ++aV) {
155 gp_Pnt aPnt = aSurf.Value(*aU, *aV);
156 theClassifier.Perform(aPnt, theTolerance);
157 aResult |= stateToState(theClassifier.State());
162 static GeomAlgoAPI_SolidClassifier::State
163 classifyByDistance(BRepClass3d_SolidClassifier& theClassifier,
164 const GeomShapePtr& theSolid,
165 const GeomShapePtr& theShape,
166 const double theTolerance)
168 GeomAlgoAPI_SolidClassifier::State aResult = GeomAlgoAPI_SolidClassifier::State_UNKNOWN;
170 const TopoDS_Shape& aSolid = theSolid->impl<TopoDS_Shape>();
171 const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
172 for (TopExp_Explorer anExp(aSolid, TopAbs_SHELL); anExp.More(); anExp.Next()) {
173 // compare distance from the shape to the solid's shells
174 BRepExtrema_DistShapeShape aDistance(anExp.Current(), aShape);
175 if (aDistance.Perform() && aDistance.Value() < theTolerance) {
176 aResult |= GeomAlgoAPI_SolidClassifier::State_ON;
177 // classify vicinity of intersection points
178 for (int sol = 1; sol <= aDistance.NbSolution(); ++sol) {
179 if (aDistance.SupportTypeShape2(sol) == BRepExtrema_IsOnEdge) {
180 TopoDS_Edge anEdge = TopoDS::Edge(aDistance.SupportOnShape2(sol));
182 aDistance.ParOnEdgeS2(sol, aParOnEdge);
184 aResult |= classifyVicinityOnEdge(theClassifier, anEdge, aParOnEdge, theTolerance);
186 else if (aDistance.SupportTypeShape2(sol) == BRepExtrema_IsInFace) {
187 TopoDS_Face aFace = TopoDS::Face(aDistance.SupportOnShape2(sol));
189 aDistance.ParOnFaceS2(sol, aParU, aParV);
191 aResult |= classifyVicinityOnFace(theClassifier, aFace, aParU, aParV, theTolerance);
200 //==================================================================================================
201 GeomAlgoAPI_SolidClassifier::GeomAlgoAPI_SolidClassifier(const GeomSolidPtr theSolid,
202 const GeomShapePtr theShape,
203 const double theTolerance)
204 : myState(State_UNKNOWN)
206 if (!theSolid || !theShape)
209 BRepClass3d_SolidClassifier aClassifierAlgo(theSolid->impl<TopoDS_Shape>());
211 myState = classifyMiddlePoint(aClassifierAlgo, theShape, theTolerance);
212 if (!theShape->isVertex())
213 myState |= classifyVertices(aClassifierAlgo, theShape, theTolerance);
214 myState |= classifyByDistance(aClassifierAlgo, theSolid, theShape, theTolerance);
216 if (myState == State_ALL)
217 myState = State_UNKNOWN;