0025861: Wrong result obtained by projection algorithm.
[occt.git] / src / Extrema / Extrema_ExtPS.cxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 15//-----------------------------------------------------------------
7fd59977 16
17#include <Extrema_ExtPS.ixx>
18#include <Extrema_GenExtPS.hxx>
19#include <StdFail_NotDone.hxx>
20#include <Standard_NotImplemented.hxx>
21#include <Precision.hxx>
22#include <GeomAbs_CurveType.hxx>
0734c53d 23#include <Adaptor3d_HSurfaceOfRevolution.hxx>
24#include <Adaptor3d_HSurfaceOfLinearExtrusion.hxx>
7fd59977 25#include <ElCLib.hxx>
26#include <gp_Pnt.hxx>
27#include <gp_Pln.hxx>
28#include <gp_Cylinder.hxx>
29#include <gp_Cone.hxx>
30#include <gp_Sphere.hxx>
31#include <gp_Torus.hxx>
32#include <Extrema_ExtPExtS.hxx>
33#include <Extrema_ExtPRevS.hxx>
34#include <Extrema_POnSurf.hxx>
35#include <GeomAbs_IsoType.hxx>
36
37//=======================================================================
38//function : IsoIsDeg
39//purpose :
40//=======================================================================
41
42static Standard_Boolean IsoIsDeg (const Adaptor3d_Surface& S,
43 const Standard_Real Param,
44 const GeomAbs_IsoType IT,
45 const Standard_Real TolMin,
46 const Standard_Real TolMax)
47{
48 Standard_Real U1=0.,U2=0.,V1=0.,V2=0.,T;
49 Standard_Boolean Along = Standard_True;
50 U1 = S.FirstUParameter();
51 U2 = S.LastUParameter();
52 V1 = S.FirstVParameter();
53 V2 = S.LastVParameter();
54 gp_Vec D1U,D1V;
55 gp_Pnt P;
56 Standard_Real Step,D1NormMax;
57 if (IT == GeomAbs_IsoV)
58 {
5368adff 59 if( !Precision::IsInfinite(U1) && !Precision::IsInfinite(U2) )
7fd59977 60 {
5368adff 61 Step = (U2 - U1)/10;
62 if(Step < Precision::PConfusion()) {
63 return Standard_False;
64 }
65 D1NormMax=0.;
66
67 for (T=U1;T<=U2;T=T+Step)
68 {
69 S.D1(T,Param,P,D1U,D1V);
70 D1NormMax=Max(D1NormMax,D1U.Magnitude());
71 }
72
73 if (D1NormMax >TolMax || D1NormMax < TolMin )
74 Along = Standard_False;
7fd59977 75 }
7fd59977 76 }
77 else
78 {
5368adff 79 if( !Precision::IsInfinite(V1) && !Precision::IsInfinite(V2) )
7fd59977 80 {
5368adff 81 Step = (V2 - V1)/10;
82 if(Step < Precision::PConfusion()) {
83 return Standard_False;
84 }
85 D1NormMax=0.;
86 for (T=V1;T<=V2;T=T+Step)
87 {
88 S.D1(Param,T,P,D1U,D1V);
89 D1NormMax=Max(D1NormMax,D1V.Magnitude());
90 }
91
92 if (D1NormMax >TolMax || D1NormMax < TolMin )
93 Along = Standard_False;
7fd59977 94 }
95
7fd59977 96
97
98 }
99 return Along;
100}
101
102//=======================================================================
103//function : TreatSolution
104//purpose :
105//=======================================================================
106
107void Extrema_ExtPS::TreatSolution (const Extrema_POnSurf& PS,
108 const Standard_Real Val)
109{
110 Standard_Real U, V;
111 PS.Parameter(U, V);
112 if (myS->IsUPeriodic()) {
9bf3177f 113 U = ElCLib::InPeriod(U, myuinf, myuinf + myS->UPeriod());
114
115 // Handle trimmed surfaces.
116 if (U > myusup + mytolu)
117 U -= myS->UPeriod();
118 if (U < myuinf - mytolu)
119 U += myS->UPeriod();
7fd59977 120 }
121 if (myS->IsVPeriodic()) {
9bf3177f 122 V = ElCLib::InPeriod(V, myvinf, myvinf + myS->VPeriod());
123
124 // Handle trimmed surfaces.
125 if (V > myvsup + mytolv)
126 V -= myS->VPeriod();
127 if (V < myvinf - mytolv)
128 V += myS->VPeriod();
7fd59977 129 }
130 if ((myuinf-U) <= mytolu && (U-myusup) <= mytolu &&
131 (myvinf-V) <= mytolv && (V-myvsup) <= mytolv) {
132 myPoints.Append(Extrema_POnSurf (U, V, PS.Value()));
133 mySqDist.Append(Val);
134 }
135}
136
137
138//=======================================================================
139//function : Extrema_ExtPS
140//purpose :
141//=======================================================================
142
0734c53d 143Extrema_ExtPS::Extrema_ExtPS()
7fd59977 144{
145 myDone = Standard_False;
146}
147
148
149//=======================================================================
150//function : Extrema_ExtPS
151//purpose :
152//=======================================================================
153
0734c53d 154Extrema_ExtPS::Extrema_ExtPS (const gp_Pnt& theP,
155 const Adaptor3d_Surface& theS,
156 const Standard_Real theTolU,
157 const Standard_Real theTolV,
158 const Extrema_ExtFlag theF,
159 const Extrema_ExtAlgo theA)
7fd59977 160{
0734c53d 161 myExtPS.SetFlag (theF);
162 myExtPS.SetAlgo (theA);
163
164 Initialize (theS,
165 theS.FirstUParameter(),
166 theS.LastUParameter(),
167 theS.FirstVParameter(),
168 theS.LastVParameter(),
169 theTolU,
170 theTolV);
171
172 Perform (theP);
7fd59977 173}
174
175//=======================================================================
176//function : Extrema_ExtPS
177//purpose :
178//=======================================================================
179
0734c53d 180Extrema_ExtPS::Extrema_ExtPS (const gp_Pnt& theP,
181 const Adaptor3d_Surface& theS,
182 const Standard_Real theUinf,
183 const Standard_Real theUsup,
184 const Standard_Real theVinf,
185 const Standard_Real theVsup,
186 const Standard_Real theTolU,
187 const Standard_Real theTolV,
188 const Extrema_ExtFlag theF,
189 const Extrema_ExtAlgo theA)
7fd59977 190{
0734c53d 191 myExtPS.SetFlag (theF);
192 myExtPS.SetAlgo (theA);
193
194 Initialize (theS,
195 theUinf,
196 theUsup,
197 theVinf,
198 theVsup,
199 theTolU,
200 theTolV);
201
202 Perform (theP);
7fd59977 203}
204
205
206//=======================================================================
207//function : Initialize
208//purpose :
209//=======================================================================
210
0734c53d 211void Extrema_ExtPS::Initialize (const Adaptor3d_Surface& theS,
212 const Standard_Real theUinf,
213 const Standard_Real theUsup,
214 const Standard_Real theVinf,
215 const Standard_Real theVsup,
216 const Standard_Real theTolU,
217 const Standard_Real theTolV)
7fd59977 218{
0734c53d 219 myS = (Adaptor3d_SurfacePtr)&theS;
220 myuinf = theUinf;
221 myusup = theUsup;
222 myvinf = theVinf;
223 myvsup = theVsup;
7fd59977 224
225 if (Precision::IsNegativeInfinite(myuinf)) myuinf = -1e10;
226 if (Precision::IsPositiveInfinite(myusup)) myusup = 1e10;
227 if (Precision::IsNegativeInfinite(myvinf)) myvinf = -1e10;
228 if (Precision::IsPositiveInfinite(myvsup)) myvsup = 1e10;
229
0734c53d 230 mytolu = theTolU;
231 mytolv = theTolV;
7fd59977 232 mytype = myS->GetType();
233
234 Standard_Boolean isB = ( myS->GetType() == GeomAbs_BSplineSurface ||
0734c53d 235 myS->GetType() == GeomAbs_BezierSurface );
7fd59977 236
237 Standard_Integer nbU = (isB) ? 44 : 32;
238 Standard_Integer nbV = (isB) ? 44 : 32;
239
240 Standard_Boolean bUIsoIsDeg = Standard_False, bVIsoIsDeg = Standard_False;
241
242 if(myS->GetType() != GeomAbs_Plane) {
0734c53d 243 bUIsoIsDeg = IsoIsDeg(theS, myuinf, GeomAbs_IsoU, 0., 1.e-9) ||
244 IsoIsDeg(theS, myusup, GeomAbs_IsoU, 0., 1.e-9);
245 bVIsoIsDeg = IsoIsDeg(theS, myvinf, GeomAbs_IsoV, 0., 1.e-9) ||
246 IsoIsDeg(theS, myvsup, GeomAbs_IsoV, 0., 1.e-9);
7fd59977 247 }
248
249 if(bUIsoIsDeg) nbU = 300;
250 if(bVIsoIsDeg) nbV = 300;
251
252 myExtPS.Initialize(*myS, nbU, nbV, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
0734c53d 253
254 myExtPExtS.Nullify();
255 myExtPRevS.Nullify();
7fd59977 256}
257
258//=======================================================================
259//function : Perform
260//purpose :
261//=======================================================================
262
0734c53d 263void Extrema_ExtPS::Perform(const gp_Pnt& thePoint)
7fd59977 264{
265 myPoints.Clear();
266 mySqDist.Clear();
0734c53d 267
268 switch (mytype)
269 {
270 case GeomAbs_Cylinder:
271 myExtPElS.Perform (thePoint, myS->Cylinder(), Precision::Confusion());
272 break;
273 case GeomAbs_Plane:
274 myExtPElS.Perform (thePoint, myS->Plane(), Precision::Confusion());
275 break;
276 case GeomAbs_Cone:
277 myExtPElS.Perform (thePoint, myS->Cone(), Precision::Confusion());
278 break;
279 case GeomAbs_Sphere:
280 myExtPElS.Perform (thePoint, myS->Sphere(), Precision::Confusion());
281 break;
282 case GeomAbs_Torus:
283 myExtPElS.Perform (thePoint, myS->Torus(), Precision::Confusion());
284 break;
285
286 case GeomAbs_SurfaceOfExtrusion:
287 {
288 if (myExtPExtS.IsNull())
289 {
290 Handle(Adaptor3d_HSurfaceOfLinearExtrusion) aS (new Adaptor3d_HSurfaceOfLinearExtrusion (
291 Adaptor3d_SurfaceOfLinearExtrusion (myS->BasisCurve(), myS->Direction())));
292
293 myExtPExtS = new Extrema_ExtPExtS (thePoint, aS, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
294 }
295 else
296 {
297 myExtPExtS->Perform (thePoint);
7fd59977 298 }
7fd59977 299
0734c53d 300 myDone = myExtPExtS->IsDone();
301 if (myDone)
302 {
303 for (Standard_Integer anIdx = 1; anIdx <= myExtPExtS->NbExt(); ++anIdx)
304 {
305 TreatSolution (myExtPExtS->Point (anIdx), myExtPExtS->SquareDistance (anIdx));
306 }
7fd59977 307 }
7fd59977 308
0734c53d 309 return;
310 }
311
312 case GeomAbs_SurfaceOfRevolution:
313 {
314 if (myExtPRevS.IsNull())
315 {
316 Handle(Adaptor3d_HSurfaceOfRevolution) aS (new Adaptor3d_HSurfaceOfRevolution (
317 Adaptor3d_SurfaceOfRevolution (myS->BasisCurve(), myS->AxeOfRevolution())));
318
319 myExtPRevS = new Extrema_ExtPRevS (thePoint, aS, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
320 }
321 else
322 {
323 myExtPRevS->Perform (thePoint);
324 }
325
326 myDone = myExtPRevS->IsDone();
327 if (myDone)
328 {
329 for (Standard_Integer anIdx = 1; anIdx <= myExtPRevS->NbExt(); ++anIdx)
330 {
331 TreatSolution (myExtPRevS->Point (anIdx), myExtPRevS->SquareDistance (anIdx));
332 }
333 }
334
335 return;
336 }
337
338 default:
339 {
340 myExtPS.Perform (thePoint);
341 myDone = myExtPS.IsDone();
342 if (myDone)
343 {
344 for (Standard_Integer anIdx = 1; anIdx <= myExtPS.NbExt(); ++anIdx)
345 {
346 TreatSolution (myExtPS.Point (anIdx), myExtPS.SquareDistance (anIdx));
347 }
348 }
349 return;
350 }
7fd59977 351 }
352
7fd59977 353 myDone = myExtPElS.IsDone();
0734c53d 354 if (myDone)
355 {
356 for (Standard_Integer anIdx = 1; anIdx <= myExtPElS.NbExt(); ++anIdx)
357 {
358 TreatSolution (myExtPElS.Point (anIdx), myExtPElS.SquareDistance (anIdx));
359 }
360 }
7fd59977 361}
362
363
7fd59977 364Standard_Boolean Extrema_ExtPS::IsDone() const
365{
366 return myDone;
367}
368
369
370Standard_Real Extrema_ExtPS::SquareDistance(const Standard_Integer N) const
371{
372 if(!myDone) StdFail_NotDone::Raise();
373 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
374 return mySqDist.Value(N);
375}
376
377
378Standard_Integer Extrema_ExtPS::NbExt() const
379{
380 if(!myDone) StdFail_NotDone::Raise();
381 return mySqDist.Length();
382}
383
384
5d99f2c8 385const Extrema_POnSurf& Extrema_ExtPS::Point(const Standard_Integer N) const
7fd59977 386{
387 if(!myDone) StdFail_NotDone::Raise();
388 return myPoints.Value(N);
389}
390
391
392void Extrema_ExtPS::TrimmedSquareDistances(Standard_Real& dUfVf,
393 Standard_Real& dUfVl,
394 Standard_Real& dUlVf,
395 Standard_Real& dUlVl,
396 gp_Pnt& PUfVf,
397 gp_Pnt& PUfVl,
398 gp_Pnt& PUlVf,
399 gp_Pnt& PUlVl) const
400{
401 dUfVf = d11;
402 dUfVl = d12;
403 dUlVf = d21;
404 dUlVl = d22;
405 PUfVf = P11;
406 PUfVl = P12;
407 PUlVf = P21;
408 PUlVl = P22;
409}
92d1589b
A
410
411void Extrema_ExtPS::SetFlag(const Extrema_ExtFlag F)
412{
413 myExtPS.SetFlag(F);
414}
415
416void Extrema_ExtPS::SetAlgo(const Extrema_ExtAlgo A)
417{
418 myExtPS.SetAlgo(A);
0d969553 419}