0023404: Create SquareConfusion function in Precision package for speed and convenience
[occt.git] / src / Extrema / Extrema_GExtPC.gxx
CommitLineData
b311480e 1// Created on: 1992-10-19
2// Created by: Laurent PAINNOT
3// Copyright (c) 1992-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// Modified by cma, Fri Dec 10 18:11:56 1993
7fd59977 22
23#include Extrema_EPC_hxx
24#include ThePOnC_hxx
25#include TheSequenceOfPOnC_hxx
26#include ThePoint_hxx
27#include TheVector_hxx
28#include TheExtPElC_hxx
29#include <StdFail_NotDone.hxx>
30#include <Standard_Failure.hxx>
31#include <GeomAbs_CurveType.hxx>
32#include <Precision.hxx>
33#include <ElCLib.hxx>
34#include <TColStd_Array1OfReal.hxx>
35
36
37//=======================================================================
38//function : Perform
39//purpose :
40//=======================================================================
41
42void Extrema_GExtPC::Perform(const ThePoint& P)
43{
44 mySqDist.Clear();
45 mypoint.Clear();
46 myismin.Clear();
47 Standard_Integer i, NbExt, n;
48 Standard_Real U;
49 mysample = 17;
50 Standard_Real t3d = Precision::Confusion();
51 if (Precision::IsInfinite(myuinf)) mydist1 = RealLast();
52 else {
53 Pf = TheCurveTool::Value(*((TheCurve*)myC), myuinf);
54 mydist1 = P.SquareDistance(Pf);
55 }
56
57 if (Precision::IsInfinite(myusup)) mydist2 = RealLast();
58 else {
59 Pl = TheCurveTool::Value(*((TheCurve*)myC), myusup);
60 mydist2 = P.SquareDistance(Pl);
61 }
62
63 switch(type) {
64 case GeomAbs_Circle:
65 {
66 myExtPElC.Perform(P, TheCurveTool::Circle(*((TheCurve*)myC)), t3d, myuinf, myusup);
67 }
68 break;
69 case GeomAbs_Ellipse:
70 {
71 myExtPElC.Perform(P, TheCurveTool::Ellipse(*((TheCurve*)myC)), t3d, myuinf, myusup);
72 }
73 break;
74 case GeomAbs_Parabola:
75 {
76 myExtPElC.Perform(P, TheCurveTool::Parabola(*((TheCurve*)myC)), t3d,myuinf,myusup);
77 }
78 break;
79 case GeomAbs_Hyperbola:
80 {
81 myExtPElC.Perform(P,TheCurveTool::Hyperbola(*((TheCurve*)myC)),t3d, myuinf, myusup);
82 }
83 break;
84 case GeomAbs_Line:
85 {
86 myExtPElC.Perform(P, TheCurveTool::Line(*((TheCurve*)myC)), t3d, myuinf, myusup);
87 }
88 break;
89 case GeomAbs_BezierCurve:
90 {
91 myintuinf = myuinf;
92 myintusup = myusup;
93 mysample = (TheCurveTool::Bezier(*((TheCurve*)myC)))->NbPoles()*2;
94 IntervalPerform(P);
95 return;
96 }
97 case GeomAbs_BSplineCurve:
98 {
99 mysample = (TheCurveTool::BSpline(*((TheCurve*)myC)))->NbPoles()*2;
100 }
101 case GeomAbs_OtherCurve:
102 {
103 Standard_Boolean IntExtIsDone = Standard_False;
104 Standard_Boolean IntIsNotValid;
105 n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2);
106 TColStd_Array1OfReal theInter(1, n+1);
253881cf 107 Standard_Boolean isPeriodic = TheCurveTool::IsPeriodic(*((TheCurve*)myC));
108 Standard_Real aPeriodicShift = 0.;
7fd59977 109 TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2);
110 mysample = Max(mysample/n, 17);
111 TheVector V1;
112 ThePoint PP;
113 Standard_Real s1 = 0.0 ;
114 Standard_Real s2 = 0.0;
115 for (i = 1; i <= n; i++) {
253881cf 116 myintuinf = theInter(i);
117 myintusup = theInter(i+1);
118
119 Standard_Real anInfToCheck = myintuinf;
120 Standard_Real aSupToCheck = myintusup;
121
122 if (isPeriodic) {
123 Standard_Real aPeriod = TheCurveTool::Period(*((TheCurve*)myC));
124 anInfToCheck = ElCLib::InPeriod(myintuinf, myuinf, myuinf+aPeriod);
125 aSupToCheck = myintusup+(anInfToCheck-myintuinf);
126 }
127 IntIsNotValid = (myuinf > aSupToCheck) || (myusup < anInfToCheck);
128
129 if(IntIsNotValid) continue;
130
131 if (myuinf >= anInfToCheck) anInfToCheck = myuinf;
132 if (myusup <= aSupToCheck) aSupToCheck = myusup;
133 if((aSupToCheck - anInfToCheck) <= mytolu) continue;
134
135 if (i != 1) {
136 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, PP, V1);
137 s1 = (TheVector(P, PP))*V1;
138 if (s1*s2 < 0.0) {
139 mySqDist.Append(PP.SquareDistance(P));
140 myismin.Append((s1 < 0.0));
141 mypoint.Append(ThePOnC(myintuinf, PP));
142 }
143 }
144 if (i != n) {
145 TheCurveTool::D1(*((TheCurve*)myC), myintusup, PP, V1);
146 s2 = (TheVector(P, PP))*V1;
147 }
148 IntervalPerform(P);
149 IntExtIsDone = IntExtIsDone || mydone;
7fd59977 150 }
151 mydone = IntExtIsDone;
152 return;
153 }
154 }
155
156
157 mydone = myExtPElC.IsDone();
158 if (mydone) {
159 NbExt = myExtPElC.NbExt();
160 for (i = 1; i <= NbExt; i++) {
161 // Verification de la validite des parametres:
162 ThePOnC PC = myExtPElC.Point(i);
163 U = PC.Parameter();
164 if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) {
253881cf 165 U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC)));
7fd59977 166 }
167 if ((U >= myuinf-mytolu) && (U <= myusup+mytolu)){
253881cf 168 PC.SetValues(U, myExtPElC.Point(i).Value());
169 mySqDist.Append(myExtPElC.SquareDistance(i));
170 myismin.Append(myExtPElC.IsMin(i));
171 mypoint.Append(PC);
7fd59977 172 }
173 }
253881cf 174 }
7fd59977 175}
176
177
178//=======================================================================
179//function : Initialize
180//purpose :
181//=======================================================================
182
183void Extrema_GExtPC::Initialize(const TheCurve& C,
184 const Standard_Real Uinf,
185 const Standard_Real Usup,
186 const Standard_Real TolF)
187{
188 myC = (Standard_Address)&C;
189 myintuinf = myuinf = Uinf;
190 myintusup = myusup = Usup;
191 mytolf = TolF;
192 mytolu = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion());
193 type = TheCurveTool::GetType(C);
194 mydone = Standard_False;
195 mydist1 = RealLast();
196 mydist2 = RealLast();
197 mysample = 17;
198}
199
200
201//=======================================================================
202//function : IntervalPerform
203//purpose :
204//=======================================================================
205
206void Extrema_GExtPC::IntervalPerform(const ThePoint& P)
207{
208 Standard_Integer i;
209 Standard_Real U;
210 myExtPC.Initialize((*((TheCurve*)myC)), mysample,
211 myintuinf, myintusup, mytolu, mytolf);
212 myExtPC.Perform(P);
213 mydone = myExtPC.IsDone();
214 if (mydone) {
215 Standard_Integer NbExt = myExtPC.NbExt();
216 for (i = 1; i <= NbExt; i++) {
217 // Verification de la validite des parametres pour le cas trimme:
218 ThePOnC PC = myExtPC.Point(i);
219 U = PC.Parameter();
220 if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) {
253881cf 221 U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC)));
7fd59977 222 }
223 if ((U >= myuinf - mytolu) && (U <= myusup + mytolu)) {
253881cf 224 PC.SetValues(U, PC.Value());
225 mySqDist.Append(myExtPC.SquareDistance(i));
226 myismin.Append(myExtPC.IsMin(i));
227 mypoint.Append(PC);
7fd59977 228 }
229 }
230 }
231}
232
233
234
235
236//=======================================================================
237//function : Extrema_GExtPC
238//purpose :
239//=======================================================================
240
241Extrema_GExtPC::Extrema_GExtPC()
242{
243 myC = 0;
244 mydone = Standard_False;
245 mydist1 = RealLast();
246 mydist2 = RealLast();
247 mytolu = 0.0;
248 mytolf = 0.0;
249 mysample = 17;
250 myintuinf = myintusup = myuinf = myusup = Precision::Infinite();
251 type = GeomAbs_OtherCurve;
252}
253
254//=======================================================================
255//function : Extrema_GExtPC
256//purpose :
257//=======================================================================
258
259Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P,
260 const TheCurve& C,
261 const Standard_Real Uinf,
262 const Standard_Real Usup,
263 const Standard_Real TolF)
264{
265 Initialize(C, Uinf, Usup, TolF);
266 Perform(P);
267}
268
269//=======================================================================
270//function : Extrema_GExtPC
271//purpose :
272//=======================================================================
273
274Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P,
275 const TheCurve& C,
276 const Standard_Real TolF)
277{
278 Initialize(C, TheCurveTool::FirstParameter(C),
279 TheCurveTool::LastParameter(C), TolF);
280 Perform(P);
281}
282
283
284//=======================================================================
285//function : IsDone
286//purpose :
287//=======================================================================
288
289Standard_Boolean Extrema_GExtPC::IsDone() const
290{
291 return mydone;
292}
293
294
295//=======================================================================
296//function : Value
297//purpose :
298//=======================================================================
299
300Standard_Real Extrema_GExtPC::SquareDistance(const Standard_Integer N) const
301{
302 if(!mydone) StdFail_NotDone::Raise();
303 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
304 return mySqDist.Value(N);
305}
306
307
308//=======================================================================
309//function : NbExt
310//purpose :
311//=======================================================================
312
313Standard_Integer Extrema_GExtPC::NbExt() const
314{
315 if(!mydone) StdFail_NotDone::Raise();
316 return mySqDist.Length();
317}
318
319
320//=======================================================================
321//function : IsMin
322//purpose :
323//=======================================================================
324
325Standard_Boolean Extrema_GExtPC::IsMin(const Standard_Integer N) const
326{
327 if(!mydone) StdFail_NotDone::Raise();
328 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
329 return myismin.Value(N);
330}
331
332
333
334//=======================================================================
335//function : Point
336//purpose :
337//=======================================================================
338
339ThePOnC Extrema_GExtPC::Point(const Standard_Integer N) const
340{
341 if(!mydone) StdFail_NotDone::Raise();
342 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
343 return mypoint.Value(N);
344}
345
346
347//=======================================================================
348//function : TrimmedDistances
349//purpose :
350//=======================================================================
351
352void Extrema_GExtPC::TrimmedSquareDistances(Standard_Real& dist1,
353 Standard_Real& dist2,
354 ThePoint& P1,
355 ThePoint& P2) const
356{
357 dist1 = mydist1;
358 dist2 = mydist2;
359 P1 = Pf;
360 P2 = Pl;
361}
362