1 // Created on: 1999-09-21
2 // Created by: Edward AGAPOV
3 // Copyright (c) 1999-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.
23 #include <Extrema_ExtPRevS.ixx>
24 #include <Adaptor3d_HCurve.hxx>
25 #include <Extrema_ExtPElC.hxx>
26 #include <Extrema_GenExtPS.hxx>
27 #include <Extrema_POnCurv.hxx>
28 #include <Extrema_POnSurf.hxx>
34 #include <gp_Trsf.hxx>
36 #include <Precision.hxx>
39 static gp_Ax2 GetPosition (const Adaptor3d_SurfaceOfRevolution& S)//const Handle(Adaptor_HCurve)& C)
41 Handle(Adaptor3d_HCurve) C = S.BasisCurve();
43 switch (C->GetType()) {
47 gp_Dir N = S.AxeOfRevolution().Direction();
48 if (N.IsParallel(L.Direction(), Precision::Angular())) {
49 gp_Vec OO (L.Location(), S.AxeOfRevolution().Location());
50 if (OO.Magnitude() <= gp::Resolution()) {
51 OO = gp_Vec(L.Location(), ElCLib::Value(100,L));
52 if (N.IsParallel(OO, Precision::Angular()))
53 return gp_Ax2(); // Line and axe of revolution coinside
60 return gp_Ax2 (L.Location(), N, L.Direction());
63 return C->Circle().Position();
65 return C->Ellipse().Position();
66 case GeomAbs_Hyperbola:
67 return C->Hyperbola().Position();
68 case GeomAbs_Parabola:
69 return C->Parabola().Position();
75 //=======================================================================
76 //function : HasSingularity
78 //=======================================================================
80 static Standard_Boolean HasSingularity(const Adaptor3d_SurfaceOfRevolution& S)
83 const Handle(Adaptor3d_HCurve) C = S.BasisCurve();
84 gp_Dir N = S.AxeOfRevolution().Direction();
85 gp_Pnt P = S.AxeOfRevolution().Location();
89 P = C->Value(C->FirstParameter());
91 if(L.SquareDistance(P) < Precision::Confusion() * Precision::Confusion()) return Standard_True;
93 P = C->Value(C->LastParameter());
95 if(L.SquareDistance(P) < Precision::Confusion() * Precision::Confusion()) return Standard_True;
97 return Standard_False;
100 //=============================================================================
102 static void PerformExtPElC (Extrema_ExtPElC& E,
104 const Handle(Adaptor3d_HCurve)& C,
105 const Standard_Real Tol)
107 switch (C->GetType()) {
108 case GeomAbs_Hyperbola:
109 E.Perform(P, C->Hyperbola(), Tol, -Precision::Infinite(),Precision::Infinite());
112 E.Perform(P, C->Line(), Tol, -Precision::Infinite(),Precision::Infinite());
115 E.Perform(P, C->Circle(), Tol, 0.0, 2.0 * M_PI);
117 case GeomAbs_Ellipse:
118 E.Perform(P, C->Ellipse(), Tol, 0.0, 2.0 * M_PI);
120 case GeomAbs_Parabola:
121 E.Perform(P, C->Parabola(), Tol, -Precision::Infinite(),Precision::Infinite());
130 //=======================================================================
131 //function : IsCaseAnalyticallyComputable
133 //=======================================================================
135 static Standard_Boolean IsCaseAnalyticallyComputable
136 (const GeomAbs_CurveType& theType,
137 const gp_Ax2& theCurvePos,
138 const gp_Ax1& AxeOfRevolution)
144 case GeomAbs_Ellipse:
145 case GeomAbs_Hyperbola:
146 case GeomAbs_Parabola:
149 return Standard_False;
151 // the axe of revolution must be in the plane of the curve.
152 gp_Pln pl(theCurvePos.Location(), theCurvePos.Direction());
153 gp_Pnt p1 = AxeOfRevolution.Location();
154 Standard_Real dist = 100., dist2 = dist * dist;
155 Standard_Real aThreshold = Precision::Angular() * Precision::Angular() * dist2;
156 gp_Pnt p2 = AxeOfRevolution.Location().XYZ() + dist * AxeOfRevolution.Direction().XYZ();
158 if((pl.SquareDistance(p1) < aThreshold) &&
159 (pl.SquareDistance(p2) < aThreshold))
160 return Standard_True;
161 return Standard_False;
162 // gp_Vec V (AxeOfRevolution.Location(),theCurvePos.Location());
163 // if (Abs( V * theCurvePos.Direction()) <= gp::Resolution())
164 // return Standard_True;
166 // return Standard_False;
169 //=======================================================================
170 //function : IsOriginalPnt
172 //=======================================================================
174 static Standard_Boolean IsOriginalPnt (const gp_Pnt& P,
175 const Extrema_POnSurf* Points,
176 const Standard_Integer NbPoints)
178 for (Standard_Integer i=1; i<=NbPoints; i++) {
179 if (Points[i].Value().IsEqual(P, Precision::Confusion())) {
180 return Standard_False;
183 return Standard_True;
185 //=======================================================================
186 //function : IsExtremum
188 //=======================================================================
190 static Standard_Boolean IsExtremum (const Standard_Real U, const Standard_Real V,
191 const gp_Pnt& P, const Adaptor3d_SurfacePtr& S,
192 gp_Pnt& E, Standard_Real& Dist2,
193 const Standard_Boolean IsVSup,
194 const Standard_Boolean IsMin)
197 Dist2 = P.SquareDistance(E);
199 return (Dist2 < P.SquareDistance(S->Value(U+1,V)) &&
200 Dist2 < P.SquareDistance(S->Value(U-1,V)) &&
201 Dist2 < P.SquareDistance(S->Value(U, IsVSup ? V-1 : V+1)));
203 return (Dist2 > P.SquareDistance(S->Value(U+1,V)) &&
204 Dist2 > P.SquareDistance(S->Value(U-1,V)) &&
205 Dist2 > P.SquareDistance(S->Value(U, IsVSup ? V-1 : V+1)));
207 //=======================================================================
208 //function : Extrema_ExtPRevS
210 //=======================================================================
212 Extrema_ExtPRevS::Extrema_ExtPRevS()
215 myDone = Standard_False;
217 //=======================================================================
218 //function : Extrema_ExtPRevS
220 //=======================================================================
222 Extrema_ExtPRevS::Extrema_ExtPRevS(const gp_Pnt& P,
223 const Adaptor3d_SurfaceOfRevolution& S,
224 const Standard_Real Umin,
225 const Standard_Real Usup,
226 const Standard_Real Vmin,
227 const Standard_Real Vsup,
228 const Standard_Real TolU,
229 const Standard_Real TolV)
233 Umin, Usup, Vmin, Vsup,
237 //=======================================================================
238 //function : Extrema_ExtPRevS
240 //=======================================================================
242 Extrema_ExtPRevS::Extrema_ExtPRevS(const gp_Pnt& P,
243 const Adaptor3d_SurfaceOfRevolution& S,
244 const Standard_Real TolU,
245 const Standard_Real TolV)
249 S.FirstUParameter(), S.LastUParameter(),
250 S.FirstVParameter(), S.LastVParameter(),
254 //=======================================================================
255 //function : Initialize
257 //=======================================================================
259 void Extrema_ExtPRevS::Initialize(const Adaptor3d_SurfaceOfRevolution& S,
260 const Standard_Real Umin,
261 const Standard_Real Usup,
262 const Standard_Real Vmin,
263 const Standard_Real Vsup,
264 const Standard_Real TolU,
265 const Standard_Real TolV)
271 Handle(Adaptor3d_HCurve) anACurve = S.BasisCurve();
272 if (!myS || myS != (Adaptor3d_SurfacePtr)&S) {
273 myS = Adaptor3d_SurfacePtr(&S);
274 myPosition = GetPosition(S);
275 myIsAnalyticallyComputable =
276 IsCaseAnalyticallyComputable (anACurve->GetType(),myPosition,S.AxeOfRevolution());
278 if (!myIsAnalyticallyComputable) {
280 Standard_Integer nbu = 32, nbv = 32;
282 if(HasSingularity(S)) {nbv = 100;}
284 myExtPS.Initialize(S, nbu, nbv,
285 Umin, Usup, Vmin, Vsup,
289 //=======================================================================
292 //=======================================================================
294 void Extrema_ExtPRevS::Perform(const gp_Pnt& P)
296 myDone = Standard_False;
299 if (!myIsAnalyticallyComputable) {
302 myDone = myExtPS.IsDone();
303 myNbExt = myExtPS.NbExt();
307 Handle(Adaptor3d_HCurve) anACurve = myS->BasisCurve();
309 gp_Ax1 Ax = myS->AxeOfRevolution();
310 gp_Vec Dir = Ax.Direction(), Z = myPosition.Direction();
311 gp_Pnt O = Ax.Location();
313 Standard_Real OPdir = gp_Vec(O,P).Dot(Dir);
314 gp_Pnt Pp = P.Translated(Dir.Multiplied(-OPdir));
315 if (O.IsEqual(Pp,Precision::Confusion())) // P is on the AxeOfRevolution
320 Standard_Real OPpz = gp_Vec(O,Pp).Dot(Z);
321 if (Abs(OPpz) <= gp::Resolution()) {
326 Ppp = Pp.Translated(Z.Multiplied(-OPpz));
327 if (O.IsEqual(Ppp,Precision::Confusion()))
330 U = gp_Vec(O,Ppp).AngleWithRef(gp_Vec(O,Pp),Dir);
334 gp_Vec OPpp (O,Ppp), OPq (O, myS->Value(M_PI/2,0));
336 if (Abs(OPq.Magnitude()) <= gp::Resolution())
337 OPq = gp_Vec(O, myS->Value(M_PI/2,anACurve->LastParameter()/10));
338 if (OPpp.AngleWithRef(OPq,Dir) < 0)
343 T.SetRotation(Ax, -U);
344 P1 = P.Transformed(T);
350 Extrema_ExtPElC anExt;
351 PerformExtPElC(anExt, P1, anACurve, mytolv);
353 if (anExt.IsDone()) {
354 myDone = Standard_True;
355 for (i=1; i<=anExt.NbExt(); i++) {
356 Extrema_POnCurv POC=anExt.Point(i);
359 // if ( !IsExtremum (U, V = myvsup, P, myS, E, Dist2,
360 // Standard_True, anExt.IsMin(i))) continue;
361 Standard_Real newV = myvsup;
363 if((anACurve->GetType() == GeomAbs_Circle) ||
364 (anACurve->GetType() == GeomAbs_Ellipse)) {
365 newV = ElCLib::InPeriod(V, myvinf, myvinf + 2. * M_PI);
373 if ( !IsExtremum (U, V, P, myS, E, Dist2,
374 Standard_True, anExt.IsMin(i))) {
377 } else if (V < myvinf) {
378 // if ( !IsExtremum (U, V = myvinf, P, myS, E, Dist2,
379 // Standard_False, anExt.IsMin(i))) continue;
381 Standard_Real newV = myvinf;
383 if((anACurve->GetType() == GeomAbs_Circle) ||
384 (anACurve->GetType() == GeomAbs_Ellipse)) {
385 newV = ElCLib::InPeriod(V, myvsup - 2. * M_PI, myvsup);
392 if ( !IsExtremum (U, V, P, myS, E, Dist2,
393 Standard_False, anExt.IsMin(i))) continue;
396 Dist2 = P.SquareDistance(E);
398 if (IsOriginalPnt(E, myPoint, myNbExt)) {
399 myPoint[++myNbExt] = Extrema_POnSurf(U,V,E);
400 mySqDist[myNbExt] = Dist2;
404 T.SetRotation(Ax, M_PI);
407 PerformExtPElC(anExt, P1, anACurve, mytolv);
408 if (anExt.IsDone()) {
409 myDone = Standard_True;
413 for (i=1; i<=anExt.NbExt(); i++) {
414 Extrema_POnCurv POC=anExt.Point(i);
417 // if ( !IsExtremum (U, V = myvsup, P, myS, E, Dist2,
418 // Standard_True, anExt.IsMin(i))) continue;
420 Standard_Real newV = myvsup;
422 if((anACurve->GetType() == GeomAbs_Circle) ||
423 (anACurve->GetType() == GeomAbs_Ellipse)) {
424 newV = ElCLib::InPeriod(V, myvinf, myvinf + 2. * M_PI);
432 if ( !IsExtremum (U, V, P, myS, E, Dist2,
433 Standard_True, anExt.IsMin(i))) continue;
434 } else if (V < myvinf) {
435 // if ( !IsExtremum (U, V = myvinf, P, myS, E, Dist2,
436 // Standard_False, anExt.IsMin(i))) continue;
437 Standard_Real newV = myvinf;
439 if((anACurve->GetType() == GeomAbs_Circle) ||
440 (anACurve->GetType() == GeomAbs_Ellipse)) {
441 newV = ElCLib::InPeriod(V, myvsup - 2. * M_PI, myvsup);
448 if ( !IsExtremum (U, V, P, myS, E, Dist2,
449 Standard_False, anExt.IsMin(i))) continue;
452 Dist2 = P.SquareDistance(E);
454 if (IsOriginalPnt(E, myPoint, myNbExt)) {
455 myPoint[++myNbExt] = Extrema_POnSurf(U,V,E);
456 mySqDist[myNbExt] = Dist2;
464 //=======================================================================
467 //=======================================================================
469 Standard_Boolean Extrema_ExtPRevS::IsDone() const
475 //=======================================================================
478 //=======================================================================
480 Standard_Integer Extrema_ExtPRevS::NbExt() const
482 if (!IsDone()) { StdFail_NotDone::Raise(); }
487 //=======================================================================
490 //=======================================================================
492 Standard_Real Extrema_ExtPRevS::SquareDistance(const Standard_Integer N) const
494 if (!IsDone()) { StdFail_NotDone::Raise(); }
495 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
496 if (myIsAnalyticallyComputable)
499 return myExtPS.SquareDistance(N);
501 //=======================================================================
504 //=======================================================================
506 Extrema_POnSurf Extrema_ExtPRevS::Point(const Standard_Integer N) const
508 if (!IsDone()) { StdFail_NotDone::Raise(); }
509 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
510 if (myIsAnalyticallyComputable)
513 return myExtPS.Point(N);