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 #include <GCPnts_AbscissaPoint.hxx>
19 #include <GCPnts_AbscissaType.hxx>
20 #include <GCPnts_TCurveTypes.hxx>
21 #include <Standard_ConstructionError.hxx>
23 //! Dimension independent used to implement GCPnts_AbscissaPoint
24 //! compute the type and the length ratio if GCPnts_LengthParametrized.
25 template<class TheCurve>
26 static GCPnts_AbscissaType computeType (const TheCurve& theC,
27 Standard_Real& theRatio)
29 if (theC.NbIntervals (GeomAbs_CN) > 1)
31 return GCPnts_AbsComposite;
34 switch (theC.GetType())
39 return GCPnts_LengthParametrized;
43 theRatio = theC.Circle().Radius();
44 return GCPnts_LengthParametrized;
46 case GeomAbs_BezierCurve:
48 Handle(typename GCPnts_TCurveTypes<TheCurve>::BezierCurve) aBz = theC.Bezier();
49 if (aBz->NbPoles() == 2
50 && !aBz->IsRational())
52 theRatio = aBz->DN (0, 1).Magnitude();
53 return GCPnts_LengthParametrized;
55 return GCPnts_Parametrized;
57 case GeomAbs_BSplineCurve:
59 Handle(typename GCPnts_TCurveTypes<TheCurve>::BSplineCurve) aBs = theC.BSpline();
60 if (aBs->NbPoles() == 2
61 && !aBs->IsRational())
63 theRatio = aBs->DN (aBs->FirstParameter(), 1).Magnitude();
64 return GCPnts_LengthParametrized;
66 return GCPnts_Parametrized;
70 return GCPnts_Parametrized;
75 //! Compute a point at distance theAbscis from parameter theU0 using theUi as initial guess
76 template<class TheCurve>
77 static void Compute (CPnts_AbscissaPoint& theComputer,
79 Standard_Real& theAbscis,
82 const Standard_Real theEPSILON)
84 // test for easy solution
85 if (Abs (theAbscis) <= Precision::Confusion())
87 theComputer.SetParameter (theU0);
91 Standard_Real aRatio = 1.0;
92 const GCPnts_AbscissaType aType = computeType (theC, aRatio);
95 case GCPnts_LengthParametrized:
97 theComputer.SetParameter (theU0 + theAbscis / aRatio);
100 case GCPnts_Parametrized:
102 theComputer.Init (theC);
103 theComputer.Perform (theAbscis, theU0, theUi, theEPSILON);
106 case GCPnts_AbsComposite:
108 const Standard_Integer aNbIntervals = theC.NbIntervals (GeomAbs_CN);
109 TColStd_Array1OfReal aTI (1, aNbIntervals + 1);
110 theC.Intervals (aTI, GeomAbs_CN);
111 Standard_Real aL = 0.0, aSign = 1.0;
112 Standard_Integer anIndex = 1;
113 BSplCLib::Hunt (aTI, theU0, anIndex);
114 Standard_Integer aDirection = 1;
118 theAbscis = -theAbscis;
123 && anIndex <= aNbIntervals)
125 aL = CPnts_AbscissaPoint::Length (theC, theU0, aTI (anIndex + aDirection));
126 if (Abs (aL - theAbscis) <= Precision::Confusion())
128 theComputer.SetParameter (aTI (anIndex + aDirection));
134 if (theUi < aTI (anIndex)
135 || theUi > aTI (anIndex + 1))
137 theUi = (theAbscis / aL) * (aTI (anIndex + 1) - theU0);
140 theUi = theU0 + theUi;
144 theUi = theU0 - theUi;
147 theComputer.Init (theC, aTI (anIndex), aTI (anIndex + 1));
148 theComputer.Perform (aSign * theAbscis, theU0, theUi, theEPSILON);
153 theU0 = aTI (anIndex + aDirection);
166 // Push a little bit outside the limits (hairy !!!)
168 theComputer.Init (theC, theU0, theU0 + 0.2);
169 theComputer.Perform (aSign * theAbscis, theU0, theUi, theEPSILON);
176 //! Introduced by rbv for curvilinear parametrization
177 //! performs more appropriate tolerance management.
178 template<class TheCurve>
179 static void AdvCompute (CPnts_AbscissaPoint& theComputer,
180 const TheCurve& theC,
181 Standard_Real& theAbscis,
182 Standard_Real& theU0,
183 Standard_Real& theUi,
184 const Standard_Real theEPSILON)
186 Standard_Real aRatio = 1.0;
187 const GCPnts_AbscissaType aType = computeType (theC, aRatio);
190 case GCPnts_LengthParametrized:
192 theComputer.SetParameter (theU0 + theAbscis / aRatio);
195 case GCPnts_Parametrized:
197 // theComputer.Init (theC);
198 theComputer.Init (theC, theEPSILON); //rbv's modification
199 theComputer.AdvPerform (theAbscis, theU0, theUi, theEPSILON);
202 case GCPnts_AbsComposite:
204 const Standard_Integer aNbIntervals = theC.NbIntervals (GeomAbs_CN);
205 TColStd_Array1OfReal aTI (1, aNbIntervals + 1);
206 theC.Intervals (aTI, GeomAbs_CN);
207 Standard_Real aL = 0.0, aSign = 1.0;
208 Standard_Integer anIndex = 1;
209 BSplCLib::Hunt (aTI, theU0, anIndex);
211 Standard_Integer aDirection = 1;
215 theAbscis = -theAbscis;
219 if (anIndex == 0 && aDirection > 0)
221 aL = CPnts_AbscissaPoint::Length (theC, theU0, aTI (anIndex + aDirection), theEPSILON);
222 if (Abs (aL - theAbscis) <= /*Precision::Confusion()*/theEPSILON)
224 theComputer.SetParameter (aTI (anIndex + aDirection));
230 if (theUi > aTI (anIndex + 1))
232 theUi = (theAbscis / aL) * (aTI (anIndex + 1) - theU0);
233 theUi = theU0 + theUi;
235 theComputer.Init (theC, theU0, aTI (anIndex + 1), theEPSILON);
236 theComputer.AdvPerform (aSign * theAbscis, theU0, theUi, theEPSILON);
241 theU0 = aTI (anIndex + aDirection);
248 && anIndex <= aNbIntervals)
250 aL = CPnts_AbscissaPoint::Length (theC, theU0, aTI (anIndex + aDirection), theEPSILON);
251 if (Abs (aL - theAbscis) <= Precision::PConfusion())
253 theComputer.SetParameter (aTI (anIndex + aDirection));
259 if (theUi < aTI (anIndex)
260 || theUi > aTI (anIndex + 1))
262 theUi = (theAbscis / aL) * (aTI (anIndex + 1) - theU0);
265 theUi = theU0 + theUi;
269 theUi = theU0 - theUi;
272 theComputer.Init (theC, aTI (anIndex), aTI (anIndex + 1), theEPSILON);
273 theComputer.AdvPerform (aSign * theAbscis, theU0, theUi, theEPSILON);
278 theU0 = aTI (anIndex + aDirection);
291 // Push a little bit outside the limits (hairy !!!)
292 const Standard_Boolean isNonPeriodic = !theC.IsPeriodic();
293 theUi = theU0 + aSign * 0.1;
294 Standard_Real aU1 = theU0 + aSign * 0.2;
299 theUi = Min (theUi, theC.LastParameter());
300 aU1 = Min (aU1, theC.LastParameter());
304 theUi = Max (theUi, theC.FirstParameter());
305 aU1 = Max (aU1, theC.FirstParameter());
309 theComputer.Init (theC, theU0, aU1, theEPSILON);
310 theComputer.AdvPerform (aSign * theAbscis, theU0, theUi, theEPSILON);
317 //=======================================================================
318 //function : GCPnts_AbscissaPoint
320 //=======================================================================
321 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint()
326 //=======================================================================
329 //=======================================================================
330 Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor3d_Curve& theC)
332 return GCPnts_AbscissaPoint::Length (theC, theC.FirstParameter(), theC.LastParameter());
335 //=======================================================================
338 //=======================================================================
339 Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor2d_Curve2d& theC)
341 return GCPnts_AbscissaPoint::Length (theC, theC.FirstParameter(), theC.LastParameter());
344 //=======================================================================
347 //=======================================================================
348 Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor3d_Curve& theC,
349 const Standard_Real theTol)
351 return GCPnts_AbscissaPoint::Length (theC, theC.FirstParameter(), theC.LastParameter(), theTol);
354 //=======================================================================
357 //=======================================================================
358 Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor2d_Curve2d& theC,
359 const Standard_Real theTol)
361 return GCPnts_AbscissaPoint::Length (theC, theC.FirstParameter(), theC.LastParameter(), theTol);
364 //=======================================================================
367 //=======================================================================
368 Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor3d_Curve& theC,
369 const Standard_Real theU1, const Standard_Real theU2)
371 return length (theC, theU1, theU2, NULL);
374 //=======================================================================
377 //=======================================================================
378 Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor2d_Curve2d& theC,
379 const Standard_Real theU1, const Standard_Real theU2)
381 return length (theC, theU1, theU2, NULL);
384 //=======================================================================
387 //=======================================================================
388 Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor3d_Curve& theC,
389 const Standard_Real theU1, const Standard_Real theU2,
390 const Standard_Real theTol)
392 return length (theC, theU1, theU2, &theTol);
395 //=======================================================================
398 //=======================================================================
399 Standard_Real GCPnts_AbscissaPoint::Length (const Adaptor2d_Curve2d& theC,
400 const Standard_Real theU1, const Standard_Real theU2,
401 const Standard_Real theTol)
403 return length (theC, theU1, theU2, &theTol);
406 //=======================================================================
409 //=======================================================================
410 template<class TheCurve>
411 Standard_Real GCPnts_AbscissaPoint::length (const TheCurve& theC,
412 const Standard_Real theU1, const Standard_Real theU2,
413 const Standard_Real* theTol)
415 Standard_Real aRatio = 1.0;
416 const GCPnts_AbscissaType aType = computeType (theC, aRatio);
419 case GCPnts_LengthParametrized:
421 return Abs (theU2 - theU1) * aRatio;
423 case GCPnts_Parametrized:
425 return theTol != NULL
426 ? CPnts_AbscissaPoint::Length (theC, theU1, theU2, *theTol)
427 : CPnts_AbscissaPoint::Length (theC, theU1, theU2);
429 case GCPnts_AbsComposite:
431 const Standard_Integer aNbIntervals = theC.NbIntervals (GeomAbs_CN);
432 TColStd_Array1OfReal aTI (1, aNbIntervals + 1);
433 theC.Intervals (aTI, GeomAbs_CN);
434 const Standard_Real aUU1 = Min (theU1, theU2);
435 const Standard_Real aUU2 = Max (theU1, theU2);
436 Standard_Real aL = 0.0;
437 for (Standard_Integer anIndex = 1; anIndex <= aNbIntervals; ++anIndex)
439 if (aTI (anIndex) > aUU2) { break; }
440 if (aTI (anIndex + 1) < aUU1) { continue; }
443 aL += CPnts_AbscissaPoint::Length (theC,
444 Max (aTI (anIndex), aUU1),
445 Min (aTI (anIndex + 1), aUU2),
450 aL += CPnts_AbscissaPoint::Length (theC,
451 Max (aTI (anIndex), aUU1),
452 Min (aTI (anIndex + 1), aUU2));
461 //=======================================================================
464 //=======================================================================
465 template<class TheCurve>
466 void GCPnts_AbscissaPoint::compute (const TheCurve& theC,
467 const Standard_Real theAbscissa,
468 const Standard_Real theU0)
470 const Standard_Real aL = GCPnts_AbscissaPoint::Length (theC);
471 if (aL < Precision::Confusion())
473 throw Standard_ConstructionError();
476 Standard_Real anAbscis = theAbscissa;
477 Standard_Real aUU0 = theU0;
478 Standard_Real aUUi = theU0 + (anAbscis / aL) * (theC.LastParameter() - theC.FirstParameter());
479 Compute (myComputer, theC, anAbscis, aUU0, aUUi,
480 theC.Resolution (Precision::Confusion()));
483 //=======================================================================
484 //function : GCPnts_AbscissaPoint
486 //=======================================================================
487 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor3d_Curve& theC,
488 const Standard_Real theAbscissa,
489 const Standard_Real theU0)
491 compute (theC, theAbscissa, theU0);
494 //=======================================================================
495 //function : GCPnts_AbscissaPoint
497 //=======================================================================
498 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor2d_Curve2d& theC,
499 const Standard_Real theAbscissa,
500 const Standard_Real theU0)
502 compute (theC, theAbscissa, theU0);
505 //=======================================================================
506 //function : advCompute
508 //=======================================================================
509 template<class TheCurve>
510 void GCPnts_AbscissaPoint::advCompute (const Standard_Real theTol,
511 const TheCurve& theC,
512 const Standard_Real theAbscissa,
513 const Standard_Real theU0)
515 const Standard_Real aL = GCPnts_AbscissaPoint::Length (theC, theTol);
516 /*if (aL < Precision::Confusion())
518 throw Standard_ConstructionError ("GCPnts_AbscissaPoint::GCPnts_AbscissaPoint");
520 Standard_Real anAbscis = theAbscissa;
521 Standard_Real aUU0 = theU0;
522 Standard_Real aUUi = 0.0;
523 if (aL >= Precision::Confusion())
525 aUUi= theU0 + (anAbscis / aL) * (theC.LastParameter() - theC.FirstParameter());
531 AdvCompute (myComputer, theC, anAbscis, aUU0, aUUi, theTol);
534 //=======================================================================
535 //function : GCPnts_AbscissaPoint
537 //=======================================================================
538 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Standard_Real theTol,
539 const Adaptor3d_Curve& theC,
540 const Standard_Real theAbscissa,
541 const Standard_Real theU0)
543 advCompute (theTol, theC, theAbscissa, theU0);
546 //=======================================================================
547 //function : GCPnts_AbscissaPoint
549 //=======================================================================
550 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Standard_Real theTol,
551 const Adaptor2d_Curve2d& theC,
552 const Standard_Real theAbscissa,
553 const Standard_Real theU0)
555 advCompute (theTol, theC, theAbscissa, theU0);
558 //=======================================================================
559 //function : GCPnts_AbscissaPoint
561 //=======================================================================
562 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor3d_Curve& theC,
563 const Standard_Real theAbscissa,
564 const Standard_Real theU0, const Standard_Real theUi)
566 Standard_Real anAbscis = theAbscissa, aUU0 = theU0, aUUi = theUi;
567 Compute (myComputer, theC, anAbscis, aUU0, aUUi, theC.Resolution (Precision::Confusion()));
570 //=======================================================================
571 //function : GCPnts_AbscissaPoint
573 //=======================================================================
574 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor2d_Curve2d& theC,
575 const Standard_Real theAbscissa,
576 const Standard_Real theU0, const Standard_Real theUi)
578 Standard_Real anAbscis = theAbscissa, aUU0 = theU0, aUUi = theUi;
579 Compute (myComputer, theC, anAbscis, aUU0, aUUi, theC.Resolution (Precision::Confusion()));
582 //=======================================================================
583 //function : GCPnts_AbscissaPoint
585 //=======================================================================
586 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor3d_Curve& theC,
587 const Standard_Real theAbscissa,
588 const Standard_Real theU0, const Standard_Real theUi,
589 const Standard_Real theTol)
591 Standard_Real anAbscis = theAbscissa, aUU0 = theU0, aUUi = theUi;
592 AdvCompute (myComputer, theC, anAbscis, aUU0, aUUi, theTol);
595 //=======================================================================
596 //function : GCPnts_AbscissaPoint
598 //=======================================================================
599 GCPnts_AbscissaPoint::GCPnts_AbscissaPoint (const Adaptor2d_Curve2d& theC,
600 const Standard_Real theAbscissa,
601 const Standard_Real theU0, const Standard_Real theUi,
602 const Standard_Real theTol)
604 Standard_Real anAbscis = theAbscissa, aUU0 = theU0, aUUi = theUi;
605 AdvCompute (myComputer, theC, anAbscis, aUU0, aUUi, theTol);