1 // Created on: 1995-05-05
2 // Created by: Modelistation
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
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.
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.
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.
22 // Dimension independant used to implement GCPnts_AbscissaPoint
25 // and the length ratio if GCPnts_LengthParametrized
26 #include <GCPnts_AbscissaType.hxx>
28 #include <gp_Vec2d.hxx>
29 #include <gp_Circ.hxx>
30 #include <gp_Circ2d.hxx>
31 #include <Precision.hxx>
32 #include <TColStd_Array1OfReal.hxx>
33 #include <BSplCLib.hxx>
35 static GCPnts_AbscissaType computeType( TheCurve& C,
38 GCPnts_AbscissaType LocalType ;
40 if (C.NbIntervals(GeomAbs_CN) > 1)
41 return GCPnts_AbsComposite;
43 switch (C.GetType()) {
47 return GCPnts_LengthParametrized;
50 Ratio = C.Circle().Radius();
51 return GCPnts_LengthParametrized;
53 case GeomAbs_BezierCurve:
55 Handle_TheBezierCurve Bz = C.Bezier();
56 if ((Bz->NbPoles() == 2) && !(Bz->IsRational())) {
57 Ratio = Bz->DN(0,1).Magnitude();
58 LocalType = GCPnts_LengthParametrized;
61 LocalType = GCPnts_Parametrized;
64 case GeomAbs_BSplineCurve:
66 Handle_TheBSplineCurve Bs = C.BSpline();
67 if ((Bs->NbPoles() == 2) && !(Bs->IsRational())) {
68 Ratio = Bs->DN(Bs->FirstParameter(),1).Magnitude();
69 LocalType = GCPnts_LengthParametrized;
72 LocalType = GCPnts_Parametrized;
76 return GCPnts_Parametrized;
81 // compute a point at distance Abscis from parameter U0
82 // using Ui as initial guess
84 static void Compute(CPnts_AbscissaPoint& theComputer,
86 Standard_Real& Abscis,
89 const Standard_Real EPSILON)
91 // test for easy solution
92 if (Abs(Abscis) <= Precision::Confusion()) {
93 theComputer.SetParameter(U0);
98 GCPnts_AbscissaType Type = computeType(C,Ratio);
101 case GCPnts_LengthParametrized :
102 theComputer.SetParameter(U0 + Abscis / Ratio);
105 case GCPnts_Parametrized :
107 theComputer.Perform(Abscis, U0, Ui, EPSILON);
110 case GCPnts_AbsComposite :
112 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
113 TColStd_Array1OfReal TI(1,NbIntervals+1);
114 C.Intervals(TI,GeomAbs_CN);
115 Standard_Real L = 0.0, sign = 1.;
116 Standard_Integer Index = 1;
117 BSplCLib::Hunt(TI,U0,Index);
118 Standard_Integer Direction = 1;
125 while ((Index >= 1) && (Index <= NbIntervals)) {
127 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction));
128 if (Abs(L - Abscis) <= Precision::Confusion()) {
129 theComputer.SetParameter(TI(Index+Direction));
133 if ((Ui < TI(Index)) || (Ui > TI(Index+1))) {
134 Ui = (Abscis / L) * (TI(Index+1) - U0);
140 theComputer.Init(C,TI(Index),TI(Index+1));
141 theComputer.Perform(sign*Abscis, U0, Ui, EPSILON);
145 U0 = TI(Index+Direction);
154 // Push a little bit outside the limits (hairy !!!)
156 theComputer.Init(C,U0,U0+0.2);
157 theComputer.Perform(sign*Abscis, U0, Ui, EPSILON);
165 // introduced by rbv for curvilinear parametrization
166 // performs more apropriate tolerance managment
168 static void AdvCompute(CPnts_AbscissaPoint& theComputer,
170 Standard_Real& Abscis,
173 const Standard_Real EPSILON)
175 // test for easy solution
176 if (Abs(Abscis) <= EPSILON) {
177 theComputer.SetParameter(U0);
182 GCPnts_AbscissaType Type = computeType(C,Ratio);
185 case GCPnts_LengthParametrized :
186 theComputer.SetParameter(U0 + Abscis / Ratio);
189 case GCPnts_Parametrized :
190 // theComputer.Init(C);
191 theComputer.Init(C, EPSILON); //rbv's modification
193 theComputer.AdvPerform(Abscis, U0, Ui, EPSILON);
196 case GCPnts_AbsComposite :
198 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
199 TColStd_Array1OfReal TI(1,NbIntervals+1);
200 C.Intervals(TI,GeomAbs_CN);
201 Standard_Real L = 0.0, sign = 1.;
202 Standard_Integer Index = 1;
203 BSplCLib::Hunt(TI,U0,Index);
205 Standard_Integer Direction = 1;
212 if(Index == 0 && Direction > 0) {
213 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON);
214 if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) {
215 theComputer.SetParameter(TI(Index+Direction));
219 if ( Ui > TI(Index+1) ) {
220 Ui = (Abscis / L) * (TI(Index+1) - U0);
223 theComputer.Init(C,U0,TI(Index+1), EPSILON);
224 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
228 U0 = TI(Index+Direction);
235 while ((Index >= 1) && (Index <= NbIntervals)) {
237 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON);
238 if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) {
239 theComputer.SetParameter(TI(Index+Direction));
243 if ((Ui < TI(Index)) || (Ui > TI(Index+1))) {
244 Ui = (Abscis / L) * (TI(Index+1) - U0);
250 theComputer.Init(C,TI(Index),TI(Index+1), EPSILON);
251 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
255 U0 = TI(Index+Direction);
268 // Push a little bit outside the limits (hairy !!!)
270 Standard_Boolean nonperiodic = !C.IsPeriodic();
272 Standard_Real U1 = U0 + sign*.2;
275 Ui = Min(Ui,C.LastParameter());
276 U1 = Min(U1, C.LastParameter());
279 Ui = Max(Ui,C.FirstParameter());
280 U1 = Max(U1, C.FirstParameter());
284 theComputer.Init(C, U0, U1, EPSILON);
285 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
293 //=======================================================================
296 //=======================================================================
298 Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C)
300 return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(),
304 //=======================================================================
307 //=======================================================================
309 Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C,
310 const Standard_Real Tol)
312 return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(),
313 C.LastParameter(),Tol);
317 //=======================================================================
320 //=======================================================================
322 Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C,
323 const Standard_Real U1,
324 const Standard_Real U2)
327 GCPnts_AbscissaType Type = computeType(C,Ratio);
330 case GCPnts_LengthParametrized:
331 return Abs(U2-U1) * Ratio;
333 case GCPnts_Parametrized:
334 return CPnts_AbscissaPoint::Length(C, U1, U2);
336 case GCPnts_AbsComposite:
338 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
339 TColStd_Array1OfReal TI(1,NbIntervals+1);
340 C.Intervals(TI,GeomAbs_CN);
341 Standard_Real UU1 = Min(U1, U2);
342 Standard_Real UU2 = Max(U1, U2);
343 Standard_Real L = 0.0;
344 for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) {
345 if (TI(Index) > UU2) break;
346 if (TI(Index+1) < UU1) continue;
347 L += CPnts_AbscissaPoint::Length(C,
349 Min(TI(Index+1),UU2));
357 //=======================================================================
360 //=======================================================================
362 Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C,
363 const Standard_Real U1,
364 const Standard_Real U2,
365 const Standard_Real Tol)
368 GCPnts_AbscissaType Type = computeType(C,Ratio);
371 case GCPnts_LengthParametrized:
372 return Abs(U2-U1) * Ratio;
374 case GCPnts_Parametrized:
375 return CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
377 case GCPnts_AbsComposite:
379 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
380 TColStd_Array1OfReal TI(1,NbIntervals+1);
381 C.Intervals(TI,GeomAbs_CN);
382 Standard_Real UU1 = Min(U1, U2);
383 Standard_Real UU2 = Max(U1, U2);
384 Standard_Real L = 0.0;
385 for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) {
386 if (TI(Index) > UU2) break;
387 if (TI(Index+1) < UU1) continue;
388 L += CPnts_AbscissaPoint::Length(C,
390 Min(TI(Index+1),UU2),
400 //=======================================================================
401 //function : GCPnts_AbscissaPoint
403 //=======================================================================
405 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
407 const Standard_Real Abscissa,
408 const Standard_Real U0)
410 Standard_Real L = GCPnts_AbscissaPoint::Length(C);
411 if (L < Precision::Confusion()) {
412 Standard_ConstructionError::Raise();
414 Standard_Real Abscis = Abscissa;
415 Standard_Real UU0 = U0;
416 Standard_Real UUi = U0 +
417 (Abscis / L) * (C.LastParameter() - C.FirstParameter());
418 Compute(myComputer, C, Abscis, UU0, UUi,
419 C.Resolution(Precision::Confusion()));
422 //=======================================================================
423 //function : GCPnts_AbscissaPoint
424 //purpose : rbv for curvilinear parametrization
425 //=======================================================================
427 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
428 (const Standard_Real Tol,
430 const Standard_Real Abscissa,
431 const Standard_Real U0)
433 Standard_Real L = GCPnts_AbscissaPoint::Length(C, Tol);
434 /* if (L < Precision::Confusion()) {
435 cout<<"FirstParameter = "<<C.FirstParameter()<<endl;
436 cout<<"LastParameter = "<<C.LastParameter()<<endl;
437 Standard_ConstructionError::Raise("GCPnts_AbscissaPoint::GCPnts_AbscissaPoint");
440 Standard_Real Abscis = Abscissa;
441 Standard_Real UU0 = U0;
443 if (L >= Precision::Confusion())
445 (Abscis / L) * (C.LastParameter() - C.FirstParameter());
448 AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol);
451 //=======================================================================
452 //function : GCPnts_AbscissaPoint
454 //=======================================================================
456 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
458 const Standard_Real Abscissa,
459 const Standard_Real U0,
460 const Standard_Real Ui)
462 Standard_Real Abscis = Abscissa;
463 Standard_Real UU0 = U0;
464 Standard_Real UUi = Ui;
465 Compute(myComputer, C, Abscis, UU0, UUi,
466 C.Resolution(Precision::Confusion()));
469 //=======================================================================
470 //function : GCPnts_AbscissaPoint
471 //purpose : rbv for curvilinear parametrization
472 //=======================================================================
474 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
476 const Standard_Real Abscissa,
477 const Standard_Real U0,
478 const Standard_Real Ui,
479 const Standard_Real Tol)
481 Standard_Real Abscis = Abscissa;
482 Standard_Real UU0 = U0;
483 Standard_Real UUi = Ui;
484 AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol);