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
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.
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.
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.
22 #include <Standard_NotImplemented.hxx>
23 #include <Standard_OutOfRange.hxx>
24 #include <StdFail_NotDone.hxx>
25 #include <Adaptor3d_HCurve.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>
39 #include <math_FunctionSetRoot.hxx>
40 #include <math_Vector.hxx>
41 #include <Adaptor3d_SurfaceOfLinearExtrusion.hxx>
43 static gp_Ax2 GetPosition (const Handle(Adaptor3d_HCurve)& C);
45 static void PerformExtPElC (Extrema_ExtPElC& E,
47 const Handle(Adaptor3d_HCurve)& C,
48 const Standard_Real Tol);
50 static Standard_Boolean
51 IsCaseAnalyticallyComputable (const GeomAbs_CurveType& theType,
52 const gp_Ax2& theCurvePos,
53 const gp_Dir& theSurfaceDirection) ;
55 static gp_Pnt GetValue(const Standard_Real U,
56 const Handle(Adaptor3d_HCurve)& C);
57 //=======================================================================
59 //purpose : Returns the projection of a point <Point> on a plane
60 // <ThePlane> along a direction <TheDir>.
61 //=======================================================================
62 static gp_Pnt ProjectPnt(const gp_Ax2& ThePlane,
66 gp_Vec PO(Point,ThePlane.Location());
67 Standard_Real Alpha = PO * gp_Vec(ThePlane.Direction());
68 Alpha /= TheDir * ThePlane.Direction();
70 P.SetXYZ(Point.XYZ() + Alpha * TheDir.XYZ());
74 //=======================================================================
75 //function : IsOriginalPnt
77 //=======================================================================
79 static Standard_Boolean IsOriginalPnt (const gp_Pnt& P,
80 const Extrema_POnSurf* Points,
81 const Standard_Integer NbPoints)
83 for (Standard_Integer i=1; i<=NbPoints; i++) {
84 if (Points[i-1].Value().IsEqual(P, Precision::Confusion())) {
85 return Standard_False;
91 //=======================================================================
92 //function : MakePreciser
94 //=======================================================================
96 void Extrema_ExtPExtS::MakePreciser (Standard_Real& U,
98 const Standard_Boolean isMin,
99 const gp_Ax2& OrtogSection) const
103 } else if (U<myuinf) {
107 Standard_Real step = (myusup - myuinf) / 30, D2e, D2next ,D2prev;
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;
117 notFound = (D2e > D2prev || D2e > D2next);
119 notFound = (D2e < D2prev || D2e < D2next);
121 if (notFound && (D2e < D2next && isMin)) {
138 Pnext = ProjectPnt (OrtogSection, myDirection, GetValue(U+step, myC));
139 D2next = P.SquareDistance(Pnext);
141 notFound = D2e > D2next;
143 notFound = D2e < D2next;
147 //=============================================================================
149 Extrema_ExtPExtS::Extrema_ExtPExtS ()
151 myDone = Standard_False;
154 //=============================================================================
156 Extrema_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)
166 Umin, Usup, Vmin, Vsup,
170 //=============================================================================
172 Extrema_ExtPExtS::Extrema_ExtPExtS (const gp_Pnt& P,
173 const Adaptor3d_SurfaceOfLinearExtrusion& S,
174 const Standard_Real TolU,
175 const Standard_Real TolV)
178 S.FirstUParameter(), S.LastUParameter(),
179 S.FirstVParameter(), S.LastVParameter(),
183 //=======================================================================
184 //function : Initialize
186 //=======================================================================
188 void 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)
204 Handle(Adaptor3d_HCurve) anACurve = S.BasisCurve();
208 myPosition = GetPosition(myC);
209 myDirection = S.Direction();
210 myIsAnalyticallyComputable = //Standard_False;
211 IsCaseAnalyticallyComputable (myC->GetType(),myPosition,myDirection);
213 if (!myIsAnalyticallyComputable)
215 myExtPS.Initialize(S, 32, 32,
216 Uinf, Usup, Vinf, Vsup,
221 //=======================================================================
224 //=======================================================================
226 void Extrema_ExtPExtS::Perform (const gp_Pnt& P)
228 myDone = Standard_False;
231 if (!myIsAnalyticallyComputable) {
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___
240 gp_Pnt Pe, Pp = ProjectPnt(myPosition,myDirection,P);
241 Extrema_ExtPElC anExt;
242 PerformExtPElC(anExt, Pp, myC, mytolu);
243 if (!anExt.IsDone()) return;
245 gp_Ax2 anOrtogSection (P, myDirection);
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;
258 for (i=1; i<=aNbExt; i++) {
259 Extrema_POnCurv POC=anExt.Point(i);
261 //// modified by jgv, 23.12.2008 for OCC17194 ////
262 if (myC->IsPeriodic())
264 Standard_Real U2 = U;
265 ElCLib::AdjustPeriodic(myuinf, myuinf + 2.*M_PI, Precision::PConfusion(), U, U2);
267 //////////////////////////////////////////////////
268 gp_Pnt E = POC.Value();
269 Pe = ProjectPnt(anOrtogSection, myDirection, E);
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);
279 // modified by NIZHNY-MKK Thu Sep 18 14:46:18 2003.END
283 isMin = anExt.IsMin(i);//( Pp.Distance(GetValue(U+10,myC)) > anExt.Value(i) );
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();
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);
301 // modified by NIZHNY-MKK Thu Sep 18 14:46:43 2003.END
304 // try symmetric point
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;
312 aFSR.Perform (myF,UV,UVinf,UVsup);
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);
322 // modified by NIZHNY-MKK Thu Sep 18 14:47:04 2003.END
327 myDone = Standard_True;
331 //=============================================================================
333 Standard_Boolean Extrema_ExtPExtS::IsDone () const { return myDone; }
334 //=============================================================================
336 Standard_Integer Extrema_ExtPExtS::NbExt () const
338 if (!IsDone()) { StdFail_NotDone::Raise(); }
339 if (myIsAnalyticallyComputable)
342 return myExtPS.NbExt();
344 //=============================================================================
346 Standard_Real Extrema_ExtPExtS::SquareDistance (const Standard_Integer N) const
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
356 return myExtPS.SquareDistance(N);
358 //=============================================================================
360 Extrema_POnSurf Extrema_ExtPExtS::Point (const Standard_Integer N) const
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];
369 // modified by NIZHNY-MKK Thu Sep 18 14:47:43 2003.END
371 return myExtPS.Point(N);
373 //=============================================================================
376 static gp_Ax2 GetPosition (const Handle(Adaptor3d_HCurve)& C)
378 switch (C->GetType()) {
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());
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();
401 //=============================================================================
403 static void PerformExtPElC (Extrema_ExtPElC& E,
405 const Handle(Adaptor3d_HCurve)& C,
406 const Standard_Real Tol)
408 switch (C->GetType()) {
409 case GeomAbs_Hyperbola:
410 E.Perform(P, C->Hyperbola(), Tol, -Precision::Infinite(),Precision::Infinite());
413 E.Perform(P, C->Line(), Tol, -Precision::Infinite(),Precision::Infinite());
416 E.Perform(P, C->Circle(), Tol, 0.0, 2.0 * M_PI);
418 case GeomAbs_Ellipse:
419 E.Perform(P, C->Ellipse(), Tol, 0.0, 2.0 * M_PI);
421 case GeomAbs_Parabola:
422 E.Perform(P, C->Parabola(), Tol, -Precision::Infinite(),Precision::Infinite());
431 //=======================================================================
432 //function : IsCaseAnalyticallyComputable
434 //=======================================================================
436 static Standard_Boolean IsCaseAnalyticallyComputable
437 (const GeomAbs_CurveType& theType,
438 const gp_Ax2& theCurvePos,
439 const gp_Dir& theSurfaceDirection)
445 case GeomAbs_Ellipse:
446 case GeomAbs_Hyperbola:
447 case GeomAbs_Parabola:
450 return Standard_False;
452 // check if it is a plane
453 if (Abs(theCurvePos.Direction() * theSurfaceDirection) <= gp::Resolution())
454 return Standard_False;
456 return Standard_True;
458 //=======================================================================
459 //function : GetValue
461 //=======================================================================
463 static gp_Pnt GetValue(const Standard_Real U,
464 const Handle(Adaptor3d_HCurve)& C)
466 switch (C->GetType()) {
468 return ElCLib::Value(U, C->Line());
470 return ElCLib::Value(U, C->Circle());
471 case GeomAbs_Ellipse:
472 return ElCLib::Value(U, C->Ellipse());
473 case GeomAbs_Hyperbola:
474 return ElCLib::Value(U, C->Hyperbola());
475 case GeomAbs_Parabola:
476 return ElCLib::Value(U, C->Parabola());
481 //=======================================================================
484 //=======================================================================
486 //static Standard_Real GetU(const gp_Vec& vec,
488 // const Handle(Adaptor3d_HCurve)& C)
490 // switch (C->GetType()) {
491 // case GeomAbs_Line:
492 // return ElCLib::Parameter(C->Line().Translated(vec), P);
493 // case GeomAbs_Circle:
494 // return ElCLib::Parameter(C->Circle().Translated(vec), P);
495 // case GeomAbs_Ellipse:
496 // return ElCLib::Parameter(C->Ellipse().Translated(vec), P);
497 // case GeomAbs_Hyperbola:
498 // return ElCLib::Parameter(C->Hyperbola().Translated(vec), P);
499 // case GeomAbs_Parabola:
500 // return ElCLib::Parameter(C->Parabola().Translated(vec), P);