1 // Copyright (C) 2014-2019 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 <BRepClass3d_SolidClassifier.hxx>
30 #include <BRepExtrema_DistShapeShape.hxx>
34 static GeomAlgoAPI_SolidClassifier::State stateToState(const TopAbs_State theState)
36 GeomAlgoAPI_SolidClassifier::State aResult;
40 aResult = GeomAlgoAPI_SolidClassifier::State_IN;
43 aResult = GeomAlgoAPI_SolidClassifier::State_ON;
46 aResult = GeomAlgoAPI_SolidClassifier::State_OUT;
49 aResult = GeomAlgoAPI_SolidClassifier::State_ALL;
55 static GeomAlgoAPI_SolidClassifier::State
56 classifyMiddlePoint(BRepClass3d_SolidClassifier& theClassifier,
57 const GeomShapePtr& theShape,
58 const double theTolerance)
60 GeomPointPtr aMiddlePoint = theShape->middlePoint();
61 theClassifier.Perform(aMiddlePoint->impl<gp_Pnt>(), theTolerance);
62 return stateToState(theClassifier.State());
65 static GeomAlgoAPI_SolidClassifier::State
66 classifyVertices(BRepClass3d_SolidClassifier& theClassifier,
67 const GeomShapePtr& theShape,
68 const double theTolerance)
70 GeomAlgoAPI_SolidClassifier::State aResult = GeomAlgoAPI_SolidClassifier::State_UNKNOWN;
71 TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
72 for (TopExp_Explorer anExp(aShape, TopAbs_VERTEX);
73 anExp.More() && aResult != GeomAlgoAPI_SolidClassifier::State_ALL;
75 TopoDS_Vertex aCurV = TopoDS::Vertex(anExp.Current());
76 theClassifier.Perform(BRep_Tool::Pnt(aCurV), theTolerance);
77 aResult |= stateToState(theClassifier.State());
82 static GeomAlgoAPI_SolidClassifier::State
83 classifyVicinityOnEdge(BRepClass3d_SolidClassifier& theClassifier,
84 const TopoDS_Edge& theEdge,
85 const double theParameter,
86 const double theTolerance)
88 // coefficient to step out of the vicinity of theParameter
89 static const double THE_STEP_COEFF = 2.0;
91 BRepAdaptor_Curve aCurve(theEdge);
92 double aParStep = aCurve.Resolution(theTolerance) * THE_STEP_COEFF;
93 double aParams[2] = { theParameter - aParStep, theParameter + aParStep };
95 GeomAlgoAPI_SolidClassifier::State aResult = GeomAlgoAPI_SolidClassifier::State_UNKNOWN;
96 for (double* anIt = std::begin(aParams); anIt != std::end(aParams); ++anIt) {
97 if (*anIt < aCurve.FirstParameter())
98 *anIt = aCurve.FirstParameter();
99 else if (*anIt > aCurve.LastParameter())
100 *anIt = aCurve.LastParameter();
102 gp_Pnt aPnt = aCurve.Value(*anIt);
103 theClassifier.Perform(aPnt, theTolerance);
104 aResult |= stateToState(theClassifier.State());
109 static GeomAlgoAPI_SolidClassifier::State
110 classifyVicinityOnFace(BRepClass3d_SolidClassifier& theClassifier,
111 const TopoDS_Face& theFace,
114 const double theTolerance)
116 // coefficient to step out of the vicinity of parameters
117 static const double THE_STEP_COEFF = 2.0;
119 BRepAdaptor_Surface aSurf(theFace);
120 double aStepU = aSurf.UResolution(theTolerance) * THE_STEP_COEFF;
121 double aStepV = aSurf.VResolution(theTolerance) * THE_STEP_COEFF;
122 double aParamsU[3] = { theU - aStepU, theU, theU + aStepU };
123 double aParamsV[3] = { theV - aStepV, theV, theV + aStepV };
124 for (double* aU = std::begin(aParamsU); aU != std::end(aParamsU); ++aU) {
125 if (*aU < aSurf.FirstUParameter())
126 *aU = aSurf.FirstUParameter();
127 else if (*aU > aSurf.LastUParameter())
128 *aU = aSurf.LastUParameter();
130 for (double* aV = std::begin(aParamsV); aV != std::end(aParamsV); ++aV) {
131 if (*aV < aSurf.FirstVParameter())
132 *aV = aSurf.FirstVParameter();
133 else if (*aV > aSurf.LastVParameter())
134 *aV = aSurf.LastVParameter();
137 GeomAlgoAPI_SolidClassifier::State aResult = GeomAlgoAPI_SolidClassifier::State_UNKNOWN;
138 for (double* aU = std::begin(aParamsU); aU != std::end(aParamsU); ++aU)
139 for (double* aV = std::begin(aParamsV); aV != std::end(aParamsV); ++aV) {
140 gp_Pnt aPnt = aSurf.Value(*aU, *aV);
141 theClassifier.Perform(aPnt, theTolerance);
142 aResult |= stateToState(theClassifier.State());
147 static GeomAlgoAPI_SolidClassifier::State
148 classifyByDistance(BRepClass3d_SolidClassifier& theClassifier,
149 const GeomShapePtr& theSolid,
150 const GeomShapePtr& theShape,
151 const double theTolerance)
153 GeomAlgoAPI_SolidClassifier::State aResult = GeomAlgoAPI_SolidClassifier::State_UNKNOWN;
155 const TopoDS_Shape& aSolid = theSolid->impl<TopoDS_Shape>();
156 const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
157 for (TopExp_Explorer anExp(aSolid, TopAbs_SHELL); anExp.More(); anExp.Next()) {
158 // compare distance from the shape to the solid's shells
159 BRepExtrema_DistShapeShape aDistance(anExp.Current(), aShape);
160 if (aDistance.Perform() && aDistance.Value() < theTolerance) {
161 aResult |= GeomAlgoAPI_SolidClassifier::State_ON;
162 // classify vicinity of intersection points
163 for (int sol = 1; sol <= aDistance.NbSolution(); ++sol) {
164 if (aDistance.SupportTypeShape2(sol) == BRepExtrema_IsOnEdge) {
165 TopoDS_Edge anEdge = TopoDS::Edge(aDistance.SupportOnShape2(sol));
167 aDistance.ParOnEdgeS2(sol, aParOnEdge);
169 aResult |= classifyVicinityOnEdge(theClassifier, anEdge, aParOnEdge, theTolerance);
171 else if (aDistance.SupportTypeShape2(sol) == BRepExtrema_IsInFace) {
172 TopoDS_Face aFace = TopoDS::Face(aDistance.SupportOnShape2(sol));
174 aDistance.ParOnFaceS2(sol, aParU, aParV);
176 aResult |= classifyVicinityOnFace(theClassifier, aFace, aParU, aParV, theTolerance);
185 //==================================================================================================
186 GeomAlgoAPI_SolidClassifier::GeomAlgoAPI_SolidClassifier(const GeomSolidPtr theSolid,
187 const GeomShapePtr theShape,
188 const double theTolerance)
189 : myState(State_UNKNOWN)
191 if (!theSolid || !theShape)
194 BRepClass3d_SolidClassifier aClassifierAlgo(theSolid->impl<TopoDS_Shape>());
196 myState = classifyMiddlePoint(aClassifierAlgo, theShape, theTolerance);
197 if (!theShape->isVertex())
198 myState |= classifyVertices(aClassifierAlgo, theShape, theTolerance);
199 myState |= classifyByDistance(aClassifierAlgo, theSolid, theShape, theTolerance);
201 if (myState == State_ALL)
202 myState = State_UNKNOWN;