1 // Created on: 1999-09-16
2 // Created by: Edward AGAPOV
3 // Copyright (c) 1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <Standard_NotImplemented.hxx>
18 #include <Standard_OutOfRange.hxx>
19 #include <StdFail_NotDone.hxx>
20 #include <Adaptor3d_HCurve.hxx>
22 #include <Extrema_ExtPElC.hxx>
23 #include <Extrema_ExtPExtS.hxx>
24 #include <Extrema_POnCurv.hxx>
25 #include <Extrema_POnSurf.hxx>
26 #include <Precision.hxx>
34 #include <math_FunctionSetRoot.hxx>
35 #include <math_Vector.hxx>
36 #include <Adaptor3d_HSurfaceOfLinearExtrusion.hxx>
39 static gp_Ax2 GetPosition (const Handle(Adaptor3d_HCurve)& C);
41 static void PerformExtPElC (Extrema_ExtPElC& E,
43 const Handle(Adaptor3d_HCurve)& C,
44 const Standard_Real Tol);
46 static Standard_Boolean
47 IsCaseAnalyticallyComputable (const GeomAbs_CurveType& theType,
48 const gp_Ax2& theCurvePos,
49 const gp_Dir& theSurfaceDirection) ;
51 static gp_Pnt GetValue(const Standard_Real U,
52 const Handle(Adaptor3d_HCurve)& C);
53 //=======================================================================
55 //purpose : Returns the projection of a point <Point> on a plane
56 // <ThePlane> along a direction <TheDir>.
57 //=======================================================================
58 static gp_Pnt ProjectPnt(const gp_Ax2& ThePlane,
62 gp_Vec PO(Point,ThePlane.Location());
63 Standard_Real Alpha = PO * gp_Vec(ThePlane.Direction());
64 Alpha /= TheDir * ThePlane.Direction();
66 P.SetXYZ(Point.XYZ() + Alpha * TheDir.XYZ());
70 //=======================================================================
71 //function : IsOriginalPnt
73 //=======================================================================
75 static Standard_Boolean IsOriginalPnt (const gp_Pnt& P,
76 const Extrema_POnSurf* Points,
77 const Standard_Integer NbPoints)
79 for (Standard_Integer i=1; i<=NbPoints; i++) {
80 if (Points[i-1].Value().IsEqual(P, Precision::Confusion())) {
81 return Standard_False;
87 //=======================================================================
88 //function : MakePreciser
90 //=======================================================================
92 void Extrema_ExtPExtS::MakePreciser (Standard_Real& U,
94 const Standard_Boolean isMin,
95 const gp_Ax2& OrtogSection) const
99 } else if (U<myuinf) {
103 Standard_Real step = (myusup - myuinf) / 30, D2e, D2next ,D2prev;
105 Pe = ProjectPnt (OrtogSection, myDirection, GetValue(U,myC)),
106 Pprev = ProjectPnt (OrtogSection, myDirection, GetValue(U-step, myC)),
107 Pnext = ProjectPnt (OrtogSection, myDirection, GetValue(U+step, myC));
108 D2e = P.SquareDistance(Pe),
109 D2next = P.SquareDistance(Pnext),
110 D2prev = P.SquareDistance(Pprev);
111 Standard_Boolean notFound;
113 notFound = (D2e > D2prev || D2e > D2next);
115 notFound = (D2e < D2prev || D2e < D2next);
117 if (notFound && (D2e < D2next && isMin)) {
134 Pnext = ProjectPnt (OrtogSection, myDirection, GetValue(U+step, myC));
135 D2next = P.SquareDistance(Pnext);
137 notFound = D2e > D2next;
139 notFound = D2e < D2next;
143 //=============================================================================
145 Extrema_ExtPExtS::Extrema_ExtPExtS()
152 myIsAnalyticallyComputable(Standard_False),
153 myDone(Standard_False),
154 myNbExt(Standard_False)
158 //=============================================================================
160 Extrema_ExtPExtS::Extrema_ExtPExtS (const gp_Pnt& theP,
161 const Handle(Adaptor3d_HSurfaceOfLinearExtrusion)& theS,
162 const Standard_Real theUmin,
163 const Standard_Real theUsup,
164 const Standard_Real theVmin,
165 const Standard_Real theVsup,
166 const Standard_Real theTolU,
167 const Standard_Real theTolV)
175 myIsAnalyticallyComputable(Standard_False),
176 myDone(Standard_False),
177 myNbExt(Standard_False)
189 //=============================================================================
191 Extrema_ExtPExtS::Extrema_ExtPExtS (const gp_Pnt& theP,
192 const Handle(Adaptor3d_HSurfaceOfLinearExtrusion)& theS,
193 const Standard_Real theTolU,
194 const Standard_Real theTolV)
195 : myuinf(theS->FirstUParameter()),
196 myusup(theS->LastUParameter()),
198 myvinf(theS->FirstVParameter()),
199 myvsup(theS->LastVParameter()),
202 myIsAnalyticallyComputable(Standard_False),
203 myDone(Standard_False),
204 myNbExt(Standard_False)
207 theS->FirstUParameter(),
208 theS->LastUParameter(),
209 theS->FirstVParameter(),
210 theS->LastVParameter(),
217 //=======================================================================
218 //function : Initialize
220 //=======================================================================
222 void Extrema_ExtPExtS::Initialize (const Handle(Adaptor3d_HSurfaceOfLinearExtrusion)& theS,
223 const Standard_Real theUinf,
224 const Standard_Real theUsup,
225 const Standard_Real theVinf,
226 const Standard_Real theVsup,
227 const Standard_Real theTolU,
228 const Standard_Real theTolV)
238 Handle(Adaptor3d_HCurve) anACurve = theS->BasisCurve();
240 myF.Initialize (theS->ChangeSurface());
243 myPosition = GetPosition(myC);
244 myDirection = theS->Direction();
245 myIsAnalyticallyComputable = //Standard_False;
246 IsCaseAnalyticallyComputable (myC->GetType(), myPosition, myDirection);
248 if (!myIsAnalyticallyComputable)
250 myExtPS.Initialize (theS->ChangeSurface(),
263 //=======================================================================
266 //=======================================================================
268 void Extrema_ExtPExtS::Perform (const gp_Pnt& P)
270 const Standard_Integer NbExtMax = 4; //dimension of arrays
271 //myPoint[] and mySqDist[]
272 //For "analytical" case
273 myDone = Standard_False;
276 if (!myIsAnalyticallyComputable) {
278 myDone = myExtPS.IsDone();
279 // modified by NIZHNY-EAP Wed Nov 17 12:59:08 1999 ___BEGIN___
280 myNbExt = myExtPS.NbExt();
281 // modified by NIZHNY-EAP Wed Nov 17 12:59:09 1999 ___END___
285 gp_Pnt Pe, Pp = ProjectPnt(myPosition,myDirection,P);
286 Extrema_ExtPElC anExt;
287 PerformExtPElC(anExt, Pp, myC, mytolu);
288 if (!anExt.IsDone()) return;
290 gp_Ax2 anOrtogSection (P, myDirection);
295 myDirection.IsParallel(myPosition.Direction(),Precision::Angular());
296 Standard_Integer i, aNbExt = anExt.NbExt();
297 math_Vector UV(1,2), Tol(1,2), UVinf(1,2), UVsup(1,2);
298 Tol(1) = mytolu; Tol(2) = mytolv;
299 UVinf(1) = myuinf; UVinf(2) = myvinf;
300 UVsup(1) = myusup; UVsup(2) = myvsup;
303 for (i=1; i<=aNbExt; i++) {
304 Extrema_POnCurv POC=anExt.Point(i);
306 //// modified by jgv, 23.12.2008 for OCC17194 ////
307 if (myC->IsPeriodic())
309 Standard_Real U2 = U;
310 ElCLib::AdjustPeriodic(myuinf, myuinf + 2.*M_PI, Precision::PConfusion(), U, U2);
312 //////////////////////////////////////////////////
313 gp_Pnt E = POC.Value();
314 Pe = ProjectPnt(anOrtogSection, myDirection, E);
317 V = gp_Vec(E,Pe) * gp_Vec(myDirection);
318 // modified by NIZHNY-MKK Thu Sep 18 14:46:14 2003.BEGIN
319 // myPoint[++myNbExt] = Extrema_POnSurf(U, V, Pe);
320 // myValue[myNbExt] = anExt.Value(i);
321 myPoint[myNbExt] = Extrema_POnSurf(U, V, Pe);
322 mySqDist[myNbExt] = anExt.SquareDistance(i);
324 if(myNbExt == NbExtMax)
328 // modified by NIZHNY-MKK Thu Sep 18 14:46:18 2003.END
332 isMin = anExt.IsMin(i);//( Pp.Distance(GetValue(U+10,myC)) > anExt.Value(i) );
334 MakePreciser(U, P, isMin, anOrtogSection);
335 E = GetValue(U, myC);
336 Pe = ProjectPnt (anOrtogSection, myDirection, E),
337 V = gp_Vec(E,Pe) * gp_Vec(myDirection);
338 UV(1) = U; UV(2) = V;
339 math_FunctionSetRoot aFSR (myF, Tol);
340 aFSR.Perform(myF, UV, UVinf, UVsup);
341 // for (Standard_Integer k=1 ; k <= myF.NbExt();
343 for ( k=1 ; k <= myF.NbExt(); k++) {
344 if (IsOriginalPnt(myF.Point(k).Value(), myPoint, myNbExt)) {
345 // modified by NIZHNY-MKK Thu Sep 18 14:46:41 2003.BEGIN
346 // myPoint[++myNbExt] = myF.Point(k);
347 // myValue[myNbExt] = myF.Value(k);
348 myPoint[myNbExt] = myF.Point(k);
349 mySqDist[myNbExt] = myF.SquareDistance(k);
351 if(myNbExt == NbExtMax)
355 // modified by NIZHNY-MKK Thu Sep 18 14:46:43 2003.END
358 if(myNbExt == NbExtMax)
362 // try symmetric point
363 myF.SetPoint(P); //To clear previous solutions
365 MakePreciser(U, P, isMin, anOrtogSection);
366 E = GetValue(U, myC);
367 Pe = ProjectPnt (anOrtogSection, myDirection, E),
368 V = gp_Vec(E,Pe) * gp_Vec(myDirection);
369 UV(1) = U; UV(2) = V;
371 aFSR.Perform (myF,UV,UVinf,UVsup);
373 for (k=1 ; k <= myF.NbExt(); k++) {
374 if(myF.SquareDistance(k) > Precision::Confusion()*Precision::Confusion())
376 //Additional checking solution: FSR sometimes is wrong
377 //when starting point is far from solution.
378 Standard_Real dist = Sqrt(myF.SquareDistance(k));
379 math_Vector Vals(1, 2);
380 const Extrema_POnSurf& PonS=myF.Point(k);
382 PonS.Parameter(u, v);
387 myS->D1(u, v, Pe, du, dv);
388 Standard_Real mdu = du.Magnitude();
389 Standard_Real mdv = dv.Magnitude();
392 if(mdu > Precision::PConfusion())
394 if(u / dist / mdu > Precision::PConfusion())
399 if(mdv > Precision::PConfusion())
401 if(v / dist / mdv > Precision::PConfusion())
408 if (IsOriginalPnt(myF.Point(k).Value(), myPoint, myNbExt)) {
409 // modified by NIZHNY-MKK Thu Sep 18 14:46:59 2003.BEGIN
410 // myPoint[++myNbExt] = myF.Point(k);
411 // myValue[myNbExt] = myF.Value(k);
412 myPoint[myNbExt] = myF.Point(k);
413 mySqDist[myNbExt] = myF.SquareDistance(k);
415 if(myNbExt == NbExtMax)
419 // modified by NIZHNY-MKK Thu Sep 18 14:47:04 2003.END
422 if(myNbExt == NbExtMax)
428 myDone = Standard_True;
432 //=============================================================================
434 Standard_Boolean Extrema_ExtPExtS::IsDone () const { return myDone; }
435 //=============================================================================
437 Standard_Integer Extrema_ExtPExtS::NbExt () const
439 if (!IsDone()) { StdFail_NotDone::Raise(); }
440 if (myIsAnalyticallyComputable)
443 return myExtPS.NbExt();
445 //=============================================================================
447 Standard_Real Extrema_ExtPExtS::SquareDistance (const Standard_Integer N) const
449 if (!IsDone()) { StdFail_NotDone::Raise(); }
450 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
451 if (myIsAnalyticallyComputable)
452 // modified by NIZHNY-MKK Thu Sep 18 14:48:39 2003.BEGIN
453 // return myValue[N];
454 return mySqDist[N-1];
455 // modified by NIZHNY-MKK Thu Sep 18 14:48:42 2003.END
457 return myExtPS.SquareDistance(N);
459 //=============================================================================
461 const Extrema_POnSurf& Extrema_ExtPExtS::Point (const Standard_Integer N) const
463 if (!IsDone()) { StdFail_NotDone::Raise(); }
464 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
465 if (myIsAnalyticallyComputable) {
466 // modified by NIZHNY-MKK Thu Sep 18 14:47:40 2003.BEGIN
467 // return myPoint[N];
470 // modified by NIZHNY-MKK Thu Sep 18 14:47:43 2003.END
472 return myExtPS.Point(N);
474 //=============================================================================
477 static gp_Ax2 GetPosition (const Handle(Adaptor3d_HCurve)& C)
479 switch (C->GetType()) {
481 gp_Lin L = C->Line();
482 gp_Pln Pln = gp_Pln(L.Location(), L.Direction());
483 //:abv 30.05.02: OCC - use constructor instead of Set...s() to avoid exception
484 gp_Ax2 Pos ( Pln.Location(), Pln.Position().Direction(), Pln.Position().XDirection() );
485 // Pos.SetAxis(Pln.XAxis());
486 // Pos.SetXDirection(Pln.YAxis().Direction());
487 // Pos.SetYDirection(Pln.Position().Direction());
491 return C->Circle().Position();
492 case GeomAbs_Ellipse:
493 return C->Ellipse().Position();
494 case GeomAbs_Hyperbola:
495 return C->Hyperbola().Position();
496 case GeomAbs_Parabola:
497 return C->Parabola().Position();
502 //=============================================================================
504 static void PerformExtPElC (Extrema_ExtPElC& E,
506 const Handle(Adaptor3d_HCurve)& C,
507 const Standard_Real Tol)
509 switch (C->GetType()) {
510 case GeomAbs_Hyperbola:
511 E.Perform(P, C->Hyperbola(), Tol, -Precision::Infinite(),Precision::Infinite());
514 E.Perform(P, C->Line(), Tol, -Precision::Infinite(),Precision::Infinite());
517 E.Perform(P, C->Circle(), Tol, 0.0, 2.0 * M_PI);
519 case GeomAbs_Ellipse:
520 E.Perform(P, C->Ellipse(), Tol, 0.0, 2.0 * M_PI);
522 case GeomAbs_Parabola:
523 E.Perform(P, C->Parabola(), Tol, -Precision::Infinite(),Precision::Infinite());
530 //=======================================================================
531 //function : IsCaseAnalyticallyComputable
533 //=======================================================================
535 static Standard_Boolean IsCaseAnalyticallyComputable
536 (const GeomAbs_CurveType& theType,
537 const gp_Ax2& theCurvePos,
538 const gp_Dir& theSurfaceDirection)
544 case GeomAbs_Ellipse:
545 case GeomAbs_Hyperbola:
546 case GeomAbs_Parabola:
549 return Standard_False;
551 // check if it is a plane
552 if (Abs(theCurvePos.Direction() * theSurfaceDirection) <= gp::Resolution())
553 return Standard_False;
555 return Standard_True;
557 //=======================================================================
558 //function : GetValue
560 //=======================================================================
562 static gp_Pnt GetValue(const Standard_Real U,
563 const Handle(Adaptor3d_HCurve)& C)
565 switch (C->GetType()) {
567 return ElCLib::Value(U, C->Line());
569 return ElCLib::Value(U, C->Circle());
570 case GeomAbs_Ellipse:
571 return ElCLib::Value(U, C->Ellipse());
572 case GeomAbs_Hyperbola:
573 return ElCLib::Value(U, C->Hyperbola());
574 case GeomAbs_Parabola:
575 return ElCLib::Value(U, C->Parabola());
580 //=======================================================================
583 //=======================================================================
585 //static Standard_Real GetU(const gp_Vec& vec,
587 // const Handle(Adaptor3d_HCurve)& C)
589 // switch (C->GetType()) {
590 // case GeomAbs_Line:
591 // return ElCLib::Parameter(C->Line().Translated(vec), P);
592 // case GeomAbs_Circle:
593 // return ElCLib::Parameter(C->Circle().Translated(vec), P);
594 // case GeomAbs_Ellipse:
595 // return ElCLib::Parameter(C->Ellipse().Translated(vec), P);
596 // case GeomAbs_Hyperbola:
597 // return ElCLib::Parameter(C->Hyperbola().Translated(vec), P);
598 // case GeomAbs_Parabola:
599 // return ElCLib::Parameter(C->Parabola().Translated(vec), P);