0023830: BRepExtrema_DistShapeShape does not find intersection of face with edge
[occt.git] / src / Extrema / Extrema_ExtPExtS.cxx
CommitLineData
b311480e 1// Created on: 1999-09-16
2// Created by: Edward AGAPOV
3// Copyright (c) 1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21
22#include <Standard_NotImplemented.hxx>
23#include <Standard_OutOfRange.hxx>
24#include <StdFail_NotDone.hxx>
25#include <Adaptor3d_HCurve.hxx>
26#include <ElCLib.hxx>
27#include <Extrema_ExtPElC.hxx>
28#include <Extrema_ExtPExtS.hxx>
29#include <Extrema_POnCurv.hxx>
30#include <Extrema_POnSurf.hxx>
31#include <Precision.hxx>
32#include <gp.hxx>
33#include <gp_Ax2.hxx>
34#include <gp_Dir.hxx>
35#include <gp_Lin.hxx>
36#include <gp_Pln.hxx>
37#include <gp_Pnt.hxx>
38#include <gp_Vec.hxx>
39#include <math_FunctionSetRoot.hxx>
40#include <math_Vector.hxx>
41#include <Adaptor3d_SurfaceOfLinearExtrusion.hxx>
42
43static gp_Ax2 GetPosition (const Handle(Adaptor3d_HCurve)& C);
44
45static void PerformExtPElC (Extrema_ExtPElC& E,
46 const gp_Pnt& P,
47 const Handle(Adaptor3d_HCurve)& C,
48 const Standard_Real Tol);
49
50static Standard_Boolean
51 IsCaseAnalyticallyComputable (const GeomAbs_CurveType& theType,
52 const gp_Ax2& theCurvePos,
53 const gp_Dir& theSurfaceDirection) ;
54
55static gp_Pnt GetValue(const Standard_Real U,
56 const Handle(Adaptor3d_HCurve)& C);
57//=======================================================================
58//function : Project
59//purpose : Returns the projection of a point <Point> on a plane
60// <ThePlane> along a direction <TheDir>.
61//=======================================================================
62static gp_Pnt ProjectPnt(const gp_Ax2& ThePlane,
63 const gp_Dir& TheDir,
64 const gp_Pnt& Point)
65{
66 gp_Vec PO(Point,ThePlane.Location());
67 Standard_Real Alpha = PO * gp_Vec(ThePlane.Direction());
68 Alpha /= TheDir * ThePlane.Direction();
69 gp_Pnt P;
70 P.SetXYZ(Point.XYZ() + Alpha * TheDir.XYZ());
71 return P;
72}
73
74//=======================================================================
75//function : IsOriginalPnt
76//purpose :
77//=======================================================================
78
79static Standard_Boolean IsOriginalPnt (const gp_Pnt& P,
80 const Extrema_POnSurf* Points,
81 const Standard_Integer NbPoints)
82{
83 for (Standard_Integer i=1; i<=NbPoints; i++) {
84 if (Points[i-1].Value().IsEqual(P, Precision::Confusion())) {
85 return Standard_False;
86 }
87 }
88 return Standard_True;
89}
90
91//=======================================================================
92//function : MakePreciser
93//purpose :
94//=======================================================================
95
96void Extrema_ExtPExtS::MakePreciser (Standard_Real& U,
97 const gp_Pnt& P,
98 const Standard_Boolean isMin,
99 const gp_Ax2& OrtogSection) const
100{
101 if (U>myusup) {
102 U = myusup;
103 } else if (U<myuinf) {
104 U = myuinf;
105 } else {
106
107 Standard_Real step = (myusup - myuinf) / 30, D2e, D2next ,D2prev;
108 gp_Pnt
109 Pe = ProjectPnt (OrtogSection, myDirection, GetValue(U,myC)),
110 Pprev = ProjectPnt (OrtogSection, myDirection, GetValue(U-step, myC)),
111 Pnext = ProjectPnt (OrtogSection, myDirection, GetValue(U+step, myC));
112 D2e = P.SquareDistance(Pe),
113 D2next = P.SquareDistance(Pnext),
114 D2prev = P.SquareDistance(Pprev);
115 Standard_Boolean notFound;
116 if (isMin)
117 notFound = (D2e > D2prev || D2e > D2next);
118 else
119 notFound = (D2e < D2prev || D2e < D2next);
120
121 if (notFound && (D2e < D2next && isMin)) {
122 step = -step;
123 D2next = D2prev;
124 Pnext = Pprev;
125 }
126 while (notFound) {
127 U = U + step;
128 if (U > myusup) {
129 U = myusup;
130 break;
131 }
132 if (U < myuinf) {
133 U = myuinf;
134 break;
135 }
136 D2e = D2next;
137 Pe = Pnext;
138 Pnext = ProjectPnt (OrtogSection, myDirection, GetValue(U+step, myC));
139 D2next = P.SquareDistance(Pnext);
140 if (isMin)
141 notFound = D2e > D2next;
142 else
143 notFound = D2e < D2next;
144 }
145 }
146}
147//=============================================================================
148
149Extrema_ExtPExtS::Extrema_ExtPExtS ()
150{
151 myDone = Standard_False;
152}
153
154//=============================================================================
155
156Extrema_ExtPExtS::Extrema_ExtPExtS (const gp_Pnt& P,
157 const Adaptor3d_SurfaceOfLinearExtrusion& S,
158 const Standard_Real Umin,
159 const Standard_Real Usup,
160 const Standard_Real Vmin,
161 const Standard_Real Vsup,
162 const Standard_Real TolU,
163 const Standard_Real TolV)
164{
165 Initialize (S,
166 Umin, Usup, Vmin, Vsup,
167 TolU, TolV);
168 Perform(P);
169}
170//=============================================================================
171
172Extrema_ExtPExtS::Extrema_ExtPExtS (const gp_Pnt& P,
173 const Adaptor3d_SurfaceOfLinearExtrusion& S,
174 const Standard_Real TolU,
175 const Standard_Real TolV)
176{
177 Initialize (S,
178 S.FirstUParameter(), S.LastUParameter(),
179 S.FirstVParameter(), S.LastVParameter(),
180 TolU, TolV);
181 Perform(P);
182}
183//=======================================================================
184//function : Initialize
185//purpose :
186//=======================================================================
187
188void Extrema_ExtPExtS::Initialize(const Adaptor3d_SurfaceOfLinearExtrusion& S,
189 const Standard_Real Uinf,
190 const Standard_Real Usup,
191 const Standard_Real Vinf,
192 const Standard_Real Vsup,
193 const Standard_Real TolU,
194 const Standard_Real TolV)
195{
196 myuinf=Uinf;
197 myusup=Usup;
198 mytolu=TolU;
199
200 myvinf=Vinf;
201 myvsup=Vsup;
202 mytolv=TolV;
203
204 Handle(Adaptor3d_HCurve) anACurve = S.BasisCurve();
205
206 myF.Initialize(S);
207 myC = anACurve;
208 myPosition = GetPosition(myC);
209 myDirection = S.Direction();
210 myIsAnalyticallyComputable = //Standard_False;
211 IsCaseAnalyticallyComputable (myC->GetType(),myPosition,myDirection);
212
213 if (!myIsAnalyticallyComputable)
214
215 myExtPS.Initialize(S, 32, 32,
216 Uinf, Usup, Vinf, Vsup,
217 TolU, TolV);
218}
219
220
221//=======================================================================
222//function : Perform
223//purpose :
224//=======================================================================
225
226void Extrema_ExtPExtS::Perform (const gp_Pnt& P)
227{
228 myDone = Standard_False;
229 myNbExt = 0;
230
231 if (!myIsAnalyticallyComputable) {
232 myExtPS.Perform(P);
233 myDone = myExtPS.IsDone();
234// modified by NIZHNY-EAP Wed Nov 17 12:59:08 1999 ___BEGIN___
235 myNbExt = myExtPS.NbExt();
236// modified by NIZHNY-EAP Wed Nov 17 12:59:09 1999 ___END___
237 return;
238 }
239
240 gp_Pnt Pe, Pp = ProjectPnt(myPosition,myDirection,P);
241 Extrema_ExtPElC anExt;
242 PerformExtPElC(anExt, Pp, myC, mytolu);
243 if (!anExt.IsDone()) return;
244
245 gp_Ax2 anOrtogSection (P, myDirection);
246 Standard_Real U,V;
247 Standard_Boolean
248 isMin,
249 isSimpleCase =
250 myDirection.IsParallel(myPosition.Direction(),Precision::Angular());
251 Standard_Integer i, aNbExt = anExt.NbExt();
252 math_Vector UV(1,2), Tol(1,2), UVinf(1,2), UVsup(1,2);
253 Tol(1) = mytolu; Tol(2) = mytolv;
254 UVinf(1) = myuinf; UVinf(2) = myvinf;
255 UVsup(1) = myusup; UVsup(2) = myvsup;
256
257
258 for (i=1; i<=aNbExt; i++) {
259 Extrema_POnCurv POC=anExt.Point(i);
260 U = POC.Parameter();
261 //// modified by jgv, 23.12.2008 for OCC17194 ////
262 if (myC->IsPeriodic())
263 {
264 Standard_Real U2 = U;
c6541a0c 265 ElCLib::AdjustPeriodic(myuinf, myuinf + 2.*M_PI, Precision::PConfusion(), U, U2);
7fd59977 266 }
267 //////////////////////////////////////////////////
268 gp_Pnt E = POC.Value();
269 Pe = ProjectPnt(anOrtogSection, myDirection, E);
270
271 if (isSimpleCase) {
272 V = gp_Vec(E,Pe) * gp_Vec(myDirection);
273 // modified by NIZHNY-MKK Thu Sep 18 14:46:14 2003.BEGIN
274 // myPoint[++myNbExt] = Extrema_POnSurf(U, V, Pe);
275 // myValue[myNbExt] = anExt.Value(i);
276 myPoint[myNbExt] = Extrema_POnSurf(U, V, Pe);
277 mySqDist[myNbExt] = anExt.SquareDistance(i);
278 myNbExt++;
279 // modified by NIZHNY-MKK Thu Sep 18 14:46:18 2003.END
280 }
281 else {
282 myF.SetPoint(P);
283 isMin = anExt.IsMin(i);//( Pp.Distance(GetValue(U+10,myC)) > anExt.Value(i) );
284
285 MakePreciser(U, P, isMin, anOrtogSection);
286 E = GetValue(U, myC);
287 Pe = ProjectPnt (anOrtogSection, myDirection, E),
288 V = gp_Vec(E,Pe) * gp_Vec(myDirection);
289 UV(1) = U; UV(2) = V;
290 math_FunctionSetRoot aFSR (myF,UV,Tol,UVinf,UVsup);
291// for (Standard_Integer k=1 ; k <= myF.NbExt();
292 Standard_Integer k;
293 for ( k=1 ; k <= myF.NbExt(); k++) {
294 if (IsOriginalPnt(myF.Point(k).Value(), myPoint, myNbExt)) {
295 // modified by NIZHNY-MKK Thu Sep 18 14:46:41 2003.BEGIN
296 // myPoint[++myNbExt] = myF.Point(k);
297 // myValue[myNbExt] = myF.Value(k);
298 myPoint[myNbExt] = myF.Point(k);
299 mySqDist[myNbExt] = myF.SquareDistance(k);
300 myNbExt++;
301 // modified by NIZHNY-MKK Thu Sep 18 14:46:43 2003.END
302 }
303 }
304 // try symmetric point
305 U *= -1;
306 MakePreciser(U, P, isMin, anOrtogSection);
307 E = GetValue(U, myC);
308 Pe = ProjectPnt (anOrtogSection, myDirection, E),
309 V = gp_Vec(E,Pe) * gp_Vec(myDirection);
310 UV(1) = U; UV(2) = V;
311
312 aFSR.Perform (myF,UV,UVinf,UVsup);
313
314 for (k=1 ; k <= myF.NbExt(); k++) {
315 if (IsOriginalPnt(myF.Point(k).Value(), myPoint, myNbExt)) {
316 // modified by NIZHNY-MKK Thu Sep 18 14:46:59 2003.BEGIN
317 // myPoint[++myNbExt] = myF.Point(k);
318 // myValue[myNbExt] = myF.Value(k);
319 myPoint[myNbExt] = myF.Point(k);
320 mySqDist[myNbExt] = myF.SquareDistance(k);
321 myNbExt++;
322 // modified by NIZHNY-MKK Thu Sep 18 14:47:04 2003.END
323 }
324 }
325 }
326 }
327 myDone = Standard_True;
328 return;
329}
330
331//=============================================================================
332
333Standard_Boolean Extrema_ExtPExtS::IsDone () const { return myDone; }
334//=============================================================================
335
336Standard_Integer Extrema_ExtPExtS::NbExt () const
337{
338 if (!IsDone()) { StdFail_NotDone::Raise(); }
339 if (myIsAnalyticallyComputable)
340 return myNbExt;
341 else
342 return myExtPS.NbExt();
343}
344//=============================================================================
345
346Standard_Real Extrema_ExtPExtS::SquareDistance (const Standard_Integer N) const
347{
348 if (!IsDone()) { StdFail_NotDone::Raise(); }
349 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
350 if (myIsAnalyticallyComputable)
351 // modified by NIZHNY-MKK Thu Sep 18 14:48:39 2003.BEGIN
352 // return myValue[N];
353 return mySqDist[N-1];
354 // modified by NIZHNY-MKK Thu Sep 18 14:48:42 2003.END
355 else
356 return myExtPS.SquareDistance(N);
357}
358//=============================================================================
359
360Extrema_POnSurf Extrema_ExtPExtS::Point (const Standard_Integer N) const
361{
362 if (!IsDone()) { StdFail_NotDone::Raise(); }
363 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
364 if (myIsAnalyticallyComputable) {
365 // modified by NIZHNY-MKK Thu Sep 18 14:47:40 2003.BEGIN
366 // return myPoint[N];
367 return myPoint[N-1];
368 }
369 // modified by NIZHNY-MKK Thu Sep 18 14:47:43 2003.END
370 else
371 return myExtPS.Point(N);
372}
373//=============================================================================
374
375
376static gp_Ax2 GetPosition (const Handle(Adaptor3d_HCurve)& C)
377{
378 switch (C->GetType()) {
379 case GeomAbs_Line: {
380 gp_Lin L = C->Line();
381 gp_Pln Pln = gp_Pln(L.Location(), L.Direction());
382 //:abv 30.05.02: OCC - use constructor instead of Set...s() to avoid exception
383 gp_Ax2 Pos ( Pln.Location(), Pln.Position().Direction(), Pln.Position().XDirection() );
384// Pos.SetAxis(Pln.XAxis());
385// Pos.SetXDirection(Pln.YAxis().Direction());
386// Pos.SetYDirection(Pln.Position().Direction());
387 return Pos;
388 }
389 case GeomAbs_Circle:
390 return C->Circle().Position();
391 case GeomAbs_Ellipse:
392 return C->Ellipse().Position();
393 case GeomAbs_Hyperbola:
394 return C->Hyperbola().Position();
395 case GeomAbs_Parabola:
396 return C->Parabola().Position();
397 default:
398 return gp_Ax2 ();
399 }
400}
401//=============================================================================
402
403static void PerformExtPElC (Extrema_ExtPElC& E,
404 const gp_Pnt& P,
405 const Handle(Adaptor3d_HCurve)& C,
406 const Standard_Real Tol)
407{
408 switch (C->GetType()) {
409 case GeomAbs_Hyperbola:
410 E.Perform(P, C->Hyperbola(), Tol, -Precision::Infinite(),Precision::Infinite());
411 return;
412 case GeomAbs_Line:
413 E.Perform(P, C->Line(), Tol, -Precision::Infinite(),Precision::Infinite());
414 return;
415 case GeomAbs_Circle:
c6541a0c 416 E.Perform(P, C->Circle(), Tol, 0.0, 2.0 * M_PI);
7fd59977 417 return;
418 case GeomAbs_Ellipse:
c6541a0c 419 E.Perform(P, C->Ellipse(), Tol, 0.0, 2.0 * M_PI);
7fd59977 420 return;
421 case GeomAbs_Parabola:
422 E.Perform(P, C->Parabola(), Tol, -Precision::Infinite(),Precision::Infinite());
423 return;
7fd59977 424 default:
425 return;
7fd59977 426 }
427}
428
429//=======================================================================
430//function : IsCaseAnalyticallyComputable
431//purpose :
432//=======================================================================
433
434static Standard_Boolean IsCaseAnalyticallyComputable
435 (const GeomAbs_CurveType& theType,
436 const gp_Ax2& theCurvePos,
437 const gp_Dir& theSurfaceDirection)
438{
439 // check type
440 switch (theType) {
441 case GeomAbs_Line:
442 case GeomAbs_Circle:
443 case GeomAbs_Ellipse:
444 case GeomAbs_Hyperbola:
445 case GeomAbs_Parabola:
446 break;
447 default:
448 return Standard_False;
449 }
450 // check if it is a plane
451 if (Abs(theCurvePos.Direction() * theSurfaceDirection) <= gp::Resolution())
452 return Standard_False;
453 else
454 return Standard_True;
455}
456//=======================================================================
457//function : GetValue
458//purpose :
459//=======================================================================
460
461static gp_Pnt GetValue(const Standard_Real U,
462 const Handle(Adaptor3d_HCurve)& C)
463{
464 switch (C->GetType()) {
465 case GeomAbs_Line:
466 return ElCLib::Value(U, C->Line());
467 case GeomAbs_Circle:
468 return ElCLib::Value(U, C->Circle());
469 case GeomAbs_Ellipse:
470 return ElCLib::Value(U, C->Ellipse());
471 case GeomAbs_Hyperbola:
472 return ElCLib::Value(U, C->Hyperbola());
473 case GeomAbs_Parabola:
474 return ElCLib::Value(U, C->Parabola());
475 default:
476 return gp_Pnt();
477 }
478}
479//=======================================================================
480//function : GetU
481//purpose :
482//=======================================================================
483//#ifdef DEB
484//static Standard_Real GetU(const gp_Vec& vec,
485// const gp_Pnt& P,
486// const Handle(Adaptor3d_HCurve)& C)
487//{
488// switch (C->GetType()) {
489// case GeomAbs_Line:
490// return ElCLib::Parameter(C->Line().Translated(vec), P);
491// case GeomAbs_Circle:
492// return ElCLib::Parameter(C->Circle().Translated(vec), P);
493// case GeomAbs_Ellipse:
494// return ElCLib::Parameter(C->Ellipse().Translated(vec), P);
495// case GeomAbs_Hyperbola:
496// return ElCLib::Parameter(C->Hyperbola().Translated(vec), P);
497// case GeomAbs_Parabola:
498// return ElCLib::Parameter(C->Parabola().Translated(vec), P);
499// default:
500// return 0;
501// }
502//}
503//#endif