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 //------------------------------------------------------------------------
16 // Calculate a point with given abscissa starting from a given point
17 // cases processed: straight segment, arc of circle, parameterized curve
19 // for a parameterized curve:
20 // calculate the total length of the curve
21 // calculate an approached point by assimilating the curve to a staight line
22 // calculate the length of the curve between the start point and the approached point
23 // by succsessive iteration find the point and its associated parameter
24 // call to FunctionRoot
26 #include <Adaptor2d_Curve2d.hxx>
27 #include <Adaptor3d_Curve.hxx>
28 #include <CPnts_AbscissaPoint.hxx>
29 #include <Geom2d_BezierCurve.hxx>
30 #include <Geom2d_BSplineCurve.hxx>
31 #include <Geom_BezierCurve.hxx>
32 #include <Geom_BSplineCurve.hxx>
34 #include <gp_Vec2d.hxx>
35 #include <math_FunctionRoot.hxx>
36 #include <math_GaussSingleIntegration.hxx>
37 #include <Precision.hxx>
38 #include <Standard_ConstructionError.hxx>
39 #include <StdFail_NotDone.hxx>
41 // auxiliary functions to compute the length of the derivative
42 static Standard_Real f3d(const Standard_Real X, const Standard_Address C)
46 ((Adaptor3d_Curve*)C)->D1(X,P,V);
50 static Standard_Real f2d(const Standard_Real X, const Standard_Address C)
54 ((Adaptor2d_Curve2d*)C)->D1(X,P,V);
58 static Standard_Integer order(const Adaptor3d_Curve& C)
60 switch (C.GetType()) {
65 case GeomAbs_Parabola :
68 case GeomAbs_BezierCurve :
69 return Min(24, 2*C.Degree());
71 case GeomAbs_BSplineCurve :
72 return Min(24, 2*C.NbPoles()-1);
79 static Standard_Integer order(const Adaptor2d_Curve2d& C)
81 switch (C.GetType()) {
86 case GeomAbs_Parabola :
89 case GeomAbs_BezierCurve :
90 return Min(24, 2*C.Bezier()->Degree());
92 case GeomAbs_BSplineCurve :
93 return Min(24, 2*C.BSpline()->NbPoles()-1);
101 //=======================================================================
104 //=======================================================================
106 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C)
108 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
112 //=======================================================================
115 //=======================================================================
117 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C)
119 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
123 //=======================================================================
125 //purpose : 3d with tolerance
126 //=======================================================================
128 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C, const Standard_Real Tol)
130 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
131 C.LastParameter(), Tol);
134 //=======================================================================
136 //purpose : 2d with tolerance
137 //=======================================================================
139 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C, const Standard_Real Tol)
141 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
142 C.LastParameter(), Tol);
146 //=======================================================================
148 //purpose : 3d with parameters
149 //=======================================================================
151 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C,
152 const Standard_Real U1,
153 const Standard_Real U2)
155 CPnts_MyGaussFunction FG;
157 CPnts_RealFunction rf = f3d;
158 FG.Init(rf,(Standard_Address)&C);
159 // FG.Init(f3d,(Standard_Address)&C);
160 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C));
161 if (!TheLength.IsDone()) {
162 throw Standard_ConstructionError();
164 return Abs(TheLength.Value());
167 //=======================================================================
169 //purpose : 2d with parameters
170 //=======================================================================
172 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C,
173 const Standard_Real U1,
174 const Standard_Real U2)
176 CPnts_MyGaussFunction FG;
178 CPnts_RealFunction rf = f2d;
179 FG.Init(rf,(Standard_Address)&C);
180 // FG.Init(f2d,(Standard_Address)&C);
181 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C));
182 if (!TheLength.IsDone()) {
183 throw Standard_ConstructionError();
185 return Abs(TheLength.Value());
188 //=======================================================================
190 //purpose : 3d with parameters and tolerance
191 //=======================================================================
193 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C,
194 const Standard_Real U1,
195 const Standard_Real U2,
196 const Standard_Real Tol)
198 CPnts_MyGaussFunction FG;
200 CPnts_RealFunction rf = f3d;
201 FG.Init(rf,(Standard_Address)&C);
202 // FG.Init(f3d,(Standard_Address)&C);
203 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C), Tol);
204 if (!TheLength.IsDone()) {
205 throw Standard_ConstructionError();
207 return Abs(TheLength.Value());
210 //=======================================================================
212 //purpose : 2d with parameters and tolerance
213 //=======================================================================
215 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C,
216 const Standard_Real U1,
217 const Standard_Real U2,
218 const Standard_Real Tol)
220 CPnts_MyGaussFunction FG;
222 CPnts_RealFunction rf = f2d;
223 FG.Init(rf,(Standard_Address)&C);
224 // FG.Init(f2d,(Standard_Address)&C);
225 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C), Tol);
226 if (!TheLength.IsDone()) {
227 throw Standard_ConstructionError();
229 return Abs(TheLength.Value());
232 //=======================================================================
233 //function : CPnts_AbscissaPoint
235 //=======================================================================
237 CPnts_AbscissaPoint::CPnts_AbscissaPoint() : myDone(Standard_False)
241 //=======================================================================
242 //function : CPnts_AbscissaPoint
244 //=======================================================================
246 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor3d_Curve& C,
247 const Standard_Real Abscissa,
248 const Standard_Real U0,
249 const Standard_Real Resolution)
252 Init(C, Resolution); //rbv's modification
254 Perform(Abscissa, U0, Resolution);
257 //=======================================================================
258 //function : CPnts_AbscissaPoint
260 //=======================================================================
262 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor2d_Curve2d& C,
263 const Standard_Real Abscissa,
264 const Standard_Real U0,
265 const Standard_Real Resolution)
268 Perform(Abscissa, U0, Resolution);
272 //=======================================================================
273 //function : CPnts_AbscissaPoint
275 //=======================================================================
277 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor3d_Curve& C,
278 const Standard_Real Abscissa,
279 const Standard_Real U0,
280 const Standard_Real Ui,
281 const Standard_Real Resolution)
284 Perform(Abscissa, U0, Ui, Resolution);
287 //=======================================================================
288 //function : CPnts_AbscissaPoint
290 //=======================================================================
292 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor2d_Curve2d& C,
293 const Standard_Real Abscissa,
294 const Standard_Real U0,
295 const Standard_Real Ui,
296 const Standard_Real Resolution)
299 Perform(Abscissa, U0, Ui, Resolution);
303 //=======================================================================
306 //=======================================================================
308 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C)
310 Init(C,C.FirstParameter(),C.LastParameter());
313 //=======================================================================
316 //=======================================================================
318 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C)
320 Init(C,C.FirstParameter(),C.LastParameter());
323 //=======================================================================
325 //purpose : introduced by rbv for curvilinear parametrization
326 //=======================================================================
328 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C, const Standard_Real Tol)
330 Init(C,C.FirstParameter(),C.LastParameter(), Tol);
333 //=======================================================================
336 //=======================================================================
338 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C, const Standard_Real Tol)
340 Init(C,C.FirstParameter(),C.LastParameter(), Tol);
343 //=======================================================================
346 //=======================================================================
348 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
349 const Standard_Real U1,
350 const Standard_Real U2)
353 CPnts_RealFunction rf = f3d;
354 myF.Init(rf,(Standard_Address)&C,order(C));
355 // myF.Init(f3d,(Standard_Address)&C,order(C));
356 myL = CPnts_AbscissaPoint::Length(C, U1, U2);
357 myUMin = Min(U1, U2);
358 myUMax = Max(U1, U2);
359 Standard_Real DU = myUMax - myUMin;
360 myUMin = myUMin - DU;
361 myUMax = myUMax + DU;
364 //=======================================================================
367 //=======================================================================
369 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
370 const Standard_Real U1,
371 const Standard_Real U2)
374 CPnts_RealFunction rf = f2d;
375 myF.Init(rf,(Standard_Address)&C,order(C));
376 // myF.Init(f2d,(Standard_Address)&C,order(C));
377 myL = CPnts_AbscissaPoint::Length(C, U1, U2);
378 myUMin = Min(U1, U2);
379 myUMax = Max(U1, U2);
380 Standard_Real DU = myUMax - myUMin;
381 myUMin = myUMin - DU;
382 myUMax = myUMax + DU;
386 //=======================================================================
388 //purpose : introduced by rbv for curvilinear parametrization
389 //=======================================================================
391 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
392 const Standard_Real U1,
393 const Standard_Real U2,
394 const Standard_Real Tol)
397 CPnts_RealFunction rf = f3d;
398 myF.Init(rf,(Standard_Address)&C,order(C));
399 // myF.Init(f3d,(Standard_Address)&C,order(C));
400 myL = CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
401 myUMin = Min(U1, U2);
402 myUMax = Max(U1, U2);
403 Standard_Real DU = myUMax - myUMin;
404 myUMin = myUMin - DU;
405 myUMax = myUMax + DU;
408 //=======================================================================
411 //=======================================================================
413 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
414 const Standard_Real U1,
415 const Standard_Real U2,
416 const Standard_Real Tol)
419 CPnts_RealFunction rf = f2d;
420 myF.Init(rf,(Standard_Address)&C,order(C));
421 // myF.Init(f2d,(Standard_Address)&C,order(C));
422 myL = CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
423 myUMin = Min(U1, U2);
424 myUMax = Max(U1, U2);
425 Standard_Real DU = myUMax - myUMin;
426 myUMin = myUMin - DU;
427 myUMax = myUMax + DU;
430 //=======================================================================
433 //=======================================================================
435 void CPnts_AbscissaPoint::Perform(const Standard_Real Abscissa,
436 const Standard_Real U0,
437 const Standard_Real Resolution)
439 if (myL < Precision::Confusion()) {
441 // leave less violently : it is expected that
442 // the increment of the level of myParam will not be great
444 myDone = Standard_True ;
449 Standard_Real Ui = U0 + (Abscissa / myL) * (myUMax - myUMin) / 3.;
450 // exercice : why 3 ?
451 Perform(Abscissa,U0,Ui,Resolution);
455 //=======================================================================
458 //=======================================================================
460 void CPnts_AbscissaPoint::Perform(const Standard_Real Abscissa,
461 const Standard_Real U0,
462 const Standard_Real Ui,
463 const Standard_Real Resolution)
465 if (myL < Precision::Confusion()) {
467 // leave less violently :
469 myDone = Standard_True ;
473 myDone = Standard_False;
474 myF.Init(U0, Abscissa);
476 math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
478 // Temporarily suspend the validity test of the solution
479 // it is necessary to make a tolreached as soon as one will make a cdl
481 // if (Solution.IsDone()) {
483 // myF.Derivative(Solution.Root(),D);
484 // if (Abs(Solution.Value()) < Resolution * D) {
485 // myDone = Standard_True;
486 // myParam = Solution.Root();
489 if (Solution.IsDone()) {
490 myDone = Standard_True;
491 myParam = Solution.Root();
496 //=======================================================================
497 //function : AdvPerform
499 //=======================================================================
501 void CPnts_AbscissaPoint::AdvPerform(const Standard_Real Abscissa,
502 const Standard_Real U0,
503 const Standard_Real Ui,
504 const Standard_Real Resolution)
506 if (myL < Precision::Confusion()) {
508 // leave less violently :
510 myDone = Standard_True ;
514 myDone = Standard_False;
515 // myF.Init(U0, Abscissa);
516 myF.Init(U0, Abscissa, Resolution/10); // rbv's modification
518 math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
520 // Temporarily suspend the validity test of the solution
521 // it is necessary to make a tolreached as soon as one will make a cdl
523 // if (Solution.IsDone()) {
525 // myF.Derivative(Solution.Root(),D);
526 // if (Abs(Solution.Value()) < Resolution * D) {
527 // myDone = Standard_True;
528 // myParam = Solution.Root();
531 if (Solution.IsDone()) {
532 myDone = Standard_True;
533 myParam = Solution.Root();