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
7 // under the terms of the GNU Lesser General Public 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 <CPnts_AbscissaPoint.ixx>
28 #include <math_GaussSingleIntegration.hxx>
29 #include <math_FunctionRoot.hxx>
30 #include <StdFail_NotDone.hxx>
31 #include <Standard_ConstructionError.hxx>
34 #include <gp_Vec2d.hxx>
35 #include <Geom_BezierCurve.hxx>
36 #include <Geom_BSplineCurve.hxx>
37 #include <Geom2d_BezierCurve.hxx>
38 #include <Geom2d_BSplineCurve.hxx>
39 #include <Precision.hxx>
41 // auxiliary functions to compute the length of the derivative
43 static Standard_Real f3d(const Standard_Real X, const Standard_Address C)
45 gp_Vec V = ((Adaptor3d_Curve*)C)->DN(X,1);
49 static Standard_Real f2d(const Standard_Real X, const Standard_Address C)
51 gp_Vec2d V = ((Adaptor2d_Curve2d*)C)->DN(X,1);
55 static Standard_Integer order(const Adaptor3d_Curve& C)
57 switch (C.GetType()) {
62 case GeomAbs_Parabola :
65 case GeomAbs_BezierCurve :
66 return Min(24, 2*C.Degree());
68 case GeomAbs_BSplineCurve :
69 return Min(24, 2*C.NbPoles()-1);
76 static Standard_Integer order(const Adaptor2d_Curve2d& C)
78 switch (C.GetType()) {
83 case GeomAbs_Parabola :
86 case GeomAbs_BezierCurve :
87 return Min(24, 2*C.Bezier()->Degree());
89 case GeomAbs_BSplineCurve :
90 return Min(24, 2*C.BSpline()->NbPoles()-1);
98 //=======================================================================
101 //=======================================================================
103 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C)
105 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
109 //=======================================================================
112 //=======================================================================
114 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C)
116 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
120 //=======================================================================
122 //purpose : 3d with tolerance
123 //=======================================================================
125 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C, const Standard_Real Tol)
127 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
128 C.LastParameter(), Tol);
131 //=======================================================================
133 //purpose : 2d with tolerance
134 //=======================================================================
136 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C, const Standard_Real Tol)
138 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
139 C.LastParameter(), Tol);
143 //=======================================================================
145 //purpose : 3d with parameters
146 //=======================================================================
148 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C,
149 const Standard_Real U1,
150 const Standard_Real U2)
152 CPnts_MyGaussFunction FG;
154 CPnts_RealFunction rf = f3d;
155 FG.Init(rf,(Standard_Address)&C);
156 // FG.Init(f3d,(Standard_Address)&C);
157 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C));
158 if (!TheLength.IsDone()) {
159 Standard_ConstructionError::Raise();
161 return Abs(TheLength.Value());
164 //=======================================================================
166 //purpose : 2d with parameters
167 //=======================================================================
169 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C,
170 const Standard_Real U1,
171 const Standard_Real U2)
173 CPnts_MyGaussFunction FG;
175 CPnts_RealFunction rf = f2d;
176 FG.Init(rf,(Standard_Address)&C);
177 // FG.Init(f2d,(Standard_Address)&C);
178 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C));
179 if (!TheLength.IsDone()) {
180 Standard_ConstructionError::Raise();
182 return Abs(TheLength.Value());
185 //=======================================================================
187 //purpose : 3d with parameters and tolerance
188 //=======================================================================
190 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C,
191 const Standard_Real U1,
192 const Standard_Real U2,
193 const Standard_Real Tol)
195 CPnts_MyGaussFunction FG;
197 CPnts_RealFunction rf = f3d;
198 FG.Init(rf,(Standard_Address)&C);
199 // FG.Init(f3d,(Standard_Address)&C);
200 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C), Tol);
201 if (!TheLength.IsDone()) {
202 Standard_ConstructionError::Raise();
204 return Abs(TheLength.Value());
207 //=======================================================================
209 //purpose : 2d with parameters and tolerance
210 //=======================================================================
212 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C,
213 const Standard_Real U1,
214 const Standard_Real U2,
215 const Standard_Real Tol)
217 CPnts_MyGaussFunction FG;
219 CPnts_RealFunction rf = f2d;
220 FG.Init(rf,(Standard_Address)&C);
221 // FG.Init(f2d,(Standard_Address)&C);
222 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C), Tol);
223 if (!TheLength.IsDone()) {
224 Standard_ConstructionError::Raise();
226 return Abs(TheLength.Value());
229 //=======================================================================
230 //function : CPnts_AbscissaPoint
232 //=======================================================================
234 CPnts_AbscissaPoint::CPnts_AbscissaPoint() : myDone(Standard_False)
238 //=======================================================================
239 //function : CPnts_AbscissaPoint
241 //=======================================================================
243 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor3d_Curve& C,
244 const Standard_Real Abscissa,
245 const Standard_Real U0,
246 const Standard_Real Resolution)
249 Init(C, Resolution); //rbv's modification
251 Perform(Abscissa, U0, Resolution);
254 //=======================================================================
255 //function : CPnts_AbscissaPoint
257 //=======================================================================
259 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor2d_Curve2d& C,
260 const Standard_Real Abscissa,
261 const Standard_Real U0,
262 const Standard_Real Resolution)
265 Perform(Abscissa, U0, Resolution);
269 //=======================================================================
270 //function : CPnts_AbscissaPoint
272 //=======================================================================
274 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor3d_Curve& C,
275 const Standard_Real Abscissa,
276 const Standard_Real U0,
277 const Standard_Real Ui,
278 const Standard_Real Resolution)
281 Perform(Abscissa, U0, Ui, Resolution);
284 //=======================================================================
285 //function : CPnts_AbscissaPoint
287 //=======================================================================
289 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor2d_Curve2d& C,
290 const Standard_Real Abscissa,
291 const Standard_Real U0,
292 const Standard_Real Ui,
293 const Standard_Real Resolution)
296 Perform(Abscissa, U0, Ui, Resolution);
300 //=======================================================================
303 //=======================================================================
305 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C)
307 Init(C,C.FirstParameter(),C.LastParameter());
310 //=======================================================================
313 //=======================================================================
315 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C)
317 Init(C,C.FirstParameter(),C.LastParameter());
320 //=======================================================================
322 //purpose : introduced by rbv for curvilinear parametrization
323 //=======================================================================
325 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C, const Standard_Real Tol)
327 Init(C,C.FirstParameter(),C.LastParameter(), Tol);
330 //=======================================================================
333 //=======================================================================
335 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C, const Standard_Real Tol)
337 Init(C,C.FirstParameter(),C.LastParameter(), Tol);
340 //=======================================================================
343 //=======================================================================
345 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
346 const Standard_Real U1,
347 const Standard_Real U2)
350 CPnts_RealFunction rf = f3d;
351 myF.Init(rf,(Standard_Address)&C,order(C));
352 // myF.Init(f3d,(Standard_Address)&C,order(C));
353 myL = CPnts_AbscissaPoint::Length(C, U1, U2);
354 myUMin = Min(U1, U2);
355 myUMax = Max(U1, U2);
356 Standard_Real DU = myUMax - myUMin;
357 myUMin = myUMin - DU;
358 myUMax = myUMax + DU;
361 //=======================================================================
364 //=======================================================================
366 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
367 const Standard_Real U1,
368 const Standard_Real U2)
371 CPnts_RealFunction rf = f2d;
372 myF.Init(rf,(Standard_Address)&C,order(C));
373 // myF.Init(f2d,(Standard_Address)&C,order(C));
374 myL = CPnts_AbscissaPoint::Length(C, U1, U2);
375 myUMin = Min(U1, U2);
376 myUMax = Max(U1, U2);
377 Standard_Real DU = myUMax - myUMin;
378 myUMin = myUMin - DU;
379 myUMax = myUMax + DU;
383 //=======================================================================
385 //purpose : introduced by rbv for curvilinear parametrization
386 //=======================================================================
388 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
389 const Standard_Real U1,
390 const Standard_Real U2,
391 const Standard_Real Tol)
394 CPnts_RealFunction rf = f3d;
395 myF.Init(rf,(Standard_Address)&C,order(C));
396 // myF.Init(f3d,(Standard_Address)&C,order(C));
397 myL = CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
398 myUMin = Min(U1, U2);
399 myUMax = Max(U1, U2);
400 Standard_Real DU = myUMax - myUMin;
401 myUMin = myUMin - DU;
402 myUMax = myUMax + DU;
405 //=======================================================================
408 //=======================================================================
410 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
411 const Standard_Real U1,
412 const Standard_Real U2,
413 const Standard_Real Tol)
416 CPnts_RealFunction rf = f2d;
417 myF.Init(rf,(Standard_Address)&C,order(C));
418 // myF.Init(f2d,(Standard_Address)&C,order(C));
419 myL = CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
420 myUMin = Min(U1, U2);
421 myUMax = Max(U1, U2);
422 Standard_Real DU = myUMax - myUMin;
423 myUMin = myUMin - DU;
424 myUMax = myUMax + DU;
427 //=======================================================================
430 //=======================================================================
432 void CPnts_AbscissaPoint::Perform(const Standard_Real Abscissa,
433 const Standard_Real U0,
434 const Standard_Real Resolution)
436 if (myL < Precision::Confusion()) {
438 // leave less violently : it is expected that
439 // the increment of the level of myParam will not be great
441 myDone = Standard_True ;
446 Standard_Real Ui = U0 + (Abscissa / myL) * (myUMax - myUMin) / 3.;
447 // exercice : why 3 ?
448 Perform(Abscissa,U0,Ui,Resolution);
452 //=======================================================================
455 //=======================================================================
457 void CPnts_AbscissaPoint::Perform(const Standard_Real Abscissa,
458 const Standard_Real U0,
459 const Standard_Real Ui,
460 const Standard_Real Resolution)
462 if (myL < Precision::Confusion()) {
464 // leave less violently :
466 myDone = Standard_True ;
470 myDone = Standard_False;
471 myF.Init(U0, Abscissa);
473 math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
475 // Temporarily suspend the validity test of the solution
476 // it is necessary to make a tolreached as soon as one will make a cdl
478 // if (Solution.IsDone()) {
480 // myF.Derivative(Solution.Root(),D);
481 // if (Abs(Solution.Value()) < Resolution * D) {
482 // myDone = Standard_True;
483 // myParam = Solution.Root();
486 if (Solution.IsDone()) {
487 myDone = Standard_True;
488 myParam = Solution.Root();
493 //=======================================================================
494 //function : AdvPerform
496 //=======================================================================
498 void CPnts_AbscissaPoint::AdvPerform(const Standard_Real Abscissa,
499 const Standard_Real U0,
500 const Standard_Real Ui,
501 const Standard_Real Resolution)
503 if (myL < Precision::Confusion()) {
505 // leave less violently :
507 myDone = Standard_True ;
511 myDone = Standard_False;
512 // myF.Init(U0, Abscissa);
513 myF.Init(U0, Abscissa, Resolution/10); // rbv's modification
515 math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
517 // Temporarily suspend the validity test of the solution
518 // it is necessary to make a tolreached as soon as one will make a cdl
520 // if (Solution.IsDone()) {
522 // myF.Derivative(Solution.Root(),D);
523 // if (Abs(Solution.Value()) < Resolution * D) {
524 // myDone = Standard_True;
525 // myParam = Solution.Root();
528 if (Solution.IsDone()) {
529 myDone = Standard_True;
530 myParam = Solution.Root();