1 // Created on: 1995-05-05
2 // Created by: Modelistation
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Dimension independant used to implement GCPnts_AbscissaPoint
20 // and the length ratio if GCPnts_LengthParametrized
21 #include <GCPnts_AbscissaType.hxx>
23 #include <gp_Vec2d.hxx>
24 #include <gp_Circ.hxx>
25 #include <gp_Circ2d.hxx>
26 #include <Precision.hxx>
27 #include <TColStd_Array1OfReal.hxx>
28 #include <BSplCLib.hxx>
30 static GCPnts_AbscissaType computeType( const TheCurve& C,
33 GCPnts_AbscissaType LocalType ;
35 if (C.NbIntervals(GeomAbs_CN) > 1)
36 return GCPnts_AbsComposite;
38 switch (C.GetType()) {
42 return GCPnts_LengthParametrized;
45 Ratio = C.Circle().Radius();
46 return GCPnts_LengthParametrized;
48 case GeomAbs_BezierCurve:
50 Handle_TheBezierCurve Bz = C.Bezier();
51 if ((Bz->NbPoles() == 2) && !(Bz->IsRational())) {
52 Ratio = Bz->DN(0,1).Magnitude();
53 LocalType = GCPnts_LengthParametrized;
56 LocalType = GCPnts_Parametrized;
59 case GeomAbs_BSplineCurve:
61 Handle_TheBSplineCurve Bs = C.BSpline();
62 if ((Bs->NbPoles() == 2) && !(Bs->IsRational())) {
63 Ratio = Bs->DN(Bs->FirstParameter(),1).Magnitude();
64 LocalType = GCPnts_LengthParametrized;
67 LocalType = GCPnts_Parametrized;
71 return GCPnts_Parametrized;
76 // compute a point at distance Abscis from parameter U0
77 // using Ui as initial guess
79 static void Compute(CPnts_AbscissaPoint& theComputer,
81 Standard_Real& Abscis,
84 const Standard_Real EPSILON)
86 // test for easy solution
87 if (Abs(Abscis) <= Precision::Confusion()) {
88 theComputer.SetParameter(U0);
92 Standard_Real Ratio = 1.;
93 GCPnts_AbscissaType Type = computeType(C,Ratio);
96 case GCPnts_LengthParametrized :
97 theComputer.SetParameter(U0 + Abscis / Ratio);
100 case GCPnts_Parametrized :
102 theComputer.Perform(Abscis, U0, Ui, EPSILON);
105 case GCPnts_AbsComposite :
107 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
108 TColStd_Array1OfReal TI(1,NbIntervals+1);
109 C.Intervals(TI,GeomAbs_CN);
110 Standard_Real L = 0.0, sign = 1.;
111 Standard_Integer Index = 1;
112 BSplCLib::Hunt(TI,U0,Index);
113 Standard_Integer Direction = 1;
120 while ((Index >= 1) && (Index <= NbIntervals)) {
122 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction));
123 if (Abs(L - Abscis) <= Precision::Confusion()) {
124 theComputer.SetParameter(TI(Index+Direction));
128 if ((Ui < TI(Index)) || (Ui > TI(Index+1))) {
129 Ui = (Abscis / L) * (TI(Index+1) - U0);
135 theComputer.Init(C,TI(Index),TI(Index+1));
136 theComputer.Perform(sign*Abscis, U0, Ui, EPSILON);
140 U0 = TI(Index+Direction);
149 // Push a little bit outside the limits (hairy !!!)
151 theComputer.Init(C,U0,U0+0.2);
152 theComputer.Perform(sign*Abscis, U0, Ui, EPSILON);
160 // introduced by rbv for curvilinear parametrization
161 // performs more apropriate tolerance managment
163 static void AdvCompute(CPnts_AbscissaPoint& theComputer,
165 Standard_Real& Abscis,
168 const Standard_Real EPSILON)
170 Standard_Real Ratio = 1.0;
171 GCPnts_AbscissaType Type = computeType(C,Ratio);
174 case GCPnts_LengthParametrized :
175 theComputer.SetParameter(U0 + Abscis / Ratio);
178 case GCPnts_Parametrized :
179 // theComputer.Init(C);
180 theComputer.Init(C, EPSILON); //rbv's modification
182 theComputer.AdvPerform(Abscis, U0, Ui, EPSILON);
185 case GCPnts_AbsComposite :
187 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
188 TColStd_Array1OfReal TI(1,NbIntervals+1);
189 C.Intervals(TI,GeomAbs_CN);
190 Standard_Real L = 0.0, sign = 1.;
191 Standard_Integer Index = 1;
192 BSplCLib::Hunt(TI,U0,Index);
194 Standard_Integer Direction = 1;
201 if(Index == 0 && Direction > 0) {
202 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON);
203 if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) {
204 theComputer.SetParameter(TI(Index+Direction));
208 if ( Ui > TI(Index+1) ) {
209 Ui = (Abscis / L) * (TI(Index+1) - U0);
212 theComputer.Init(C,U0,TI(Index+1), EPSILON);
213 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
217 U0 = TI(Index+Direction);
224 while ((Index >= 1) && (Index <= NbIntervals)) {
226 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON);
227 if (Abs(L - Abscis) <= Precision::PConfusion()) {
228 theComputer.SetParameter(TI(Index+Direction));
232 if ((Ui < TI(Index)) || (Ui > TI(Index+1))) {
233 Ui = (Abscis / L) * (TI(Index+1) - U0);
239 theComputer.Init(C,TI(Index),TI(Index+1), EPSILON);
240 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
244 U0 = TI(Index+Direction);
257 // Push a little bit outside the limits (hairy !!!)
259 Standard_Boolean nonperiodic = !C.IsPeriodic();
261 Standard_Real U1 = U0 + sign*.2;
264 Ui = Min(Ui,C.LastParameter());
265 U1 = Min(U1, C.LastParameter());
268 Ui = Max(Ui,C.FirstParameter());
269 U1 = Max(U1, C.FirstParameter());
273 theComputer.Init(C, U0, U1, EPSILON);
274 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
282 //=======================================================================
285 //=======================================================================
287 Standard_Real GCPnts_AbscissaPoint::Length(const TheCurve& C)
289 return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(),
293 //=======================================================================
296 //=======================================================================
298 Standard_Real GCPnts_AbscissaPoint::Length(const TheCurve& C,
299 const Standard_Real Tol)
301 return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(),
302 C.LastParameter(),Tol);
306 //=======================================================================
309 //=======================================================================
311 Standard_Real GCPnts_AbscissaPoint::Length(const TheCurve& C,
312 const Standard_Real U1,
313 const Standard_Real U2)
315 Standard_Real Ratio = 1.0;
316 GCPnts_AbscissaType Type = computeType(C,Ratio);
319 case GCPnts_LengthParametrized:
320 return Abs(U2-U1) * Ratio;
322 case GCPnts_Parametrized:
323 return CPnts_AbscissaPoint::Length(C, U1, U2);
325 case GCPnts_AbsComposite:
327 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
328 TColStd_Array1OfReal TI(1,NbIntervals+1);
329 C.Intervals(TI,GeomAbs_CN);
330 Standard_Real UU1 = Min(U1, U2);
331 Standard_Real UU2 = Max(U1, U2);
332 Standard_Real L = 0.0;
333 for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) {
334 if (TI(Index) > UU2) break;
335 if (TI(Index+1) < UU1) continue;
336 L += CPnts_AbscissaPoint::Length(C,
338 Min(TI(Index+1),UU2));
346 //=======================================================================
349 //=======================================================================
351 Standard_Real GCPnts_AbscissaPoint::Length(const TheCurve& C,
352 const Standard_Real U1,
353 const Standard_Real U2,
354 const Standard_Real Tol)
356 Standard_Real Ratio = 1.0;
357 GCPnts_AbscissaType Type = computeType(C,Ratio);
360 case GCPnts_LengthParametrized:
361 return Abs(U2-U1) * Ratio;
363 case GCPnts_Parametrized:
364 return CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
366 case GCPnts_AbsComposite:
368 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
369 TColStd_Array1OfReal TI(1,NbIntervals+1);
370 C.Intervals(TI,GeomAbs_CN);
371 Standard_Real UU1 = Min(U1, U2);
372 Standard_Real UU2 = Max(U1, U2);
373 Standard_Real L = 0.0;
374 for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) {
375 if (TI(Index) > UU2) break;
376 if (TI(Index+1) < UU1) continue;
377 L += CPnts_AbscissaPoint::Length(C,
379 Min(TI(Index+1),UU2),
389 //=======================================================================
390 //function : GCPnts_AbscissaPoint
392 //=======================================================================
394 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
396 const Standard_Real Abscissa,
397 const Standard_Real U0)
399 Standard_Real L = GCPnts_AbscissaPoint::Length(C);
400 if (L < Precision::Confusion()) {
401 throw Standard_ConstructionError();
403 Standard_Real Abscis = Abscissa;
404 Standard_Real UU0 = U0;
405 Standard_Real UUi = U0 +
406 (Abscis / L) * (C.LastParameter() - C.FirstParameter());
407 Compute(myComputer, C, Abscis, UU0, UUi,
408 C.Resolution(Precision::Confusion()));
411 //=======================================================================
412 //function : GCPnts_AbscissaPoint
413 //purpose : rbv for curvilinear parametrization
414 //=======================================================================
416 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
417 (const Standard_Real Tol,
419 const Standard_Real Abscissa,
420 const Standard_Real U0)
422 Standard_Real L = GCPnts_AbscissaPoint::Length(C, Tol);
423 /* if (L < Precision::Confusion()) {
424 cout<<"FirstParameter = "<<C.FirstParameter()<<endl;
425 cout<<"LastParameter = "<<C.LastParameter()<<endl;
426 throw Standard_ConstructionError("GCPnts_AbscissaPoint::GCPnts_AbscissaPoint");
429 Standard_Real Abscis = Abscissa;
430 Standard_Real UU0 = U0;
432 if (L >= Precision::Confusion())
434 (Abscis / L) * (C.LastParameter() - C.FirstParameter());
437 AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol);
440 //=======================================================================
441 //function : GCPnts_AbscissaPoint
443 //=======================================================================
445 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
447 const Standard_Real Abscissa,
448 const Standard_Real U0,
449 const Standard_Real Ui)
451 Standard_Real Abscis = Abscissa;
452 Standard_Real UU0 = U0;
453 Standard_Real UUi = Ui;
454 Compute(myComputer, C, Abscis, UU0, UUi,
455 C.Resolution(Precision::Confusion()));
458 //=======================================================================
459 //function : GCPnts_AbscissaPoint
460 //purpose : rbv for curvilinear parametrization
461 //=======================================================================
463 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
465 const Standard_Real Abscissa,
466 const Standard_Real U0,
467 const Standard_Real Ui,
468 const Standard_Real Tol)
470 Standard_Real Abscis = Abscissa;
471 Standard_Real UU0 = U0;
472 Standard_Real UUi = Ui;
473 AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol);