1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
19 //------------------------------------------------------------------------
20 // Calculate a point with given abscissa starting from a given point
21 // cases processed: straight segment, arc of circle, parameterized curve
23 // for a parameterized curve:
24 // calculate the total length of the curve
25 // calculate an approached point by assimilating the curve to a staight line
26 // calculate the length of the curve between the start point and the approached point
27 // by succsessive iteration find the point and its associated parameter
28 // call to FunctionRoot
30 #include <CPnts_AbscissaPoint.ixx>
32 #include <math_GaussSingleIntegration.hxx>
33 #include <math_FunctionRoot.hxx>
34 #include <StdFail_NotDone.hxx>
35 #include <Standard_ConstructionError.hxx>
38 #include <gp_Vec2d.hxx>
39 #include <Geom_BezierCurve.hxx>
40 #include <Geom_BSplineCurve.hxx>
41 #include <Geom2d_BezierCurve.hxx>
42 #include <Geom2d_BSplineCurve.hxx>
43 #include <Precision.hxx>
45 // auxiliary functions to compute the length of the derivative
47 static Standard_Real f3d(const Standard_Real X, const Standard_Address C)
49 gp_Vec V = ((Adaptor3d_Curve*)C)->DN(X,1);
53 static Standard_Real f2d(const Standard_Real X, const Standard_Address C)
55 gp_Vec2d V = ((Adaptor2d_Curve2d*)C)->DN(X,1);
59 static Standard_Integer order(const Adaptor3d_Curve& C)
61 switch (C.GetType()) {
66 case GeomAbs_Parabola :
69 case GeomAbs_BezierCurve :
70 return Min(24, 2*C.Bezier()->Degree());
72 case GeomAbs_BSplineCurve :
73 return Min(24, 2*C.BSpline()->NbPoles()-1);
80 static Standard_Integer order(const Adaptor2d_Curve2d& C)
82 switch (C.GetType()) {
87 case GeomAbs_Parabola :
90 case GeomAbs_BezierCurve :
91 return Min(24, 2*C.Bezier()->Degree());
93 case GeomAbs_BSplineCurve :
94 return Min(24, 2*C.BSpline()->NbPoles()-1);
102 //=======================================================================
105 //=======================================================================
107 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C)
109 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
113 //=======================================================================
116 //=======================================================================
118 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C)
120 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
124 //=======================================================================
126 //purpose : 3d with tolerance
127 //=======================================================================
129 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C, const Standard_Real Tol)
131 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
132 C.LastParameter(), Tol);
135 //=======================================================================
137 //purpose : 2d with tolerance
138 //=======================================================================
140 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C, const Standard_Real Tol)
142 return CPnts_AbscissaPoint::Length(C, C.FirstParameter(),
143 C.LastParameter(), Tol);
147 //=======================================================================
149 //purpose : 3d with parameters
150 //=======================================================================
152 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C,
153 const Standard_Real U1,
154 const Standard_Real U2)
156 CPnts_MyGaussFunction FG;
158 CPnts_RealFunction rf = f3d;
159 FG.Init(rf,(Standard_Address)&C);
160 // FG.Init(f3d,(Standard_Address)&C);
161 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C));
162 if (!TheLength.IsDone()) {
163 Standard_ConstructionError::Raise();
165 return Abs(TheLength.Value());
168 //=======================================================================
170 //purpose : 2d with parameters
171 //=======================================================================
173 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C,
174 const Standard_Real U1,
175 const Standard_Real U2)
177 CPnts_MyGaussFunction FG;
179 CPnts_RealFunction rf = f2d;
180 FG.Init(rf,(Standard_Address)&C);
181 // FG.Init(f2d,(Standard_Address)&C);
182 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C));
183 if (!TheLength.IsDone()) {
184 Standard_ConstructionError::Raise();
186 return Abs(TheLength.Value());
189 //=======================================================================
191 //purpose : 3d with parameters and tolerance
192 //=======================================================================
194 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C,
195 const Standard_Real U1,
196 const Standard_Real U2,
197 const Standard_Real Tol)
199 CPnts_MyGaussFunction FG;
201 CPnts_RealFunction rf = f3d;
202 FG.Init(rf,(Standard_Address)&C);
203 // FG.Init(f3d,(Standard_Address)&C);
204 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C), Tol);
205 if (!TheLength.IsDone()) {
206 Standard_ConstructionError::Raise();
208 return Abs(TheLength.Value());
211 //=======================================================================
213 //purpose : 2d with parameters and tolerance
214 //=======================================================================
216 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C,
217 const Standard_Real U1,
218 const Standard_Real U2,
219 const Standard_Real Tol)
221 CPnts_MyGaussFunction FG;
223 CPnts_RealFunction rf = f2d;
224 FG.Init(rf,(Standard_Address)&C);
225 // FG.Init(f2d,(Standard_Address)&C);
226 math_GaussSingleIntegration TheLength(FG, U1, U2, order(C), Tol);
227 if (!TheLength.IsDone()) {
228 Standard_ConstructionError::Raise();
230 return Abs(TheLength.Value());
233 //=======================================================================
234 //function : CPnts_AbscissaPoint
236 //=======================================================================
238 CPnts_AbscissaPoint::CPnts_AbscissaPoint() : myDone(Standard_False)
242 //=======================================================================
243 //function : CPnts_AbscissaPoint
245 //=======================================================================
247 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor3d_Curve& C,
248 const Standard_Real Abscissa,
249 const Standard_Real U0,
250 const Standard_Real Resolution)
253 Init(C, Resolution); //rbv's modification
255 Perform(Abscissa, U0, Resolution);
258 //=======================================================================
259 //function : CPnts_AbscissaPoint
261 //=======================================================================
263 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor2d_Curve2d& C,
264 const Standard_Real Abscissa,
265 const Standard_Real U0,
266 const Standard_Real Resolution)
269 Perform(Abscissa, U0, Resolution);
273 //=======================================================================
274 //function : CPnts_AbscissaPoint
276 //=======================================================================
278 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor3d_Curve& C,
279 const Standard_Real Abscissa,
280 const Standard_Real U0,
281 const Standard_Real Ui,
282 const Standard_Real Resolution)
285 Perform(Abscissa, U0, Ui, Resolution);
288 //=======================================================================
289 //function : CPnts_AbscissaPoint
291 //=======================================================================
293 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor2d_Curve2d& C,
294 const Standard_Real Abscissa,
295 const Standard_Real U0,
296 const Standard_Real Ui,
297 const Standard_Real Resolution)
300 Perform(Abscissa, U0, Ui, Resolution);
304 //=======================================================================
307 //=======================================================================
309 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C)
311 Init(C,C.FirstParameter(),C.LastParameter());
314 //=======================================================================
317 //=======================================================================
319 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C)
321 Init(C,C.FirstParameter(),C.LastParameter());
324 //=======================================================================
326 //purpose : introduced by rbv for curvilinear parametrization
327 //=======================================================================
329 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C, const Standard_Real Tol)
331 Init(C,C.FirstParameter(),C.LastParameter(), Tol);
334 //=======================================================================
337 //=======================================================================
339 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C, const Standard_Real Tol)
341 Init(C,C.FirstParameter(),C.LastParameter(), Tol);
344 //=======================================================================
347 //=======================================================================
349 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
350 const Standard_Real U1,
351 const Standard_Real U2)
354 CPnts_RealFunction rf = f3d;
355 myF.Init(rf,(Standard_Address)&C,order(C));
356 // myF.Init(f3d,(Standard_Address)&C,order(C));
357 myL = CPnts_AbscissaPoint::Length(C, U1, U2);
358 myUMin = Min(U1, U2);
359 myUMax = Max(U1, U2);
360 Standard_Real DU = myUMax - myUMin;
361 myUMin = myUMin - DU;
362 myUMax = myUMax + DU;
365 //=======================================================================
368 //=======================================================================
370 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
371 const Standard_Real U1,
372 const Standard_Real U2)
375 CPnts_RealFunction rf = f2d;
376 myF.Init(rf,(Standard_Address)&C,order(C));
377 // myF.Init(f2d,(Standard_Address)&C,order(C));
378 myL = CPnts_AbscissaPoint::Length(C, U1, U2);
379 myUMin = Min(U1, U2);
380 myUMax = Max(U1, U2);
381 Standard_Real DU = myUMax - myUMin;
382 myUMin = myUMin - DU;
383 myUMax = myUMax + DU;
387 //=======================================================================
389 //purpose : introduced by rbv for curvilinear parametrization
390 //=======================================================================
392 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
393 const Standard_Real U1,
394 const Standard_Real U2,
395 const Standard_Real Tol)
398 CPnts_RealFunction rf = f3d;
399 myF.Init(rf,(Standard_Address)&C,order(C));
400 // myF.Init(f3d,(Standard_Address)&C,order(C));
401 myL = CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
402 myUMin = Min(U1, U2);
403 myUMax = Max(U1, U2);
404 Standard_Real DU = myUMax - myUMin;
405 myUMin = myUMin - DU;
406 myUMax = myUMax + DU;
409 //=======================================================================
412 //=======================================================================
414 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
415 const Standard_Real U1,
416 const Standard_Real U2,
417 const Standard_Real Tol)
420 CPnts_RealFunction rf = f2d;
421 myF.Init(rf,(Standard_Address)&C,order(C));
422 // myF.Init(f2d,(Standard_Address)&C,order(C));
423 myL = CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
424 myUMin = Min(U1, U2);
425 myUMax = Max(U1, U2);
426 Standard_Real DU = myUMax - myUMin;
427 myUMin = myUMin - DU;
428 myUMax = myUMax + DU;
431 //=======================================================================
434 //=======================================================================
436 void CPnts_AbscissaPoint::Perform(const Standard_Real Abscissa,
437 const Standard_Real U0,
438 const Standard_Real Resolution)
440 if (myL < Precision::Confusion()) {
442 // leave less violently : it is expected that
443 // the increment of the level of myParam will not be great
445 myDone = Standard_True ;
450 Standard_Real Ui = U0 + (Abscissa / myL) * (myUMax - myUMin) / 3.;
451 // exercice : why 3 ?
452 Perform(Abscissa,U0,Ui,Resolution);
456 //=======================================================================
459 //=======================================================================
461 void CPnts_AbscissaPoint::Perform(const Standard_Real Abscissa,
462 const Standard_Real U0,
463 const Standard_Real Ui,
464 const Standard_Real Resolution)
466 if (myL < Precision::Confusion()) {
468 // leave less violently :
470 myDone = Standard_True ;
474 myDone = Standard_False;
475 myF.Init(U0, Abscissa);
477 math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
479 // Temporarily suspend the validity test of the solution
480 // it is necessary to make a tolreached as soon as one will make a cdl
482 // if (Solution.IsDone()) {
484 // myF.Derivative(Solution.Root(),D);
485 // if (Abs(Solution.Value()) < Resolution * D) {
486 // myDone = Standard_True;
487 // myParam = Solution.Root();
490 if (Solution.IsDone()) {
491 myDone = Standard_True;
492 myParam = Solution.Root();
497 //=======================================================================
498 //function : AdvPerform
500 //=======================================================================
502 void CPnts_AbscissaPoint::AdvPerform(const Standard_Real Abscissa,
503 const Standard_Real U0,
504 const Standard_Real Ui,
505 const Standard_Real Resolution)
507 if (myL < Precision::Confusion()) {
509 // leave less violently :
511 myDone = Standard_True ;
515 myDone = Standard_False;
516 // myF.Init(U0, Abscissa);
517 myF.Init(U0, Abscissa, Resolution/10); // rbv's modification
519 math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
521 // Temporarily suspend the validity test of the solution
522 // it is necessary to make a tolreached as soon as one will make a cdl
524 // if (Solution.IsDone()) {
526 // myF.Derivative(Solution.Root(),D);
527 // if (Abs(Solution.Value()) < Resolution * D) {
528 // myDone = Standard_True;
529 // myParam = Solution.Root();
532 if (Solution.IsDone()) {
533 myDone = Standard_True;
534 myParam = Solution.Root();