0028550: Foundation Classes - fix empty message passed to thrown exception
[occt.git] / src / GCPnts / GCPnts_UniformAbscissa.pxx
... / ...
CommitLineData
1// Copyright (c) 1995-1999 Matra Datavision
2// Copyright (c) 1999-2014 OPEN CASCADE SAS
3//
4// This file is part of Open CASCADE Technology software library.
5//
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
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.
11//
12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
14
15#include <StdFail_NotDone.hxx>
16#include <Standard_DomainError.hxx>
17#include <Standard_OutOfRange.hxx>
18#include <Standard_ConstructionError.hxx>
19#include <GCPnts_AbscissaType.hxx>
20#include <TColStd_HArray1OfReal.hxx>
21#include <TColStd_Array1OfReal.hxx>
22#include <GeomAbs_CurveType.hxx>
23#include <CPnts_AbscissaPoint.hxx>
24#include <GCPnts_AbscissaPoint.hxx>
25#include <Precision.hxx>
26#include <gp_Circ.hxx>
27#include <gp_Circ2d.hxx>
28#include <gp_Vec.hxx>
29#include <gp_Vec2d.hxx>
30
31
32static Standard_Real GetParameterLengthRatio(const TheCurve& C)
33{
34 switch (C.GetType()) {
35
36 case GeomAbs_Circle :
37 return C.Circle().Radius();
38
39 case GeomAbs_Line :
40 return 1.;
41
42 case GeomAbs_BezierCurve :
43 case GeomAbs_BSplineCurve :
44 {
45 if (!C.IsRational())
46 return C.DN(0., 1).Magnitude();
47 else
48 return RealLast();
49 }
50
51 default :
52 return RealLast();
53
54 }
55}
56
57
58static GCPnts_AbscissaType GetAbsType(const TheCurve& C)
59{
60 if (C.NbIntervals(GeomAbs_C1) > 1)
61 return GCPnts_AbsComposite;
62
63 switch (C.GetType()) {
64
65 case GeomAbs_Line:
66 case GeomAbs_Circle:
67 return GCPnts_LengthParametrized;
68 case GeomAbs_BezierCurve:
69 {
70 Handle_TheBezierCurve BZ = C.Bezier();
71 if (BZ->NbPoles() == 2 && !BZ->IsRational())
72 return GCPnts_LengthParametrized;
73 else
74 return GCPnts_Parametrized;
75 }
76 case GeomAbs_BSplineCurve:
77 {
78 Handle_TheBSplineCurve BS = C.BSpline() ;
79 if (BS->NbPoles() == 2 && !BS->IsRational())
80 return GCPnts_LengthParametrized;
81 else
82 return GCPnts_Parametrized;
83 }
84 default:
85 return GCPnts_Parametrized ;
86 }
87}
88
89static Standard_Boolean Perform(Handle(TColStd_HArray1OfReal)& HParameters,
90 const TheCurve& C,
91 const Standard_Real Abscissa,
92 const Standard_Real U1,
93 const Standard_Real U2,
94 const Standard_Real TotalLength,
95 Standard_Integer &NbPoints,
96 const Standard_Real EPSILON)
97{
98 Standard_Boolean NotDone = Standard_True;
99 Standard_Boolean LocalDone = Standard_True;
100// Standard_Boolean Forward = Standard_True ;
101 Standard_Real UU1 = Min(U1, U2), UU2 = Max(U1, U2) ;
102 Standard_Integer Index ;
103// Standard_Real UCurrent, Delta, Ui;
104 Standard_Real Delta, Ui;
105 NbPoints = 0 ;
106
107//
108// this initialization avoids the computation of the Length
109// of the curve
110
111 Delta = (Abscissa/TotalLength) * (UU2 - UU1) ;
112 Index = 1 ;
113 HParameters->SetValue(Index,UU1) ;
114 while (NotDone) {
115 Ui = HParameters->Value(Index) + Delta;
116 if (Ui > UU2) {
117 // MSV 21.04.2004: OCC5739 (GCPnts_UniformAbscissa gives incorrect
118 // distribution of points)
119// if (UU2 - HParameters->Value(Index) > 0.01*Delta) {
120// Index += 1;
121// }
122// HParameters->SetValue(Index, UU2);
123// NotDone = Standard_False;
124// break;
125 Ui = UU2;
126 }
127 GCPnts_AbscissaPoint AbscissaFinder(C,
128 Abscissa,
129 HParameters->Value(Index),
130 Ui,
131 EPSILON) ;
132 if (AbscissaFinder.IsDone()) {
133 Index += 1 ;
134 Ui = AbscissaFinder.Parameter();
135 if (Abs(Ui-UU2) <= EPSILON) {
136 HParameters->SetValue(Index, UU2);
137 NotDone = Standard_False;
138 }
139 else if (Ui < UU2) {
140 HParameters->SetValue(Index, Ui);
141 }
142 else {
143 HParameters->SetValue(Index, UU2);
144 NotDone = Standard_False;
145 }
146 NotDone = NotDone && (Index + 1 <= HParameters->Length()) ;
147 }
148 else {
149
150 LocalDone = Standard_False ;
151 NotDone = Standard_True ;
152 Delta -= Delta/10;
153 if (Delta <= Precision::PConfusion()) break;
154 }
155 }
156 NbPoints = Index ;
157 return (LocalDone) ;
158}
159
160
161static Standard_Boolean
162PerformLengthParametrized( Handle(TColStd_HArray1OfReal)& HParameters,
163 const TheCurve& C,
164 const Standard_Real Abscissa,
165 const Standard_Real U1,
166 const Standard_Real U2,
167 const Standard_Real TotalLength,
168 Standard_Integer &NbPoints,
169 const Standard_Real EPSILON)
170{
171 Standard_Boolean NotDone = Standard_True;
172// Standard_Boolean LocalDone = Standard_True;
173 Standard_Real UU1 = Min(U1, U2);
174// Standard_Real UCurrent;
175 Standard_Real Delta, Ui;
176 Standard_Real UU2 = Max(U1, U2);
177 Standard_Integer Index ;
178
179// Ratio is defined as dl = Ratio * du
180// for a circle of gp Ratio is equal to the radius of the circle.
181// for a line of gp ratio is equal to 1.0
182 Standard_Real Ratio = GetParameterLengthRatio(C);
183
184
185 if (Abscissa < 0.0e0) {
186 UU2 = Min(U1, U2);
187 UU1 = Max(U1, U2);
188 }
189 Delta = (Abscissa/TotalLength) * (UU2 - UU1) ;
190 Index = 1 ;
191 NbPoints = 0 ;
192 HParameters->SetValue(Index,UU1) ;
193 while (NotDone) {
194 Index += 1 ;
195 Ui = HParameters->Value(Index-1) + Delta;
196 if (Abs(Ui-UU2) <= EPSILON) {
197 HParameters->SetValue(Index, UU2);
198 NotDone = Standard_False;
199 }
200 else if (Ui < UU2) {
201 HParameters->SetValue(Index, Ui);
202 }
203 else {
204 NotDone = Standard_False;
205 if (Abs(HParameters->Value(Index-1) - UU2)*Ratio/Abscissa < 0.1) {
206 HParameters->SetValue(Index-1, UU2);
207 Index -= 1;
208 }
209 else
210 HParameters->SetValue(Index, UU2);
211 }
212 NotDone = (Index+1 <= HParameters->Length()) && NotDone ;
213 }
214
215 NbPoints = Index ;
216 return Standard_True ;
217}
218
219
220//=======================================================================
221//function : Initialize
222//purpose :
223//=======================================================================
224
225void GCPnts_UniformAbscissa::Initialize (const TheCurve& C,
226 const Standard_Real Abscissa,
227 const Standard_Real Tol)
228{
229 Initialize(C, Abscissa, C.FirstParameter(),
230 C.LastParameter(), Tol);
231}
232
233//=======================================================================
234//function : GCPnts_UniformAbscissa
235//purpose :
236//=======================================================================
237
238GCPnts_UniformAbscissa::GCPnts_UniformAbscissa (const TheCurve& C,
239 const Standard_Real Abscissa,
240 const Standard_Real Tol)
241{
242 Initialize(C, Abscissa, Tol);
243}
244
245//=======================================================================
246//function : GCPnts_UniformAbscissa
247//purpose :
248//=======================================================================
249
250GCPnts_UniformAbscissa::GCPnts_UniformAbscissa (const TheCurve& C,
251 const Standard_Real Abscissa,
252 const Standard_Real U1,
253 const Standard_Real U2,
254 const Standard_Real Tol)
255{
256 Initialize(C, Abscissa, U1, U2, Tol);
257}
258
259//=======================================================================
260//function : GCPnts_UniformAbscissa
261//purpose :
262//=======================================================================
263
264GCPnts_UniformAbscissa::GCPnts_UniformAbscissa(const TheCurve& C,
265 const Standard_Integer NbPoints,
266 const Standard_Real Tol)
267{
268 Initialize(C, NbPoints, Tol);
269}
270
271//=======================================================================
272//function : GCPnts_UniformAbscissa
273//purpose :
274//=======================================================================
275
276GCPnts_UniformAbscissa::GCPnts_UniformAbscissa(const TheCurve& C,
277 const Standard_Integer NbPoints,
278 const Standard_Real U1,
279 const Standard_Real U2,
280 const Standard_Real Tol)
281{
282 Initialize(C, NbPoints, U1, U2, Tol);
283}
284
285//=======================================================================
286//function : Initialize
287//purpose :
288//=======================================================================
289
290void GCPnts_UniformAbscissa::Initialize(const TheCurve& C,
291 const Standard_Real Abscissa,
292 const Standard_Real U1,
293 const Standard_Real U2,
294 const Standard_Real Tol)
295{
296 Standard_Real L ;
297 myAbscissa = Abscissa;
298 myNbPoints = 0 ;
299 myDone = Standard_False;
300 Standard_Real EPSILON;
301
302 if(Tol < Precision::Confusion())
303 EPSILON = C.Resolution(Precision::Confusion());
304 else
305 EPSILON = C.Resolution(Tol);
306
307 L = GCPnts_AbscissaPoint::Length(C, U1, U2, EPSILON);
308 if (L <= Precision::Confusion()) {
309 return;
310 }
311 Standard_Integer size ;
312
313//
314// compute the total Length here so that we can
315// guess the number of points instead of letting the
316// constructor of CPnts_AbscissaPoint do that and loosing
317// the information
318//
319//
320
321// modified by Igor Motchalov 23/04/2001
322// size = (Standard_Integer )( (L/Abs(Abscissa)) + 5 );
323 Standard_Real sizeR=L/Abs(Abscissa) + 5;
324 if (sizeR < IntegerLast()) {
325 size=(Standard_Integer) sizeR;
326 } else {
327 return;
328 }
329
330 if (!myParams.IsNull()) {
331 if (myParams->Length() < size) {
332 myParams.Nullify() ;
333 myParams = new
334 TColStd_HArray1OfReal(1,size) ;
335 }
336 }
337 else {
338 myParams = new
339 TColStd_HArray1OfReal(1,size) ;
340 }
341
342// Standard_Real EPSILON = C.Resolution(Precision::Confusion());
343 GCPnts_AbscissaType Type = GetAbsType(C);
344 switch (Type) {
345 case GCPnts_LengthParametrized :
346 myDone = PerformLengthParametrized(myParams,
347 C,
348 Abscissa,
349 U1,
350 U2,
351 L,
352 myNbPoints,
353 EPSILON);
354 break;
355 case GCPnts_Parametrized:
356 case GCPnts_AbsComposite:
357 myDone = Perform(myParams,
358 C,
359 Abscissa,
360 U1,
361 U2,
362 L,
363 myNbPoints,
364 EPSILON);
365 break;
366 }
367}
368
369
370//=======================================================================
371//function : Initialize
372//purpose :
373//=======================================================================
374
375void GCPnts_UniformAbscissa::Initialize(const TheCurve& C,
376 const Standard_Integer NbPoints,
377 const Standard_Real Tol)
378{
379 Initialize(C, NbPoints, C.FirstParameter(),
380 C.LastParameter(), Tol);
381}
382
383
384//=======================================================================
385//function : Initialize
386//purpose :
387//=======================================================================
388
389void GCPnts_UniformAbscissa::Initialize(const TheCurve& C,
390 const Standard_Integer NbPoints,
391 const Standard_Real U1,
392 const Standard_Real U2,
393 const Standard_Real Tol)
394{
395 Standard_ConstructionError_Raise_if (NbPoints <= 1,
396 "GCPnts_UniformAbscissa::Initialize() - number of points should be >= 2");
397 Standard_Real Abscissa ;
398 myNbPoints = 0 ;
399 myDone = Standard_False;
400 Standard_Real EPSILON;
401
402 if(Tol < Precision::Confusion())
403 EPSILON = C.Resolution(Precision::Confusion());
404 else
405 EPSILON = C.Resolution(Tol);
406
407//
408// although very similar to Initialize with Abscissa this avoid
409// the computation of the total length of the curve twice
410//
411 Standard_Real L = GCPnts_AbscissaPoint::Length(C, U1, U2, EPSILON) ;
412
413 if (L <= Precision::Confusion()) {
414 return;
415 }
416
417 Abscissa =
418 myAbscissa = L / (NbPoints - 1);
419
420 Standard_Integer size ;
421
422//
423// compute the total Length here so that we can
424// guess the number of points instead of letting the
425// constructor of CPnts_AbscissaPoint do that and loosing
426// the information
427//
428//
429
430 size = NbPoints + 5 ;
431
432
433 if (!myParams.IsNull()) {
434 if (myParams->Length() < size) {
435 myParams.Nullify() ;
436 myParams = new
437 TColStd_HArray1OfReal(1,size) ;
438 }
439 }
440 else {
441 myParams = new
442 TColStd_HArray1OfReal(1,size) ;
443 }
444
445
446 myNbPoints = 0 ;
447 GCPnts_AbscissaType Type = GetAbsType(C);
448 switch (Type) {
449 case GCPnts_LengthParametrized:
450 myDone = PerformLengthParametrized(myParams,
451 C,
452 Abscissa,
453 U1,
454 U2,
455 L,
456 myNbPoints,
457 EPSILON);
458 break;
459 case GCPnts_Parametrized:
460 case GCPnts_AbsComposite:
461 myDone = Perform(myParams,
462 C,
463 Abscissa,
464 U1,
465 U2,
466 L,
467 myNbPoints,
468 EPSILON);
469 break;
470 }
471}
472
473
474
475
476
477