0031047: Modeling Algorithms - BRepExtrema_DistShapeShape gives wrong result
[occt.git] / src / BRepClass / BRepClass_FaceExplorer.cxx
CommitLineData
b311480e 1// Created on: 1992-11-19
2// Created by: Remi LEQUETTE
3// Copyright (c) 1992-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
17// Modified by skv - Thu Jul 13 17:42:58 2006 OCC12627
18// Total rewriting of the method Segment; add the method OtherSegment.
19
42cf5bc1 20#include <BRep_Tool.hxx>
21#include <BRepClass_Edge.hxx>
22#include <BRepClass_FaceExplorer.hxx>
a148c938 23#include <BRepTools.hxx>
7fd59977 24#include <Geom2d_Curve.hxx>
42cf5bc1 25#include <Precision.hxx>
7fd59977 26#include <TopoDS.hxx>
cb7f9239 27#include <TopExp.hxx>
e2447a80 28#include <Geom2dAPI_ProjectPointOnCurve.hxx>
7fd59977 29
645ff3b1 30static const Standard_Real Probing_Start = 0.123;
31static const Standard_Real Probing_End = 0.7;
32static const Standard_Real Probing_Step = 0.2111;
33
7fd59977 34//=======================================================================
35//function : BRepClass_FaceExplorer
36//purpose :
37//=======================================================================
38
39BRepClass_FaceExplorer::BRepClass_FaceExplorer(const TopoDS_Face& F) :
40 myFace(F),
41 myCurEdgeInd(1),
47cd8af2 42 myCurEdgePar(Probing_Start),
43 myUMin (Precision::Infinite()),
44 myUMax (-Precision::Infinite()),
45 myVMin (Precision::Infinite()),
46 myVMax (-Precision::Infinite())
7fd59977 47{
48 myFace.Orientation(TopAbs_FORWARD);
49}
50
47cd8af2 51//=======================================================================
52//function : ComputeFaceBounds
53//purpose :
54//=======================================================================
55void BRepClass_FaceExplorer::ComputeFaceBounds()
56{
57 TopLoc_Location aLocation;
58 const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface (myFace, aLocation);
59 aSurface->Bounds (myUMin, myUMax, myVMin, myVMax);
60 if (Precision::IsInfinite (myUMin) || Precision::IsInfinite (myUMax) ||
61 Precision::IsInfinite (myVMin) || Precision::IsInfinite (myVMax))
62 {
63 BRepTools::UVBounds(myFace, myUMin, myUMax, myVMin, myVMax);
64 }
65}
66
a148c938 67//=======================================================================
68//function : CheckPoint
69//purpose :
70//=======================================================================
71
47cd8af2 72Standard_Boolean BRepClass_FaceExplorer::CheckPoint(gp_Pnt2d& thePoint)
a148c938 73{
47cd8af2 74 if (myUMin > myUMax)
a148c938 75 {
47cd8af2 76 ComputeFaceBounds();
77 }
78
79 if (Precision::IsInfinite(myUMin) || Precision::IsInfinite(myUMax) ||
80 Precision::IsInfinite(myVMin) || Precision::IsInfinite(myVMax))
81 {
82 return Standard_True;
a148c938 83 }
84
47cd8af2 85 gp_Pnt2d aCenterPnt(( myUMin + myUMax ) / 2, ( myVMin + myVMax ) / 2);
a148c938 86 Standard_Real aDistance = aCenterPnt.Distance(thePoint);
87 if (Precision::IsInfinite(aDistance))
88 {
47cd8af2 89 thePoint.SetCoord (myUMin - (myUMax - myUMin ),
90 myVMin - (myVMax - myVMin ));
a148c938 91 return Standard_False;
92 }
93 else
94 {
95 Standard_Real anEpsilon = Epsilon(aDistance);
47cd8af2 96 if (anEpsilon > Max (myUMax - myUMin, myVMax - myVMin))
a148c938 97 {
98 gp_Vec2d aLinVec(aCenterPnt, thePoint);
99 gp_Dir2d aLinDir(aLinVec);
100 thePoint = aCenterPnt.XY() + aLinDir.XY() * ( 2. * anEpsilon );
101 return Standard_False;
102 }
103 }
104
105 return Standard_True;
106}
107
7fd59977 108//=======================================================================
109//function : Reject
110//purpose :
111//=======================================================================
112
113Standard_Boolean BRepClass_FaceExplorer::Reject(const gp_Pnt2d&)const
114{
115 return Standard_False;
116}
117
118//=======================================================================
119//function : Segment
120//purpose :
121//=======================================================================
122
123Standard_Boolean BRepClass_FaceExplorer::Segment(const gp_Pnt2d& P,
124 gp_Lin2d& L,
125 Standard_Real& Par)
126{
127 myCurEdgeInd = 1;
645ff3b1 128 myCurEdgePar = Probing_Start;
7fd59977 129
130 return OtherSegment(P, L, Par);
131}
132
133//=======================================================================
134//function : OtherSegment
135//purpose :
136//=======================================================================
137
138Standard_Boolean BRepClass_FaceExplorer::OtherSegment(const gp_Pnt2d& P,
139 gp_Lin2d& L,
140 Standard_Real& Par)
141{
e2447a80 142 TopExp_Explorer anExpF(myFace, TopAbs_EDGE);
7fd59977 143 Standard_Integer i;
144 Standard_Real aFPar;
145 Standard_Real aLPar;
146 Handle(Geom2d_Curve) aC2d;
645ff3b1 147 Standard_Real aTolParConf2 = Precision::PConfusion() * Precision::PConfusion();
7fd59977 148 gp_Pnt2d aPOnC;
149 Standard_Real aParamIn;
150
151 for (i = 1; anExpF.More(); anExpF.Next(), i++) {
152 if (i != myCurEdgeInd)
153 continue;
154
e2447a80 155 const TopoDS_Shape &aLocalShape = anExpF.Current();
7fd59977 156 const TopAbs_Orientation anOrientation = aLocalShape.Orientation();
157
158 if (anOrientation == TopAbs_FORWARD || anOrientation == TopAbs_REVERSED) {
159 const TopoDS_Edge &anEdge = TopoDS::Edge(aLocalShape);
160
161 aC2d = BRep_Tool::CurveOnSurface(anEdge, myFace, aFPar, aLPar);
162
163 if (!aC2d.IsNull()) {
e2447a80 164 // Treatment of infinite cases.
165 if (Precision::IsNegativeInfinite(aFPar)) {
166 if (Precision::IsPositiveInfinite(aLPar)) {
167 aFPar = -1.;
168 aLPar = 1.;
169 }
170 else {
171 aFPar = aLPar - 1.;
172 }
173 }
174 else if (Precision::IsPositiveInfinite(aLPar))
175 aLPar = aFPar + 1.;
176
177 for (; myCurEdgePar < Probing_End; myCurEdgePar += Probing_Step) {
178 aParamIn = myCurEdgePar*aFPar + (1. - myCurEdgePar)*aLPar;
7fd59977 179
645ff3b1 180 gp_Vec2d aTanVec;
e2447a80 181 aC2d->D1(aParamIn, aPOnC, aTanVec);
182 Par = aPOnC.SquareDistance(P);
7fd59977 183
e2447a80 184 if (Par > aTolParConf2) {
185 gp_Vec2d aLinVec(P, aPOnC);
186 gp_Dir2d aLinDir(aLinVec);
7fd59977 187
645ff3b1 188 Standard_Real aTanMod = aTanVec.SquareMagnitude();
189 if (aTanMod < aTolParConf2)
190 continue;
191 aTanVec /= Sqrt(aTanMod);
192 Standard_Real aSinA = aTanVec.Crossed(aLinDir.XY());
193 const Standard_Real SmallAngle = 0.001;
e2447a80 194 Standard_Boolean isSmallAngle = Standard_False;
645ff3b1 195 if (Abs(aSinA) < SmallAngle)
196 {
e2447a80 197 isSmallAngle = Standard_True;
645ff3b1 198 // The line from the input point P to the current point on edge
199 // is tangent to the edge curve. This condition is bad for classification.
200 // Therefore try to go to another point in the hope that there will be
201 // no tangent. If there tangent is preserved then leave the last point in
202 // order to get this edge chanse to participate in classification.
203 if (myCurEdgePar + Probing_Step < Probing_End)
204 continue;
205 }
206
e2447a80 207 L = gp_Lin2d(P, aLinDir);
208
209 // Check if ends of a curve lie on a line.
210 aC2d->D0(aFPar, aPOnC);
211 gp_Pnt2d aFPOnC = aPOnC;
212 if (L.SquareDistance(aPOnC) > aTolParConf2) {
213 aC2d->D0(aLPar, aPOnC);
214 if (L.SquareDistance(aPOnC) > aTolParConf2) {
215
216 if (isSmallAngle)
217 {
218 //Try to find minimal distance between curve and line
219
220 Geom2dAPI_ProjectPointOnCurve aProj;
221 aProj.Init(P, aC2d, aFPar, aLPar);
222 if (aProj.NbPoints() > 0)
223 {
224 gp_Pnt2d aLPOnC = aPOnC;
225 Standard_Real aFDist = P.SquareDistance(aFPOnC);
226 Standard_Real aLDist = P.SquareDistance(aLPOnC);
227 Standard_Real aMinDist = aProj.LowerDistance();
228 aMinDist *= aMinDist;
229 aPOnC = aProj.NearestPoint();
230 if (aMinDist > aFDist)
231 {
232 aMinDist = aFDist;
233 aPOnC = aFPOnC;
234 }
235 //
236 if (aMinDist > aLDist)
237 {
238 aMinDist = aLDist;
239 aPOnC = aLPOnC;
240 }
241 //
242 if (aMinDist < Par)
243 {
244 Par = aMinDist;
245 if (Par < aTolParConf2)
246 {
247 continue;
248 }
249 aLinVec.SetXY((aPOnC.XY() - P.XY()));
250 aLinDir.SetXY(aLinVec.XY());
251 L = gp_Lin2d(P, aLinDir);
252 }
253 }
254 }
255 myCurEdgePar += Probing_Step;
256 if (myCurEdgePar >= Probing_End) {
257 myCurEdgeInd++;
258 myCurEdgePar = Probing_Start;
259 }
260
261 Par = Sqrt(Par);
262 return Standard_True;
263 }
264 }
265 }
266 }
7fd59977 267 } // if (!aC2d.IsNull()) {
268 } // if (anOrientation == TopAbs_FORWARD ...
269
270 // This curve is not valid for line construction. Go to another edge.
271 myCurEdgeInd++;
645ff3b1 272 myCurEdgePar = Probing_Start;
7fd59977 273 }
274
275 // nothing found, return an horizontal line
276 Par = RealLast();
e2447a80 277 L = gp_Lin2d(P, gp_Dir2d(1, 0));
7fd59977 278
279 return Standard_False;
280}
281
282//=======================================================================
283//function : InitWires
284//purpose :
285//=======================================================================
286
287void BRepClass_FaceExplorer::InitWires()
288{
289 myWExplorer.Init(myFace,TopAbs_WIRE);
290}
291
292//=======================================================================
293//function : RejectWire NYI
294//purpose :
295//=======================================================================
296
297Standard_Boolean BRepClass_FaceExplorer::RejectWire
298 (const gp_Lin2d& ,
299 const Standard_Real)const
300{
301 return Standard_False;
302}
303
304//=======================================================================
305//function : InitEdges
306//purpose :
307//=======================================================================
308
309void BRepClass_FaceExplorer::InitEdges()
310{
311 myEExplorer.Init(myWExplorer.Current(),TopAbs_EDGE);
cb7f9239 312 myMapVE.Clear();
313 TopExp::MapShapesAndAncestors(myWExplorer.Current(), TopAbs_VERTEX, TopAbs_EDGE, myMapVE);
7fd59977 314}
315
316//=======================================================================
317//function : RejectEdge NYI
318//purpose :
319//=======================================================================
320
321Standard_Boolean BRepClass_FaceExplorer::RejectEdge
322 (const gp_Lin2d& ,
323 const Standard_Real )const
324{
325 return Standard_False;
326}
327
328
329//=======================================================================
330//function : CurrentEdge
331//purpose :
332//=======================================================================
333
334void BRepClass_FaceExplorer::CurrentEdge(BRepClass_Edge& E,
335 TopAbs_Orientation& Or) const
336{
337 E.Edge() = TopoDS::Edge(myEExplorer.Current());
338 E.Face() = myFace;
339 Or = E.Edge().Orientation();
cb7f9239 340 E.SetNextEdge(myMapVE);
7fd59977 341}
342