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
9 // under the terms of the GNU Lesser General Public 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( 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);
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 // test for easy solution
171 if (Abs(Abscis) <= EPSILON) {
172 theComputer.SetParameter(U0);
177 GCPnts_AbscissaType Type = computeType(C,Ratio);
180 case GCPnts_LengthParametrized :
181 theComputer.SetParameter(U0 + Abscis / Ratio);
184 case GCPnts_Parametrized :
185 // theComputer.Init(C);
186 theComputer.Init(C, EPSILON); //rbv's modification
188 theComputer.AdvPerform(Abscis, U0, Ui, EPSILON);
191 case GCPnts_AbsComposite :
193 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
194 TColStd_Array1OfReal TI(1,NbIntervals+1);
195 C.Intervals(TI,GeomAbs_CN);
196 Standard_Real L = 0.0, sign = 1.;
197 Standard_Integer Index = 1;
198 BSplCLib::Hunt(TI,U0,Index);
200 Standard_Integer Direction = 1;
207 if(Index == 0 && Direction > 0) {
208 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON);
209 if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) {
210 theComputer.SetParameter(TI(Index+Direction));
214 if ( Ui > TI(Index+1) ) {
215 Ui = (Abscis / L) * (TI(Index+1) - U0);
218 theComputer.Init(C,U0,TI(Index+1), EPSILON);
219 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
223 U0 = TI(Index+Direction);
230 while ((Index >= 1) && (Index <= NbIntervals)) {
232 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON);
233 if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) {
234 theComputer.SetParameter(TI(Index+Direction));
238 if ((Ui < TI(Index)) || (Ui > TI(Index+1))) {
239 Ui = (Abscis / L) * (TI(Index+1) - U0);
245 theComputer.Init(C,TI(Index),TI(Index+1), EPSILON);
246 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
250 U0 = TI(Index+Direction);
263 // Push a little bit outside the limits (hairy !!!)
265 Standard_Boolean nonperiodic = !C.IsPeriodic();
267 Standard_Real U1 = U0 + sign*.2;
270 Ui = Min(Ui,C.LastParameter());
271 U1 = Min(U1, C.LastParameter());
274 Ui = Max(Ui,C.FirstParameter());
275 U1 = Max(U1, C.FirstParameter());
279 theComputer.Init(C, U0, U1, EPSILON);
280 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
288 //=======================================================================
291 //=======================================================================
293 Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C)
295 return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(),
299 //=======================================================================
302 //=======================================================================
304 Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C,
305 const Standard_Real Tol)
307 return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(),
308 C.LastParameter(),Tol);
312 //=======================================================================
315 //=======================================================================
317 Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C,
318 const Standard_Real U1,
319 const Standard_Real U2)
322 GCPnts_AbscissaType Type = computeType(C,Ratio);
325 case GCPnts_LengthParametrized:
326 return Abs(U2-U1) * Ratio;
328 case GCPnts_Parametrized:
329 return CPnts_AbscissaPoint::Length(C, U1, U2);
331 case GCPnts_AbsComposite:
333 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
334 TColStd_Array1OfReal TI(1,NbIntervals+1);
335 C.Intervals(TI,GeomAbs_CN);
336 Standard_Real UU1 = Min(U1, U2);
337 Standard_Real UU2 = Max(U1, U2);
338 Standard_Real L = 0.0;
339 for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) {
340 if (TI(Index) > UU2) break;
341 if (TI(Index+1) < UU1) continue;
342 L += CPnts_AbscissaPoint::Length(C,
344 Min(TI(Index+1),UU2));
352 //=======================================================================
355 //=======================================================================
357 Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C,
358 const Standard_Real U1,
359 const Standard_Real U2,
360 const Standard_Real Tol)
363 GCPnts_AbscissaType Type = computeType(C,Ratio);
366 case GCPnts_LengthParametrized:
367 return Abs(U2-U1) * Ratio;
369 case GCPnts_Parametrized:
370 return CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
372 case GCPnts_AbsComposite:
374 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
375 TColStd_Array1OfReal TI(1,NbIntervals+1);
376 C.Intervals(TI,GeomAbs_CN);
377 Standard_Real UU1 = Min(U1, U2);
378 Standard_Real UU2 = Max(U1, U2);
379 Standard_Real L = 0.0;
380 for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) {
381 if (TI(Index) > UU2) break;
382 if (TI(Index+1) < UU1) continue;
383 L += CPnts_AbscissaPoint::Length(C,
385 Min(TI(Index+1),UU2),
395 //=======================================================================
396 //function : GCPnts_AbscissaPoint
398 //=======================================================================
400 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
402 const Standard_Real Abscissa,
403 const Standard_Real U0)
405 Standard_Real L = GCPnts_AbscissaPoint::Length(C);
406 if (L < Precision::Confusion()) {
407 Standard_ConstructionError::Raise();
409 Standard_Real Abscis = Abscissa;
410 Standard_Real UU0 = U0;
411 Standard_Real UUi = U0 +
412 (Abscis / L) * (C.LastParameter() - C.FirstParameter());
413 Compute(myComputer, C, Abscis, UU0, UUi,
414 C.Resolution(Precision::Confusion()));
417 //=======================================================================
418 //function : GCPnts_AbscissaPoint
419 //purpose : rbv for curvilinear parametrization
420 //=======================================================================
422 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
423 (const Standard_Real Tol,
425 const Standard_Real Abscissa,
426 const Standard_Real U0)
428 Standard_Real L = GCPnts_AbscissaPoint::Length(C, Tol);
429 /* if (L < Precision::Confusion()) {
430 cout<<"FirstParameter = "<<C.FirstParameter()<<endl;
431 cout<<"LastParameter = "<<C.LastParameter()<<endl;
432 Standard_ConstructionError::Raise("GCPnts_AbscissaPoint::GCPnts_AbscissaPoint");
435 Standard_Real Abscis = Abscissa;
436 Standard_Real UU0 = U0;
438 if (L >= Precision::Confusion())
440 (Abscis / L) * (C.LastParameter() - C.FirstParameter());
443 AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol);
446 //=======================================================================
447 //function : GCPnts_AbscissaPoint
449 //=======================================================================
451 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
453 const Standard_Real Abscissa,
454 const Standard_Real U0,
455 const Standard_Real Ui)
457 Standard_Real Abscis = Abscissa;
458 Standard_Real UU0 = U0;
459 Standard_Real UUi = Ui;
460 Compute(myComputer, C, Abscis, UU0, UUi,
461 C.Resolution(Precision::Confusion()));
464 //=======================================================================
465 //function : GCPnts_AbscissaPoint
466 //purpose : rbv for curvilinear parametrization
467 //=======================================================================
469 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
471 const Standard_Real Abscissa,
472 const Standard_Real U0,
473 const Standard_Real Ui,
474 const Standard_Real Tol)
476 Standard_Real Abscis = Abscissa;
477 Standard_Real UU0 = U0;
478 Standard_Real UUi = Ui;
479 AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol);