0028599: Replacement of old Boolean operations with new ones in BRepProj_Projection...
[occt.git] / src / Extrema / Extrema_ExtCS.cxx
CommitLineData
b311480e 1// Created on: 1995-07-18
2// Created by: Modelistation
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
17// Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134
18
42cf5bc1 19#include <Adaptor3d_Curve.hxx>
20#include <Adaptor3d_Surface.hxx>
21#include <Bnd_Box.hxx>
22#include <BndLib_AddSurface.hxx>
23#include <ElCLib.hxx>
24#include <ElSLib.hxx>
25#include <Extrema_ExtCS.hxx>
26#include <Extrema_ExtPElC.hxx>
27#include <Extrema_ExtPElS.hxx>
28#include <Extrema_ExtPS.hxx>
7fd59977 29#include <Extrema_GenExtCS.hxx>
42cf5bc1 30#include <Extrema_POnCurv.hxx>
31#include <Extrema_POnSurf.hxx>
7fd59977 32#include <GeomAbs_CurveType.hxx>
7fd59977 33#include <gp_Cone.hxx>
42cf5bc1 34#include <gp_Cylinder.hxx>
35#include <gp_Lin.hxx>
36#include <gp_Pln.hxx>
37#include <gp_Pnt.hxx>
7fd59977 38#include <gp_Sphere.hxx>
39#include <gp_Torus.hxx>
42cf5bc1 40#include <Precision.hxx>
41#include <Standard_NotImplemented.hxx>
42#include <Standard_OutOfRange.hxx>
43#include <Standard_TypeMismatch.hxx>
44#include <StdFail_InfiniteSolutions.hxx>
45#include <StdFail_NotDone.hxx>
38308958 46#include <TColStd_Array1OfReal.hxx>
7fd59977 47
48Extrema_ExtCS::Extrema_ExtCS()
49{
50 myDone = Standard_False;
51}
52
53Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve& C,
29d778bf 54 const Adaptor3d_Surface& S,
55 const Standard_Real TolC,
56 const Standard_Real TolS)
7fd59977 57
58{
59 Initialize(S, S.FirstUParameter(), S.LastUParameter(),
29d778bf 60 S.FirstVParameter(), S.LastVParameter(),
61 TolC, TolS);
7fd59977 62 Perform(C, C.FirstParameter(), C.LastParameter());
63}
64
65Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve& C,
29d778bf 66 const Adaptor3d_Surface& S,
67 const Standard_Real UCinf,
68 const Standard_Real UCsup,
69 const Standard_Real Uinf,
70 const Standard_Real Usup,
71 const Standard_Real Vinf,
72 const Standard_Real Vsup,
73 const Standard_Real TolC,
74 const Standard_Real TolS)
7fd59977 75
76{
77 Initialize(S, Uinf, Usup, Vinf, Vsup, TolC, TolS);
78 Perform(C, UCinf, UCsup);
79}
80
81
82void Extrema_ExtCS::Initialize(const Adaptor3d_Surface& S,
29d778bf 83 const Standard_Real Uinf,
84 const Standard_Real Usup,
85 const Standard_Real Vinf,
86 const Standard_Real Vsup,
87 const Standard_Real TolC,
88 const Standard_Real TolS)
7fd59977 89{
90 myS = (Adaptor3d_SurfacePtr)&S;
91 myIsPar = Standard_False;
92 myuinf = Uinf;
93 myusup = Usup;
94 myvinf = Vinf;
95 myvsup = Vsup;
96 mytolC = TolC;
97 mytolS = TolS;
98 myStype = myS->GetType();
99}
100
29d778bf 101
7fd59977 102void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C,
29d778bf 103 const Standard_Real Uinf,
104 const Standard_Real Usup)
7fd59977 105{
106 myucinf = Uinf;
107 myucsup = Usup;
108 myPOnS.Clear();
109 myPOnC.Clear();
110 mySqDist.Clear();
38308958 111 Standard_Integer i, j;
7fd59977 112 Standard_Integer NbT, NbU, NbV;
113 NbT = NbU = NbV = 10;
114 GeomAbs_CurveType myCtype = C.GetType();
115
03cca6f7 116 myDone = Standard_False;
117 // Try analytic computation of extrema
118 Standard_Boolean isComputeAnalytic = Standard_True;
7fd59977 119
120 switch(myCtype) {
121
122 case GeomAbs_Line:
123 {
29d778bf 124
7fd59977 125 switch(myStype) {
126 case GeomAbs_Sphere:
29d778bf 127 myExtElCS.Perform(C.Line(), myS->Sphere());
128 break;
7fd59977 129 case GeomAbs_Cylinder:
29d778bf 130 myExtElCS.Perform(C.Line(), myS->Cylinder());
131 break;
7fd59977 132 case GeomAbs_Plane:
29d778bf 133 myExtElCS.Perform(C.Line(), myS->Plane());
134 if (myExtElCS.IsParallel()) break;
b1811c1d 135 Standard_FALLTHROUGH
7fd59977 136
137 case GeomAbs_Torus:
138 case GeomAbs_Cone:
139 case GeomAbs_BezierSurface:
140 case GeomAbs_BSplineSurface:
141 case GeomAbs_SurfaceOfRevolution:
142 case GeomAbs_SurfaceOfExtrusion:
1896126e 143 case GeomAbs_OffsetSurface:
7fd59977 144 case GeomAbs_OtherSurface:
29d778bf 145 {
146 Standard_Real cfirst = myucinf, clast = myucsup;
147 Standard_Real ufirst = myS->FirstUParameter(), ulast = myS->LastUParameter(),
148 vfirst = myS->FirstVParameter(), vlast = myS->LastVParameter();
7fd59977 149
29d778bf 150 if(Precision::IsInfinite(Abs(cfirst)) || Precision::IsInfinite(Abs(clast))) {
7fd59977 151
29d778bf 152 Bnd_Box aSurfBox;
1896126e 153 BndLib_AddSurface::Add(*myS, ufirst, ulast, vfirst, vlast, Precision::Confusion(), aSurfBox);
29d778bf 154 Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
155 aSurfBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
156 Standard_Real tmin = Precision::Infinite(), tmax = -tmin;
157 gp_Lin aLin = C.Line();
158
159
160 if(!( Precision::IsInfinite(Abs(xmin)) || Precision::IsInfinite(Abs(xmax)) ||
161 Precision::IsInfinite(Abs(ymin)) || Precision::IsInfinite(Abs(ymax)) ||
162 Precision::IsInfinite(Abs(zmin)) || Precision::IsInfinite(Abs(zmax))) ) {
163
164 Extrema_ExtPElC anExt;
165 Extrema_POnCurv aPntOnLin;
166 Standard_Real aParOnLin;
167 Standard_Real lim = Precision::Infinite();
168 gp_Pnt aLimPntArray[8];
169
170 aLimPntArray[0].SetCoord(xmin, ymin, zmin);
171 aLimPntArray[1].SetCoord(xmax, ymin, zmin);
172 aLimPntArray[2].SetCoord(xmin, ymax, zmin);
173 aLimPntArray[3].SetCoord(xmax, ymax, zmin);
174 aLimPntArray[4].SetCoord(xmin, ymin, zmax);
175 aLimPntArray[5].SetCoord(xmax, ymin, zmax);
176 aLimPntArray[6].SetCoord(xmin, ymax, zmax);
177 aLimPntArray[7].SetCoord(xmax, ymax, zmax);
178
179 for(i = 0; i <= 7; i++) {
180 anExt.Perform(aLimPntArray[i], aLin, Precision::Confusion(), -lim, lim);
181 aPntOnLin = anExt.Point(1);
182 aParOnLin = aPntOnLin.Parameter();
183 tmin = Min(aParOnLin, tmin);
184 tmax = Max(aParOnLin, tmax);
185 }
186
187 }
188 else {
189 tmin = -1.e+50;
190 tmax = 1.e+50;
191 }
192
193
194 cfirst = Max(cfirst, tmin);
195 clast = Min(clast, tmax);
196
197 }
198
fa6d1712 199 if (myS->IsUPeriodic())
200 NbU = 13;
201 if (myS->IsVPeriodic())
202 NbV = 13;
29d778bf 203
204 Extrema_GenExtCS Ext(C, *myS, NbT, NbU, NbV, cfirst, clast, ufirst, ulast,
205 vfirst, vlast, mytolC, mytolS);
206
207 myDone = Ext.IsDone();
208 if (myDone) {
209 Standard_Integer NbExt = Ext.NbExt();
210 Standard_Real T,U,V;
211 Extrema_POnCurv PC;
212 Extrema_POnSurf PS;
213 for (i = 1; i <= NbExt; i++) {
214 PC = Ext.PointOnCurve(i);
215 PS = Ext.PointOnSurface(i);
216 T = PC.Parameter();
217 PS.Parameter(U, V);
38308958 218 AddSolution(C, T, U, V, PC.Value(), PS.Value(), Ext.SquareDistance(i));
29d778bf 219 }
220 }
221 return;
222
223 }
7fd59977 224 }
225 break;
226 }
29d778bf 227 // Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134 Begin
7fd59977 228 case GeomAbs_Circle:
229 {
230 if(myStype == GeomAbs_Cylinder) {
29d778bf 231 myExtElCS.Perform(C.Circle(), myS->Cylinder());
232 break;
7fd59977 233 }
9dfbbfe6 234 else if(myStype == GeomAbs_Plane)
235 {
236 myExtElCS.Perform(C.Circle(), myS->Plane());
237 break;
238 }
03cca6f7 239 else if (myStype == GeomAbs_Sphere)
240 {
241 myExtElCS.Perform(C.Circle(), myS->Sphere());
242 break;
243 }
7fd59977 244 }
b1811c1d 245 Standard_FALLTHROUGH
7fd59977 246 case GeomAbs_Hyperbola:
247 {
248 if(myCtype == GeomAbs_Hyperbola && myStype == GeomAbs_Plane) {
29d778bf 249 // Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134 End
250 myExtElCS.Perform(C.Hyperbola(), myS->Plane());
251 break;
7fd59977 252 }
253 }
b1811c1d 254 Standard_FALLTHROUGH
7fd59977 255 default:
256 {
03cca6f7 257 isComputeAnalytic = Standard_False;
258 break;
259 }
260 }
261
262 if (isComputeAnalytic)
263 {
264 if (myExtElCS.IsDone())
265 {
266 myDone = Standard_True;
267 myIsPar = myExtElCS.IsParallel();
268 if (myIsPar)
269 {
270 mySqDist.Append(myExtElCS.SquareDistance(1));
7fd59977 271 }
03cca6f7 272 else
273 {
274 Standard_Integer NbExt = myExtElCS.NbExt();
275 for (i = 1; i <= NbExt; i++)
fa6d1712 276 {
03cca6f7 277 Extrema_POnCurv PC;
278 Extrema_POnSurf PS;
279 myExtElCS.Points(i, PC, PS);
280 Standard_Real Ucurve = PC.Parameter();
281 Standard_Real U, V;
29d778bf 282 PS.Parameter(U, V);
03cca6f7 283 AddSolution(C, Ucurve, U, V, PC.Value(), PS.Value(), myExtElCS.SquareDistance(i));
29d778bf 284 }
38308958 285
03cca6f7 286 if (mySqDist.Length() == 0 && NbExt > 0)
38308958 287 {
03cca6f7 288 // Analytical extrema seem to be out of curve/surface boundaries.
289 // Try extremity points of curve.
290 gp_Pnt aPOnC[2], aPOnS[2];
291 Standard_Real aT[2] = { myucinf, myucsup }, U[2], V[2];
292 Standard_Real aDist[2] = { -1, -1 };
293 for (i = 0; i < 2; ++i)
38308958 294 {
03cca6f7 295 if (Precision::IsInfinite(aT[i]))
296 continue;
297
298 aPOnC[i] = C.Value(aT[i]);
299 switch (myStype)
38308958 300 {
03cca6f7 301 case GeomAbs_Plane:
302 {
303 ElSLib::Parameters(myS->Plane(), aPOnC[i], U[i], V[i]);
304 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Plane());
305 break;
306 }
307 case GeomAbs_Sphere:
308 {
309 ElSLib::Parameters(myS->Sphere(), aPOnC[i], U[i], V[i]);
310 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Sphere());
311 break;
312 }
313 case GeomAbs_Cylinder:
314 {
315 ElSLib::Parameters(myS->Cylinder(), aPOnC[i], U[i], V[i]);
316 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Cylinder());
317 break;
318 }
319 case GeomAbs_Torus:
320 {
321 ElSLib::Parameters(myS->Torus(), aPOnC[i], U[i], V[i]);
322 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Torus());
323 break;
324 }
325 case GeomAbs_Cone:
326 {
327 ElSLib::Parameters(myS->Cone(), aPOnC[i], U[i], V[i]);
328 aPOnS[i] = ElSLib::Value(U[i], V[i], myS->Cone());
329 break;
330 }
331 default:
332 continue;
38308958 333 }
03cca6f7 334
335 aDist[i] = aPOnC[i].SquareDistance(aPOnS[i]);
38308958 336 }
03cca6f7 337
338 Standard_Boolean bAdd[2] = {Standard_False, Standard_False};
339
340 // Choose solution to add
341 if (aDist[0] >= 0. && aDist[1] >= 0.)
38308958 342 {
03cca6f7 343 Standard_Real aDiff = aDist[0] - aDist[1];
344 // Both computed -> take only minimal
345 if (Abs(aDiff) < Precision::Confusion())
346 // Add both
347 bAdd[0] = bAdd[1] = Standard_True;
348 else if (aDiff < 0)
349 // Add first
350 bAdd[0] = Standard_True;
351 else
352 // Add second
353 bAdd[1] = Standard_True;
354 }
355 else if (aDist[0] >= 0.)
356 // Add first
357 bAdd[0] = Standard_True;
358 else if (aDist[1] >= 0.)
359 // Add second
360 bAdd[1] = Standard_True;
361
362 for (i = 0; i < 2; ++i)
363 {
364 if (bAdd[i])
365 AddSolution(C, aT[i], U[i], V[i], aPOnC[i], aPOnS[i], aDist[i]);
38308958 366 }
38308958 367 }
7fd59977 368 }
369 return;
370 }
7fd59977 371 }
29d778bf 372
03cca6f7 373 // Elementary extrema is not done, try generic solution
374 Extrema_GenExtCS Ext;
375 Ext.Initialize(*myS, NbU, NbV, mytolS);
376 if (myCtype == GeomAbs_Hyperbola) {
377 Standard_Real tmin = Max(-20., C.FirstParameter());
378 Standard_Real tmax = Min(20., C.LastParameter());
379 Ext.Perform(C, NbT, tmin, tmax, mytolC); // to avoid overflow
380 }
381 else {
382 if ((myCtype == GeomAbs_Circle && NbT < 13) ||
383 (myCtype == GeomAbs_BSplineCurve && NbT < 13))
384 {
385 NbT = 13;
386 }
387 Ext.Perform(C, NbT, mytolC);
388 }
389
390 myDone = Ext.IsDone();
7fd59977 391 if (myDone) {
03cca6f7 392 Standard_Integer NbExt = Ext.NbExt();
393 Standard_Real T, U, V;
394 Extrema_POnCurv PC;
395 Extrema_POnSurf PS;
396 for (i = 1; i <= NbExt; i++) {
397 PC = Ext.PointOnCurve(i);
398 PS = Ext.PointOnSurface(i);
399 T = PC.Parameter();
400 PS.Parameter(U, V);
401 AddSolution(C, T, U, V, PC.Value(), PS.Value(), Ext.SquareDistance(i));
7fd59977 402 }
03cca6f7 403
404 //Add sharp points
405 Standard_Integer SolNumber = mySqDist.Length();
406 Standard_Address CopyC = (Standard_Address)&C;
407 Adaptor3d_Curve& aC = *(Adaptor3d_Curve*)CopyC;
408 Standard_Integer NbIntervals = aC.NbIntervals(GeomAbs_C1);
409 TColStd_Array1OfReal SharpPoints(1, NbIntervals + 1);
410 aC.Intervals(SharpPoints, GeomAbs_C1);
411
412 Extrema_ExtPS aProjPS;
413 aProjPS.Initialize(*myS,
414 myS->FirstUParameter(),
415 myS->LastUParameter(),
416 myS->FirstVParameter(),
417 myS->LastVParameter(),
418 mytolS,
419 mytolS);
420
421 for (i = 2; i < SharpPoints.Upper(); ++i)
422 {
423 T = SharpPoints(i);
424 gp_Pnt aPnt = C.Value(T);
425 aProjPS.Perform(aPnt);
426 if (!aProjPS.IsDone())
427 continue;
428 Standard_Integer NbProj = aProjPS.NbExt(), jmin = 0;
429 Standard_Real MinSqDist = RealLast();
430 for (j = 1; j <= NbProj; j++)
9dfbbfe6 431 {
03cca6f7 432 Standard_Real aSqDist = aProjPS.SquareDistance(j);
433 if (aSqDist < MinSqDist)
9dfbbfe6 434 {
03cca6f7 435 MinSqDist = aSqDist;
436 jmin = j;
9dfbbfe6 437 }
438 }
03cca6f7 439 if (jmin != 0)
440 {
441 aProjPS.Point(jmin).Parameter(U, V);
442 AddSolution(C, T, U, V,
443 aPnt, aProjPS.Point(jmin).Value(), MinSqDist);
444 }
445 }
446 //Cut sharp solutions to keep only minimum and maximum
447 Standard_Integer imin = SolNumber + 1, imax = mySqDist.Length();
448 for (i = SolNumber + 1; i <= mySqDist.Length(); i++)
449 {
450 if (mySqDist(i) < mySqDist(imin))
451 imin = i;
452 if (mySqDist(i) > mySqDist(imax))
453 imax = i;
454 }
455 if (mySqDist.Length() > SolNumber + 2)
456 {
457 Standard_Real MinSqDist = mySqDist(imin);
458 Standard_Real MaxSqDist = mySqDist(imax);
459 Extrema_POnCurv MinPC = myPOnC(imin);
460 Extrema_POnCurv MaxPC = myPOnC(imax);
461 Extrema_POnSurf MinPS = myPOnS(imin);
462 Extrema_POnSurf MaxPS = myPOnS(imax);
463
464 mySqDist.Remove(SolNumber + 1, mySqDist.Length());
465 myPOnC.Remove(SolNumber + 1, myPOnC.Length());
466 myPOnS.Remove(SolNumber + 1, myPOnS.Length());
467
468 mySqDist.Append(MinSqDist);
469 myPOnC.Append(MinPC);
470 myPOnS.Append(MinPS);
471 mySqDist.Append(MaxSqDist);
472 myPOnC.Append(MaxPC);
473 myPOnS.Append(MaxPS);
7fd59977 474 }
475 }
7fd59977 476}
477
478
479Standard_Boolean Extrema_ExtCS::IsDone() const
480{
481 return myDone;
482}
483
484Standard_Boolean Extrema_ExtCS::IsParallel() const
485{
486 return myIsPar;
487}
488
489
490Standard_Real Extrema_ExtCS::SquareDistance(const Standard_Integer N) const
491{
9775fa61 492 if(!myDone) throw StdFail_NotDone();
493 if (myIsPar && N != 1) throw StdFail_InfiniteSolutions();
494 if ((N < 1) || (N > mySqDist.Length())) throw Standard_OutOfRange();
7fd59977 495 return mySqDist.Value(N);
496}
497
498
499Standard_Integer Extrema_ExtCS::NbExt() const
500{
9775fa61 501 if(!myDone) throw StdFail_NotDone();
9176540c 502 return myPOnC.Length();
7fd59977 503}
504
505
506
507void Extrema_ExtCS::Points(const Standard_Integer N,
29d778bf 508 Extrema_POnCurv& P1,
509 Extrema_POnSurf& P2) const
7fd59977 510{
9775fa61 511 if(!myDone) throw StdFail_NotDone();
7fd59977 512 P1 = myPOnC.Value(N);
513 P2 = myPOnS.Value(N);
514}
38308958 515
516Standard_Boolean Extrema_ExtCS::AddSolution(const Adaptor3d_Curve& theCurve,
29d778bf 517 const Standard_Real aT,
518 const Standard_Real aU,
519 const Standard_Real aV,
520 const gp_Pnt& PointOnCurve,
521 const gp_Pnt& PointOnSurf,
522 const Standard_Real SquareDist)
38308958 523{
524 Standard_Boolean Added = Standard_False;
525
526 Standard_Real T = aT, U = aU, V = aV;
29d778bf 527
38308958 528 if (theCurve.IsPeriodic())
529 T = ElCLib::InPeriod(T, myucinf, myucinf + theCurve.Period());
530 if (myS->IsUPeriodic())
531 U = ElCLib::InPeriod(U, myuinf, myuinf + myS->UPeriod());
532 if (myS->IsVPeriodic())
533 V = ElCLib::InPeriod(V, myvinf, myvinf + myS->VPeriod());
534
535 Extrema_POnCurv aPC;
536 Extrema_POnSurf aPS;
537 if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
29d778bf 538 (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
539 (myvinf-V) <= mytolS && (V-myvsup) <= mytolS)
38308958 540 {
541 Standard_Boolean IsNewSolution = Standard_True;
542 for (Standard_Integer j = 1; j <= mySqDist.Length(); j++)
543 {
544 aPC = myPOnC(j);
545 aPS = myPOnS(j);
546 Standard_Real Tj = aPC.Parameter();
547 Standard_Real Uj, Vj;
548 aPS.Parameter(Uj, Vj);
549 if (Abs(T - Tj) <= mytolC &&
29d778bf 550 Abs(U - Uj) <= mytolS &&
551 Abs(V - Vj) <= mytolS)
38308958 552 {
553 IsNewSolution = Standard_False;
554 break;
555 }
556 }
557 if (IsNewSolution)
558 {
559 mySqDist.Append(SquareDist);
560 aPC.SetValues(T, PointOnCurve);
561 myPOnC.Append(aPC);
562 myPOnS.Append(Extrema_POnSurf(U, V, PointOnSurf));
563 Added = Standard_True;
564 }
565 }
566 return Added;
567}