1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
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>
29 #include <gp_Vec2d.hxx>
32 static Standard_Real GetParameterLengthRatio(const TheCurve& C)
34 switch (C.GetType()) {
37 return C.Circle().Radius();
42 case GeomAbs_BezierCurve :
43 case GeomAbs_BSplineCurve :
46 return C.DN(0., 1).Magnitude();
58 static GCPnts_AbscissaType GetAbsType(const TheCurve& C)
60 if (C.NbIntervals(GeomAbs_C1) > 1)
61 return GCPnts_AbsComposite;
63 switch (C.GetType()) {
67 return GCPnts_LengthParametrized;
68 case GeomAbs_BezierCurve:
70 Handle_TheBezierCurve BZ = C.Bezier();
71 if (BZ->NbPoles() == 2 && !BZ->IsRational())
72 return GCPnts_LengthParametrized;
74 return GCPnts_Parametrized;
76 case GeomAbs_BSplineCurve:
78 Handle_TheBSplineCurve BS = C.BSpline() ;
79 if (BS->NbPoles() == 2 && !BS->IsRational())
80 return GCPnts_LengthParametrized;
82 return GCPnts_Parametrized;
85 return GCPnts_Parametrized ;
89 static Standard_Boolean Perform(Handle(TColStd_HArray1OfReal)& HParameters,
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)
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;
108 // this initialization avoids the computation of the Length
111 Delta = (Abscissa/TotalLength) * (UU2 - UU1) ;
113 HParameters->SetValue(Index,UU1) ;
115 Ui = HParameters->Value(Index) + Delta;
117 // MSV 21.04.2004: OCC5739 (GCPnts_UniformAbscissa gives incorrect
118 // distribution of points)
119 // if (UU2 - HParameters->Value(Index) > 0.01*Delta) {
122 // HParameters->SetValue(Index, UU2);
123 // NotDone = Standard_False;
127 GCPnts_AbscissaPoint AbscissaFinder(C,
129 HParameters->Value(Index),
132 if (AbscissaFinder.IsDone()) {
134 Ui = AbscissaFinder.Parameter();
135 if (Abs(Ui-UU2) <= EPSILON) {
136 HParameters->SetValue(Index, UU2);
137 NotDone = Standard_False;
140 HParameters->SetValue(Index, Ui);
143 HParameters->SetValue(Index, UU2);
144 NotDone = Standard_False;
146 NotDone = NotDone && (Index + 1 <= HParameters->Length()) ;
150 LocalDone = Standard_False ;
151 NotDone = Standard_True ;
153 if (Delta <= Precision::PConfusion()) break;
161 static Standard_Boolean
162 PerformLengthParametrized( Handle(TColStd_HArray1OfReal)& HParameters,
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)
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 ;
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);
185 if (Abscissa < 0.0e0) {
189 Delta = (Abscissa/TotalLength) * (UU2 - UU1) ;
192 HParameters->SetValue(Index,UU1) ;
195 Ui = HParameters->Value(Index-1) + Delta;
196 if (Abs(Ui-UU2) <= EPSILON) {
197 HParameters->SetValue(Index, UU2);
198 NotDone = Standard_False;
201 HParameters->SetValue(Index, Ui);
204 NotDone = Standard_False;
205 if (Abs(HParameters->Value(Index-1) - UU2)*Ratio/Abscissa < 0.1) {
206 HParameters->SetValue(Index-1, UU2);
210 HParameters->SetValue(Index, UU2);
212 NotDone = (Index+1 <= HParameters->Length()) && NotDone ;
216 return Standard_True ;
220 //=======================================================================
221 //function : Initialize
223 //=======================================================================
225 void GCPnts_UniformAbscissa::Initialize (const TheCurve& C,
226 const Standard_Real Abscissa,
227 const Standard_Real Tol)
229 Initialize(C, Abscissa, C.FirstParameter(),
230 C.LastParameter(), Tol);
233 //=======================================================================
234 //function : GCPnts_UniformAbscissa
236 //=======================================================================
238 GCPnts_UniformAbscissa::GCPnts_UniformAbscissa (const TheCurve& C,
239 const Standard_Real Abscissa,
240 const Standard_Real Tol)
242 Initialize(C, Abscissa, Tol);
245 //=======================================================================
246 //function : GCPnts_UniformAbscissa
248 //=======================================================================
250 GCPnts_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)
256 Initialize(C, Abscissa, U1, U2, Tol);
259 //=======================================================================
260 //function : GCPnts_UniformAbscissa
262 //=======================================================================
264 GCPnts_UniformAbscissa::GCPnts_UniformAbscissa(const TheCurve& C,
265 const Standard_Integer NbPoints,
266 const Standard_Real Tol)
268 Initialize(C, NbPoints, Tol);
271 //=======================================================================
272 //function : GCPnts_UniformAbscissa
274 //=======================================================================
276 GCPnts_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)
282 Initialize(C, NbPoints, U1, U2, Tol);
285 //=======================================================================
286 //function : Initialize
288 //=======================================================================
290 void 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)
297 myAbscissa = Abscissa;
299 myDone = Standard_False;
300 Standard_Real EPSILON;
302 if(Tol < Precision::Confusion())
303 EPSILON = C.Resolution(Precision::Confusion());
305 EPSILON = C.Resolution(Tol);
307 L = GCPnts_AbscissaPoint::Length(C, U1, U2, EPSILON);
308 if (L <= Precision::Confusion()) {
311 Standard_Integer size ;
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
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;
330 if (!myParams.IsNull()) {
331 if (myParams->Length() < size) {
334 TColStd_HArray1OfReal(1,size) ;
339 TColStd_HArray1OfReal(1,size) ;
342 // Standard_Real EPSILON = C.Resolution(Precision::Confusion());
343 GCPnts_AbscissaType Type = GetAbsType(C);
345 case GCPnts_LengthParametrized :
346 myDone = PerformLengthParametrized(myParams,
355 case GCPnts_Parametrized:
356 case GCPnts_AbsComposite:
357 myDone = Perform(myParams,
370 //=======================================================================
371 //function : Initialize
373 //=======================================================================
375 void GCPnts_UniformAbscissa::Initialize(const TheCurve& C,
376 const Standard_Integer NbPoints,
377 const Standard_Real Tol)
379 Initialize(C, NbPoints, C.FirstParameter(),
380 C.LastParameter(), Tol);
384 //=======================================================================
385 //function : Initialize
387 //=======================================================================
389 void 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)
395 Standard_ConstructionError_Raise_if(NbPoints <= 1, "");
396 Standard_Real Abscissa ;
398 myDone = Standard_False;
399 Standard_Real EPSILON;
401 if(Tol < Precision::Confusion())
402 EPSILON = C.Resolution(Precision::Confusion());
404 EPSILON = C.Resolution(Tol);
407 // although very similar to Initialize with Abscissa this avoid
408 // the computation of the total length of the curve twice
410 Standard_Real L = GCPnts_AbscissaPoint::Length(C, U1, U2, EPSILON) ;
412 if (L <= Precision::Confusion()) {
417 myAbscissa = L / (NbPoints - 1);
419 Standard_Integer size ;
422 // compute the total Length here so that we can
423 // guess the number of points instead of letting the
424 // constructor of CPnts_AbscissaPoint do that and loosing
429 size = NbPoints + 5 ;
432 if (!myParams.IsNull()) {
433 if (myParams->Length() < size) {
436 TColStd_HArray1OfReal(1,size) ;
441 TColStd_HArray1OfReal(1,size) ;
446 GCPnts_AbscissaType Type = GetAbsType(C);
448 case GCPnts_LengthParametrized:
449 myDone = PerformLengthParametrized(myParams,
458 case GCPnts_Parametrized:
459 case GCPnts_AbsComposite:
460 myDone = Perform(myParams,