1 // Created on: 1995-07-18
2 // Created by: Modelistation
3 // Copyright (c) 1995-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 // Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134
19 #include <Adaptor3d_Curve.hxx>
20 #include <Adaptor3d_Surface.hxx>
21 #include <Bnd_Box.hxx>
22 #include <BndLib_AddSurface.hxx>
25 #include <Extrema_ExtCS.hxx>
26 #include <Extrema_ExtPS.hxx>
27 #include <Extrema_GenExtCS.hxx>
28 #include <Extrema_POnCurv.hxx>
29 #include <Extrema_POnSurf.hxx>
30 #include <GeomAbs_CurveType.hxx>
31 #include <gp_Cone.hxx>
32 #include <gp_Cylinder.hxx>
36 #include <gp_Sphere.hxx>
37 #include <gp_Torus.hxx>
38 #include <Precision.hxx>
39 #include <Standard_OutOfRange.hxx>
40 #include <StdFail_NotDone.hxx>
41 #include <TColStd_Array1OfReal.hxx>
42 #include <Extrema_ExtPS.hxx>
44 Extrema_ExtCS::Extrema_ExtCS()
46 myDone = Standard_False;
49 Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve& C,
50 const Adaptor3d_Surface& S,
51 const Standard_Real TolC,
52 const Standard_Real TolS)
55 Initialize(S, S.FirstUParameter(), S.LastUParameter(),
56 S.FirstVParameter(), S.LastVParameter(),
58 Perform(C, C.FirstParameter(), C.LastParameter());
61 Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve& C,
62 const Adaptor3d_Surface& S,
63 const Standard_Real UCinf,
64 const Standard_Real UCsup,
65 const Standard_Real Uinf,
66 const Standard_Real Usup,
67 const Standard_Real Vinf,
68 const Standard_Real Vsup,
69 const Standard_Real TolC,
70 const Standard_Real TolS)
73 Initialize(S, Uinf, Usup, Vinf, Vsup, TolC, TolS);
74 Perform(C, UCinf, UCsup);
78 void Extrema_ExtCS::Initialize(const Adaptor3d_Surface& S,
79 const Standard_Real Uinf,
80 const Standard_Real Usup,
81 const Standard_Real Vinf,
82 const Standard_Real Vsup,
83 const Standard_Real TolC,
84 const Standard_Real TolS)
86 myS = (Adaptor3d_SurfacePtr)&S;
87 myIsPar = Standard_False;
94 myStype = myS->GetType();
98 void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C,
99 const Standard_Real Uinf,
100 const Standard_Real Usup)
107 Standard_Integer i, j;
108 Standard_Integer NbT, NbU, NbV;
109 NbT = 12; NbU = NbV = 10;
110 GeomAbs_CurveType myCtype = C.GetType();
112 myDone = Standard_False;
113 // Try analytic computation of extrema
114 Standard_Boolean isComputeAnalytic = Standard_True;
123 myExtElCS.Perform(C.Line(), myS->Sphere());
125 case GeomAbs_Cylinder:
126 myExtElCS.Perform(C.Line(), myS->Cylinder());
129 myExtElCS.Perform(C.Line(), myS->Plane());
130 if (myExtElCS.IsParallel()) break;
135 case GeomAbs_BezierSurface:
136 case GeomAbs_BSplineSurface:
137 case GeomAbs_SurfaceOfRevolution:
138 case GeomAbs_SurfaceOfExtrusion:
139 case GeomAbs_OffsetSurface:
140 case GeomAbs_OtherSurface:
142 Standard_Real cfirst = myucinf, clast = myucsup;
143 Standard_Real ufirst = myS->FirstUParameter(), ulast = myS->LastUParameter(),
144 vfirst = myS->FirstVParameter(), vlast = myS->LastVParameter();
146 if (!(Precision::IsInfinite(ufirst) || Precision::IsInfinite(ulast) ||
147 Precision::IsInfinite(vfirst) || Precision::IsInfinite(vlast)))
149 Standard_Real tmin = Precision::Infinite(), tmax = -tmin;
150 Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
152 BndLib_AddSurface::Add(*myS, ufirst, ulast, vfirst, vlast, Precision::Confusion(), aSurfBox);
153 aSurfBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
154 gp_Lin aLin = C.Line();
155 Standard_Real aParOnLin;
156 gp_Pnt aLimPntArray[8];
158 aLimPntArray[0].SetCoord(xmin, ymin, zmin);
159 aLimPntArray[1].SetCoord(xmax, ymin, zmin);
160 aLimPntArray[2].SetCoord(xmin, ymax, zmin);
161 aLimPntArray[3].SetCoord(xmax, ymax, zmin);
162 aLimPntArray[4].SetCoord(xmin, ymin, zmax);
163 aLimPntArray[5].SetCoord(xmax, ymin, zmax);
164 aLimPntArray[6].SetCoord(xmin, ymax, zmax);
165 aLimPntArray[7].SetCoord(xmax, ymax, zmax);
167 for (i = 0; i <= 7; i++) {
168 aParOnLin = ElCLib::Parameter(aLin, aLimPntArray[i]);
169 tmin = Min(aParOnLin, tmin);
170 tmax = Max(aParOnLin, tmax);
172 cfirst = Max(cfirst, tmin);
173 clast = Min(clast, tmax);
176 if (myS->IsUPeriodic())
178 if (myS->IsVPeriodic())
181 if (clast - cfirst <= Precision::Confusion())
183 Standard_Real aCPar = (cfirst + clast) / 2.;
184 gp_Pnt aPm = C.Value(aCPar);
185 Extrema_ExtPS anExtPS(aPm, *myS, ufirst, ulast,
186 vfirst, vlast, mytolS, mytolS, Extrema_ExtFlag_MIN);
187 myDone = anExtPS.IsDone();
189 Standard_Integer NbExt = anExtPS.NbExt();
190 Standard_Real T = aCPar, U, V;
193 for (i = 1; i <= NbExt; i++) {
194 PS = anExtPS.Point(i);
196 AddSolution(C, T, U, V, PC.Value(), PS.Value(), anExtPS.SquareDistance(i));
202 Extrema_GenExtCS Ext(C, *myS, NbT, NbU, NbV, cfirst, clast, ufirst, ulast,
203 vfirst, vlast, mytolC, mytolS);
205 myDone = Ext.IsDone();
207 Standard_Integer NbExt = Ext.NbExt();
211 for (i = 1; i <= NbExt; i++) {
212 PC = Ext.PointOnCurve(i);
213 PS = Ext.PointOnSurface(i);
216 AddSolution(C, T, U, V, PC.Value(), PS.Value(), Ext.SquareDistance(i));
224 // Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134 Begin
227 if(myStype == GeomAbs_Cylinder) {
228 myExtElCS.Perform(C.Circle(), myS->Cylinder());
231 else if(myStype == GeomAbs_Plane)
233 myExtElCS.Perform(C.Circle(), myS->Plane());
236 else if (myStype == GeomAbs_Sphere)
238 myExtElCS.Perform(C.Circle(), myS->Sphere());
243 case GeomAbs_Hyperbola:
245 if(myCtype == GeomAbs_Hyperbola && myStype == GeomAbs_Plane) {
246 // Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134 End
247 myExtElCS.Perform(C.Hyperbola(), myS->Plane());
254 isComputeAnalytic = Standard_False;
259 if (isComputeAnalytic)
261 if (myExtElCS.IsDone())
263 myDone = Standard_True;
264 myIsPar = myExtElCS.IsParallel();
267 mySqDist.Append(myExtElCS.SquareDistance(1));
271 Standard_Integer NbExt = myExtElCS.NbExt();
272 for (i = 1; i <= NbExt; i++)
276 myExtElCS.Points(i, PC, PS);
277 Standard_Real Ucurve = PC.Parameter();
280 AddSolution(C, Ucurve, U, V, PC.Value(), PS.Value(), myExtElCS.SquareDistance(i));
283 if (mySqDist.Length() == 0 && NbExt > 0)
285 // Analytical extrema seem to be out of curve/surface boundaries.
286 // Try extremity points of curve.
287 gp_Pnt aPOnC[2], aPOnS[2];
288 Standard_Real aT[2] = { myucinf, myucsup }, U[2], V[2];
289 Standard_Real aDist[2] = { -1, -1 };
290 for (i = 0; i < 2; ++i)
292 if (Precision::IsInfinite(aT[i]))
295 aPOnC[i] = C.Value(aT[i]);
300 ElSLib::Parameters(myS->Plane(), aPOnC[i], U[i], V[i]);
301 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Plane());
306 ElSLib::Parameters(myS->Sphere(), aPOnC[i], U[i], V[i]);
307 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Sphere());
310 case GeomAbs_Cylinder:
312 ElSLib::Parameters(myS->Cylinder(), aPOnC[i], U[i], V[i]);
313 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Cylinder());
318 ElSLib::Parameters(myS->Torus(), aPOnC[i], U[i], V[i]);
319 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Torus());
324 ElSLib::Parameters(myS->Cone(), aPOnC[i], U[i], V[i]);
325 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Cone());
332 aDist[i] = aPOnC[i].SquareDistance(aPOnS[i]);
335 Standard_Boolean bAdd[2] = {Standard_False, Standard_False};
337 // Choose solution to add
338 if (aDist[0] >= 0. && aDist[1] >= 0.)
340 Standard_Real aDiff = aDist[0] - aDist[1];
341 // Both computed -> take only minimal
342 if (Abs(aDiff) < Precision::Confusion())
344 bAdd[0] = bAdd[1] = Standard_True;
347 bAdd[0] = Standard_True;
350 bAdd[1] = Standard_True;
352 else if (aDist[0] >= 0.)
354 bAdd[0] = Standard_True;
355 else if (aDist[1] >= 0.)
357 bAdd[1] = Standard_True;
359 for (i = 0; i < 2; ++i)
362 AddSolution(C, aT[i], U[i], V[i], aPOnC[i], aPOnS[i], aDist[i]);
370 // Elementary extrema is not done, try generic solution
371 Extrema_GenExtCS Ext;
372 Ext.Initialize(*myS, NbU, NbV, mytolS);
373 if (myCtype == GeomAbs_Hyperbola) {
374 Standard_Real tmin = Max(-20., C.FirstParameter());
375 Standard_Real tmax = Min(20., C.LastParameter());
376 Ext.Perform(C, NbT, tmin, tmax, mytolC); // to avoid overflow
379 if ((myCtype == GeomAbs_Circle && NbT < 13) ||
380 (myCtype == GeomAbs_BSplineCurve && NbT < 13))
384 Ext.Perform(C, NbT, mytolC);
387 myDone = Ext.IsDone();
389 Standard_Integer NbExt = Ext.NbExt();
390 Standard_Real T, U, V;
393 for (i = 1; i <= NbExt; i++) {
394 PC = Ext.PointOnCurve(i);
395 PS = Ext.PointOnSurface(i);
398 AddSolution(C, T, U, V, PC.Value(), PS.Value(), Ext.SquareDistance(i));
402 Standard_Integer SolNumber = mySqDist.Length();
403 Standard_Address CopyC = (Standard_Address)&C;
404 Adaptor3d_Curve& aC = *(Adaptor3d_Curve*)CopyC;
405 Standard_Integer NbIntervals = aC.NbIntervals(GeomAbs_C1);
406 TColStd_Array1OfReal SharpPoints(1, NbIntervals + 1);
407 aC.Intervals(SharpPoints, GeomAbs_C1);
409 Extrema_ExtPS aProjPS;
410 aProjPS.Initialize(*myS,
411 myS->FirstUParameter(),
412 myS->LastUParameter(),
413 myS->FirstVParameter(),
414 myS->LastVParameter(),
418 for (i = 2; i < SharpPoints.Upper(); ++i)
421 gp_Pnt aPnt = C.Value(T);
422 aProjPS.Perform(aPnt);
423 if (!aProjPS.IsDone())
425 Standard_Integer NbProj = aProjPS.NbExt(), jmin = 0;
426 Standard_Real MinSqDist = RealLast();
427 for (j = 1; j <= NbProj; j++)
429 Standard_Real aSqDist = aProjPS.SquareDistance(j);
430 if (aSqDist < MinSqDist)
438 aProjPS.Point(jmin).Parameter(U, V);
439 AddSolution(C, T, U, V,
440 aPnt, aProjPS.Point(jmin).Value(), MinSqDist);
443 //Cut sharp solutions to keep only minimum and maximum
444 Standard_Integer imin = SolNumber + 1, imax = mySqDist.Length();
445 for (i = SolNumber + 1; i <= mySqDist.Length(); i++)
447 if (mySqDist(i) < mySqDist(imin))
449 if (mySqDist(i) > mySqDist(imax))
452 if (mySqDist.Length() > SolNumber + 2)
454 Standard_Real MinSqDist = mySqDist(imin);
455 Standard_Real MaxSqDist = mySqDist(imax);
456 Extrema_POnCurv MinPC = myPOnC(imin);
457 Extrema_POnCurv MaxPC = myPOnC(imax);
458 Extrema_POnSurf MinPS = myPOnS(imin);
459 Extrema_POnSurf MaxPS = myPOnS(imax);
461 mySqDist.Remove(SolNumber + 1, mySqDist.Length());
462 myPOnC.Remove(SolNumber + 1, myPOnC.Length());
463 myPOnS.Remove(SolNumber + 1, myPOnS.Length());
465 mySqDist.Append(MinSqDist);
466 myPOnC.Append(MinPC);
467 myPOnS.Append(MinPS);
468 mySqDist.Append(MaxSqDist);
469 myPOnC.Append(MaxPC);
470 myPOnS.Append(MaxPS);
476 Standard_Boolean Extrema_ExtCS::IsDone() const
481 Standard_Boolean Extrema_ExtCS::IsParallel() const
485 throw StdFail_NotDone();
492 Standard_Real Extrema_ExtCS::SquareDistance(const Standard_Integer N) const
494 if (N < 1 || N > NbExt())
496 throw Standard_OutOfRange();
499 return mySqDist.Value(N);
503 Standard_Integer Extrema_ExtCS::NbExt() const
507 throw StdFail_NotDone();
510 return mySqDist.Length();
515 void Extrema_ExtCS::Points(const Standard_Integer N,
517 Extrema_POnSurf& P2) const
519 if (N < 1 || N > NbExt())
521 throw Standard_OutOfRange();
524 P1 = myPOnC.Value(N);
525 P2 = myPOnS.Value(N);
528 Standard_Boolean Extrema_ExtCS::AddSolution(const Adaptor3d_Curve& theCurve,
529 const Standard_Real aT,
530 const Standard_Real aU,
531 const Standard_Real aV,
532 const gp_Pnt& PointOnCurve,
533 const gp_Pnt& PointOnSurf,
534 const Standard_Real SquareDist)
536 Standard_Boolean Added = Standard_False;
538 Standard_Real T = aT, U = aU, V = aV;
540 if (theCurve.IsPeriodic())
541 T = ElCLib::InPeriod(T, myucinf, myucinf + theCurve.Period());
542 if (myS->IsUPeriodic())
543 U = ElCLib::InPeriod(U, myuinf, myuinf + myS->UPeriod());
544 if (myS->IsVPeriodic())
545 V = ElCLib::InPeriod(V, myvinf, myvinf + myS->VPeriod());
549 if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
550 (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
551 (myvinf-V) <= mytolS && (V-myvsup) <= mytolS)
553 Standard_Boolean IsNewSolution = Standard_True;
554 for (Standard_Integer j = 1; j <= mySqDist.Length(); j++)
558 Standard_Real Tj = aPC.Parameter();
559 Standard_Real Uj, Vj;
560 aPS.Parameter(Uj, Vj);
561 if (Abs(T - Tj) <= mytolC &&
562 Abs(U - Uj) <= mytolS &&
563 Abs(V - Vj) <= mytolS)
565 IsNewSolution = Standard_False;
571 mySqDist.Append(SquareDist);
572 aPC.SetValues(T, PointOnCurve);
574 myPOnS.Append(Extrema_POnSurf(U, V, PointOnSurf));
575 Added = Standard_True;