0023995: GeomAPI_ExtremaCurveSurface : wrong result between a curve and a plane
[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
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
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.
10//
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.
13//
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.
20
7fd59977 21
22// Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134
23
24#include <Extrema_ExtCS.ixx>
25#include <Extrema_GenExtCS.hxx>
26#include <StdFail_NotDone.hxx>
27#include <Standard_NotImplemented.hxx>
28#include <StdFail_InfiniteSolutions.hxx>
29#include <Precision.hxx>
30#include <GeomAbs_CurveType.hxx>
31#include <gp_Pnt.hxx>
32#include <gp_Pln.hxx>
33#include <gp_Cylinder.hxx>
34#include <gp_Cone.hxx>
35#include <gp_Sphere.hxx>
36#include <gp_Torus.hxx>
37#include <gp_Lin.hxx>
38
39#include <ElCLib.hxx>
40#include <Extrema_ExtPElC.hxx>
41#include <Bnd_Box.hxx>
42#include <BndLib_AddSurface.hxx>
43#include <Extrema_ExtPElS.hxx>
38308958 44#include <TColStd_Array1OfReal.hxx>
45#include <Extrema_ExtPS.hxx>
7fd59977 46
47Extrema_ExtCS::Extrema_ExtCS()
48{
49 myDone = Standard_False;
50}
51
52Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve& C,
53 const Adaptor3d_Surface& S,
54 const Standard_Real TolC,
55 const Standard_Real TolS)
56
57{
58 Initialize(S, S.FirstUParameter(), S.LastUParameter(),
59 S.FirstVParameter(), S.LastVParameter(),
60 TolC, TolS);
61 Perform(C, C.FirstParameter(), C.LastParameter());
62}
63
64Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve& C,
65 const Adaptor3d_Surface& S,
66 const Standard_Real UCinf,
67 const Standard_Real UCsup,
68 const Standard_Real Uinf,
69 const Standard_Real Usup,
70 const Standard_Real Vinf,
71 const Standard_Real Vsup,
72 const Standard_Real TolC,
73 const Standard_Real TolS)
74
75{
76 Initialize(S, Uinf, Usup, Vinf, Vsup, TolC, TolS);
77 Perform(C, UCinf, UCsup);
78}
79
80
81void Extrema_ExtCS::Initialize(const Adaptor3d_Surface& S,
82 const Standard_Real Uinf,
83 const Standard_Real Usup,
84 const Standard_Real Vinf,
85 const Standard_Real Vsup,
86 const Standard_Real TolC,
87 const Standard_Real TolS)
88{
89 myS = (Adaptor3d_SurfacePtr)&S;
90 myIsPar = Standard_False;
91 myuinf = Uinf;
92 myusup = Usup;
93 myvinf = Vinf;
94 myvsup = Vsup;
95 mytolC = TolC;
96 mytolS = TolS;
97 myStype = myS->GetType();
98}
99
100
101void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C,
102 const Standard_Real Uinf,
103 const Standard_Real Usup)
104{
105 myucinf = Uinf;
106 myucsup = Usup;
107 myPOnS.Clear();
108 myPOnC.Clear();
109 mySqDist.Clear();
38308958 110 Standard_Integer i, j;
7fd59977 111 Standard_Integer NbT, NbU, NbV;
112 NbT = NbU = NbV = 10;
113 GeomAbs_CurveType myCtype = C.GetType();
114
115
116 switch(myCtype) {
117
118 case GeomAbs_Line:
119 {
120
121 switch(myStype) {
122 case GeomAbs_Sphere:
123 myExtElCS.Perform(C.Line(), myS->Sphere());
124 break;
125 case GeomAbs_Cylinder:
126 myExtElCS.Perform(C.Line(), myS->Cylinder());
127 break;
128 case GeomAbs_Plane:
129 myExtElCS.Perform(C.Line(), myS->Plane());
130 if (myExtElCS.IsParallel()) break;
131
132 case GeomAbs_Torus:
133 case GeomAbs_Cone:
134 case GeomAbs_BezierSurface:
135 case GeomAbs_BSplineSurface:
136 case GeomAbs_SurfaceOfRevolution:
137 case GeomAbs_SurfaceOfExtrusion:
138 case GeomAbs_OtherSurface:
139 {
140 Standard_Real cfirst = myucinf, clast = myucsup;
141 Standard_Real ufirst = myS->FirstUParameter(), ulast = myS->LastUParameter(),
142 vfirst = myS->FirstVParameter(), vlast = myS->LastVParameter();
143
144 if(Precision::IsInfinite(Abs(cfirst)) || Precision::IsInfinite(Abs(clast))) {
145
146 Bnd_Box aSurfBox;
6e6cd5d9 147 BndLib_AddSurface::Add(*myS, ufirst, ulast, vfirst, vlast, Precision::Confusion(), aSurfBox);
7fd59977 148 Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
149 aSurfBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
150 Standard_Real tmin = Precision::Infinite(), tmax = -tmin;
151 gp_Lin aLin = C.Line();
152
153
154 if(!( Precision::IsInfinite(Abs(xmin)) || Precision::IsInfinite(Abs(xmax)) ||
155 Precision::IsInfinite(Abs(ymin)) || Precision::IsInfinite(Abs(ymax)) ||
156 Precision::IsInfinite(Abs(zmin)) || Precision::IsInfinite(Abs(zmax))) ) {
157
158 Extrema_ExtPElC anExt;
159 Extrema_POnCurv aPntOnLin;
160 Standard_Real aParOnLin;
161 Standard_Real lim = Precision::Infinite();
162 gp_Pnt aLimPntArray[8];
163
164 aLimPntArray[0].SetCoord(xmin, ymin, zmin);
165 aLimPntArray[1].SetCoord(xmax, ymin, zmin);
166 aLimPntArray[2].SetCoord(xmin, ymax, zmin);
167 aLimPntArray[3].SetCoord(xmax, ymax, zmin);
168 aLimPntArray[4].SetCoord(xmin, ymin, zmax);
169 aLimPntArray[5].SetCoord(xmax, ymin, zmax);
170 aLimPntArray[6].SetCoord(xmin, ymax, zmax);
171 aLimPntArray[7].SetCoord(xmax, ymax, zmax);
172
173 for(i = 0; i <= 7; i++) {
174 anExt.Perform(aLimPntArray[i], aLin, Precision::Confusion(), -lim, lim);
175 aPntOnLin = anExt.Point(1);
176 aParOnLin = aPntOnLin.Parameter();
177 tmin = Min(aParOnLin, tmin);
178 tmax = Max(aParOnLin, tmax);
179 }
180
181 }
182 else {
183 tmin = -1.e+50;
184 tmax = 1.e+50;
185 }
186
187
188 cfirst = Max(cfirst, tmin);
189 clast = Min(clast, tmax);
190
191 }
192
193
194
195 Extrema_GenExtCS Ext(C, *myS, NbT, NbU, NbV, cfirst, clast, ufirst, ulast,
196 vfirst, vlast, mytolC, mytolS);
197
198 myDone = Ext.IsDone();
199 if (myDone) {
200 Standard_Integer NbExt = Ext.NbExt();
201 Standard_Real T,U,V;
202 Extrema_POnCurv PC;
203 Extrema_POnSurf PS;
204 for (i = 1; i <= NbExt; i++) {
205 PC = Ext.PointOnCurve(i);
206 PS = Ext.PointOnSurface(i);
207 T = PC.Parameter();
208 PS.Parameter(U, V);
38308958 209 AddSolution(C, T, U, V, PC.Value(), PS.Value(), Ext.SquareDistance(i));
7fd59977 210 }
211 }
212 return;
213
214 }
215#ifndef DEB
216 default:
217#endif
218 break;
219 }
220 break;
221 }
222// Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134 Begin
223 case GeomAbs_Circle:
224 {
225 if(myStype == GeomAbs_Cylinder) {
226 myExtElCS.Perform(C.Circle(), myS->Cylinder());
227 break;
228 }
229 }
230 case GeomAbs_Hyperbola:
231 {
232 if(myCtype == GeomAbs_Hyperbola && myStype == GeomAbs_Plane) {
233// Modified by skv - Thu Jul 7 12:29:34 2005 OCC9134 End
234 myExtElCS.Perform(C.Hyperbola(), myS->Plane());
235 break;
236 }
237 }
238 default:
239 {
240 Extrema_GenExtCS Ext;
241 Ext.Initialize(*myS, NbU, NbV, mytolS);
242 if(myCtype == GeomAbs_Hyperbola) {
243 Standard_Real tmin = Max(-20., C.FirstParameter());
244 Standard_Real tmax = Min(20., C.LastParameter());
245 Ext.Perform(C, NbT, tmin, tmax, mytolC); // to avoid overflow
246 }
247 else {
248 if(myCtype == GeomAbs_Circle && NbT < 13) {
249 NbT = 13;
250 }
251 Ext.Perform(C, NbT, mytolC);
252 }
253
254 myDone = Ext.IsDone();
255 if (myDone) {
256 Standard_Integer NbExt = Ext.NbExt();
257 Standard_Real T,U,V;
258 Extrema_POnCurv PC;
259 Extrema_POnSurf PS;
260 for (i = 1; i <= NbExt; i++) {
261 PC = Ext.PointOnCurve(i);
262 PS = Ext.PointOnSurface(i);
263 T = PC.Parameter();
264 PS.Parameter(U, V);
38308958 265 AddSolution(C, T, U, V, PC.Value(), PS.Value(), Ext.SquareDistance(i));
7fd59977 266 }
38308958 267
268 //Add sharp points
269 Standard_Integer SolNumber = mySqDist.Length();
270 Standard_Address CopyC = (Standard_Address)&C;
271 Adaptor3d_Curve& aC = *(Adaptor3d_Curve*)CopyC;
272 Standard_Integer NbIntervals = aC.NbIntervals(GeomAbs_C1);
273 TColStd_Array1OfReal SharpPoints(1, NbIntervals+1);
274 aC.Intervals(SharpPoints, GeomAbs_C1);
275 for (i = 1; i <= SharpPoints.Upper(); i++)
276 {
277 T = SharpPoints(i);
278 gp_Pnt aPnt = C.Value(T);
279 Extrema_ExtPS ProjPS(aPnt, *myS, mytolS, mytolS);
280 if (!ProjPS.IsDone())
281 continue;
282 Standard_Integer NbProj = ProjPS.NbExt(), jmin = 0;
283 Standard_Real MinSqDist = RealLast();
284 for (j = 1; j <= NbProj; j++)
285 {
286 Standard_Real aSqDist = ProjPS.SquareDistance(j);
287 if (aSqDist < MinSqDist)
288 {
289 MinSqDist = aSqDist;
290 jmin = j;
291 }
292 }
293 if (jmin != 0)
294 {
295 ProjPS.Point(jmin).Parameter(U,V);
296 AddSolution(C, T, U, V,
297 aPnt, ProjPS.Point(jmin).Value(), MinSqDist);
298 }
299 }
300 //Cut sharp solutions to keep only minimum and maximum
301 Standard_Integer imin = SolNumber + 1, imax = mySqDist.Length();
302 for (i = SolNumber + 1; i <= mySqDist.Length(); i++)
303 {
304 if (mySqDist(i) < mySqDist(imin))
305 imin = i;
306 if (mySqDist(i) > mySqDist(imax))
307 imax = i;
308 }
309 if (mySqDist.Length() > SolNumber + 2)
310 {
311 Standard_Real MinSqDist = mySqDist(imin);
312 Standard_Real MaxSqDist = mySqDist(imax);
313 Extrema_POnCurv MinPC = myPOnC(imin);
314 Extrema_POnCurv MaxPC = myPOnC(imax);
315 Extrema_POnSurf MinPS = myPOnS(imin);
316 Extrema_POnSurf MaxPS = myPOnS(imax);
317
318 mySqDist.Remove(SolNumber + 1, mySqDist.Length());
319 myPOnC.Remove(SolNumber + 1, myPOnC.Length());
320 myPOnS.Remove(SolNumber + 1, myPOnS.Length());
321
322 mySqDist.Append(MinSqDist);
323 myPOnC.Append(MinPC);
324 myPOnS.Append(MinPS);
325 mySqDist.Append(MaxSqDist);
326 myPOnC.Append(MaxPC);
327 myPOnS.Append(MaxPS);
328 }
7fd59977 329 }
330 return;
331 }
332 break;
333 }
334
335 myDone = myExtElCS.IsDone();
336 if (myDone) {
337 myIsPar = myExtElCS.IsParallel();
338 if (myIsPar) {
339 mySqDist.Append(myExtElCS.SquareDistance(1));
340 }
341 else {
342 Standard_Integer NbExt = myExtElCS.NbExt();
343 Standard_Real U, V;
344 for (i = 1; i <= NbExt; i++) {
345 Extrema_POnCurv PC;
346 Extrema_POnSurf PS;
347 myExtElCS.Points(i, PC, PS);
348 Standard_Real Ucurve = PC.Parameter();
349 PS.Parameter(U, V);
38308958 350 AddSolution(C, Ucurve, U, V, PC.Value(), PS.Value(), myExtElCS.SquareDistance(i));
7fd59977 351 }
352 }
353 }
354
355}
356
357
358Standard_Boolean Extrema_ExtCS::IsDone() const
359{
360 return myDone;
361}
362
363Standard_Boolean Extrema_ExtCS::IsParallel() const
364{
365 return myIsPar;
366}
367
368
369Standard_Real Extrema_ExtCS::SquareDistance(const Standard_Integer N) const
370{
371 if(!myDone) StdFail_NotDone::Raise();
372 if (myIsPar && N != 1) StdFail_InfiniteSolutions::Raise();
373 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
374 return mySqDist.Value(N);
375}
376
377
378Standard_Integer Extrema_ExtCS::NbExt() const
379{
380 if(!myDone) StdFail_NotDone::Raise();
381 return mySqDist.Length();
382}
383
384
385
386void Extrema_ExtCS::Points(const Standard_Integer N,
387 Extrema_POnCurv& P1,
388 Extrema_POnSurf& P2) const
389{
390 if(!myDone) StdFail_NotDone::Raise();
391 P1 = myPOnC.Value(N);
392 P2 = myPOnS.Value(N);
393}
38308958 394
395Standard_Boolean Extrema_ExtCS::AddSolution(const Adaptor3d_Curve& theCurve,
396 const Standard_Real aT,
397 const Standard_Real aU,
398 const Standard_Real aV,
399 const gp_Pnt& PointOnCurve,
400 const gp_Pnt& PointOnSurf,
401 const Standard_Real SquareDist)
402{
403 Standard_Boolean Added = Standard_False;
404
405 Standard_Real T = aT, U = aU, V = aV;
406
407 if (theCurve.IsPeriodic())
408 T = ElCLib::InPeriod(T, myucinf, myucinf + theCurve.Period());
409 if (myS->IsUPeriodic())
410 U = ElCLib::InPeriod(U, myuinf, myuinf + myS->UPeriod());
411 if (myS->IsVPeriodic())
412 V = ElCLib::InPeriod(V, myvinf, myvinf + myS->VPeriod());
413
414 Extrema_POnCurv aPC;
415 Extrema_POnSurf aPS;
416 if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
417 (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
418 (myvinf-V) <= mytolS && (V-myvsup) <= mytolS)
419 {
420 Standard_Boolean IsNewSolution = Standard_True;
421 for (Standard_Integer j = 1; j <= mySqDist.Length(); j++)
422 {
423 aPC = myPOnC(j);
424 aPS = myPOnS(j);
425 Standard_Real Tj = aPC.Parameter();
426 Standard_Real Uj, Vj;
427 aPS.Parameter(Uj, Vj);
428 if (Abs(T - Tj) <= mytolC &&
429 Abs(U - Uj) <= mytolS &&
430 Abs(V - Vj) <= mytolS)
431 {
432 IsNewSolution = Standard_False;
433 break;
434 }
435 }
436 if (IsNewSolution)
437 {
438 mySqDist.Append(SquareDist);
439 aPC.SetValues(T, PointOnCurve);
440 myPOnC.Append(aPC);
441 myPOnS.Append(Extrema_POnSurf(U, V, PointOnSurf));
442 Added = Standard_True;
443 }
444 }
445 return Added;
446}