0024428: Implementation of LGPL license
[occt.git] / src / CPnts / CPnts_AbscissaPoint.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
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.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 //------------------------------------------------------------------------
16 //  Calculate a point with given abscissa starting from a given point 
17 //  cases processed: straight segment, arc of circle, parameterized curve
18 //  curve should be C1
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
25
26 #include <CPnts_AbscissaPoint.ixx>
27
28 #include <math_GaussSingleIntegration.hxx>
29 #include <math_FunctionRoot.hxx>
30 #include <StdFail_NotDone.hxx>
31 #include <Standard_ConstructionError.hxx>
32
33 #include <gp_Vec.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>
40
41 // auxiliary functions to compute the length of the derivative
42
43 static Standard_Real f3d(const Standard_Real X, const Standard_Address C)
44 {
45   gp_Vec V = ((Adaptor3d_Curve*)C)->DN(X,1);
46   return V.Magnitude();
47 }
48
49 static Standard_Real f2d(const Standard_Real X, const Standard_Address C)
50 {
51   gp_Vec2d V = ((Adaptor2d_Curve2d*)C)->DN(X,1);
52   return V.Magnitude();
53 }
54
55 static Standard_Integer order(const Adaptor3d_Curve& C)
56 {
57   switch (C.GetType()) {
58     
59   case GeomAbs_Line :
60     return 2;
61
62   case GeomAbs_Parabola :
63     return 5;
64
65   case GeomAbs_BezierCurve :
66     return Min(24, 2*C.Degree());
67
68   case GeomAbs_BSplineCurve :
69     return Min(24, 2*C.NbPoles()-1);
70     
71     default :
72       return 10;
73   }
74 }
75
76 static Standard_Integer order(const Adaptor2d_Curve2d& C)
77 {
78   switch (C.GetType()) {
79     
80   case GeomAbs_Line :
81     return 2;
82
83   case GeomAbs_Parabola :
84     return 5;
85
86   case GeomAbs_BezierCurve :
87     return Min(24, 2*C.Bezier()->Degree());
88
89   case GeomAbs_BSplineCurve :
90     return Min(24, 2*C.BSpline()->NbPoles()-1);
91     
92     default :
93       return 10;
94   }
95 }
96
97
98 //=======================================================================
99 //function : Length
100 //purpose  : 3d
101 //=======================================================================
102
103 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C) 
104 {
105   return CPnts_AbscissaPoint::Length(C, C.FirstParameter(), 
106                                         C.LastParameter());
107 }
108
109 //=======================================================================
110 //function : Length
111 //purpose  : 2d
112 //=======================================================================
113
114 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C) 
115 {
116   return CPnts_AbscissaPoint::Length(C, C.FirstParameter(), 
117                                         C.LastParameter());
118 }
119
120 //=======================================================================
121 //function : Length
122 //purpose  : 3d with tolerance
123 //=======================================================================
124
125 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C, const Standard_Real Tol) 
126 {
127   return CPnts_AbscissaPoint::Length(C, C.FirstParameter(), 
128                                         C.LastParameter(), Tol);
129 }
130
131 //=======================================================================
132 //function : Length
133 //purpose  : 2d with tolerance
134 //=======================================================================
135
136 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C, const Standard_Real Tol) 
137 {
138   return CPnts_AbscissaPoint::Length(C, C.FirstParameter(), 
139                                         C.LastParameter(), Tol);
140 }
141
142
143 //=======================================================================
144 //function : Length
145 //purpose  : 3d with parameters
146 //=======================================================================
147
148 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C,
149                                           const Standard_Real U1,
150                                           const Standard_Real U2) 
151 {
152   CPnts_MyGaussFunction FG;
153 //POP pout WNT
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();
160   }
161   return Abs(TheLength.Value());
162 }
163
164 //=======================================================================
165 //function : Length
166 //purpose  : 2d with parameters
167 //=======================================================================
168
169 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C,
170                                           const Standard_Real U1,
171                                           const Standard_Real U2) 
172 {
173   CPnts_MyGaussFunction FG;
174 //POP pout WNT
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();
181   }
182   return Abs(TheLength.Value());
183 }
184
185 //=======================================================================
186 //function : Length
187 //purpose  : 3d with parameters and tolerance
188 //=======================================================================
189
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) 
194 {
195   CPnts_MyGaussFunction FG;
196 //POP pout WNT
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();
203   }
204   return Abs(TheLength.Value());
205 }
206
207 //=======================================================================
208 //function : Length
209 //purpose  : 2d with parameters and tolerance
210 //=======================================================================
211
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) 
216 {
217   CPnts_MyGaussFunction FG;
218 //POP pout WNT
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();
225   }
226   return Abs(TheLength.Value());
227 }
228
229 //=======================================================================
230 //function : CPnts_AbscissaPoint
231 //purpose  : 
232 //=======================================================================
233
234 CPnts_AbscissaPoint::CPnts_AbscissaPoint() : myDone(Standard_False)
235 {
236 }
237
238 //=======================================================================
239 //function : CPnts_AbscissaPoint
240 //purpose  : 
241 //=======================================================================
242
243 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor3d_Curve& C,
244                                          const Standard_Real   Abscissa,
245                                          const Standard_Real   U0,
246                                          const Standard_Real   Resolution)
247 {
248 //  Init(C);
249   Init(C, Resolution); //rbv's modification
250 //
251   Perform(Abscissa, U0, Resolution);
252 }
253
254 //=======================================================================
255 //function : CPnts_AbscissaPoint
256 //purpose  : 
257 //=======================================================================
258
259 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor2d_Curve2d& C,
260                                          const Standard_Real   Abscissa,
261                                          const Standard_Real   U0,
262                                          const Standard_Real   Resolution)
263 {
264   Init(C);
265   Perform(Abscissa, U0, Resolution);
266 }
267
268
269 //=======================================================================
270 //function : CPnts_AbscissaPoint
271 //purpose  : 
272 //=======================================================================
273
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)
279 {
280   Init(C);
281   Perform(Abscissa, U0, Ui, Resolution);
282 }
283
284 //=======================================================================
285 //function : CPnts_AbscissaPoint
286 //purpose  : 
287 //=======================================================================
288
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)
294 {
295   Init(C);
296   Perform(Abscissa, U0, Ui, Resolution);
297 }
298
299
300 //=======================================================================
301 //function : Init
302 //purpose  : 
303 //=======================================================================
304
305 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C)
306 {
307   Init(C,C.FirstParameter(),C.LastParameter());
308 }
309
310 //=======================================================================
311 //function : Init
312 //purpose  : 
313 //=======================================================================
314
315 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C)
316 {
317   Init(C,C.FirstParameter(),C.LastParameter());
318 }
319
320 //=======================================================================
321 //function : Init
322 //purpose  : introduced by rbv for curvilinear parametrization
323 //=======================================================================
324
325 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C, const Standard_Real Tol)
326 {
327   Init(C,C.FirstParameter(),C.LastParameter(), Tol);
328 }
329
330 //=======================================================================
331 //function : Init
332 //purpose  : 
333 //=======================================================================
334
335 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C, const Standard_Real Tol)
336 {
337   Init(C,C.FirstParameter(),C.LastParameter(), Tol);
338 }
339
340 //=======================================================================
341 //function : Init
342 //purpose  : 
343 //=======================================================================
344
345 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
346                                const Standard_Real  U1,
347                                const Standard_Real  U2)
348 {
349 //POP pout WNT
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;
359 }
360
361 //=======================================================================
362 //function : Init
363 //purpose  : 
364 //=======================================================================
365
366 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
367                                const Standard_Real    U1,
368                                const Standard_Real    U2)
369 {
370 //POP pout WNT
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;
380 }
381
382
383 //=======================================================================
384 //function : Init
385 //purpose  : introduced by rbv for curvilinear parametrization
386 //=======================================================================
387
388 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
389                                const Standard_Real  U1,
390                                const Standard_Real  U2,
391                                const Standard_Real  Tol)
392 {
393 //POP pout WNT
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;
403 }
404
405 //=======================================================================
406 //function : Init
407 //purpose  : 
408 //=======================================================================
409
410 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
411                                const Standard_Real    U1,
412                                const Standard_Real    U2,
413                                const Standard_Real    Tol)
414 {
415 //POP pout WNT
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;
425 }
426
427 //=======================================================================
428 //function : Perform
429 //purpose  : 
430 //=======================================================================
431
432 void CPnts_AbscissaPoint::Perform(const Standard_Real   Abscissa,
433                                   const Standard_Real   U0,
434                                   const Standard_Real   Resolution) 
435 {
436   if (myL < Precision::Confusion()) {
437     //
438     //  leave less violently : it is expected that 
439     //  the increment of the level of myParam will not be great
440     //
441     myDone = Standard_True ;
442     myParam = U0 ;
443   
444   }
445   else {
446     Standard_Real Ui = U0 + (Abscissa / myL) * (myUMax - myUMin) / 3.;
447     // exercice : why 3 ?
448     Perform(Abscissa,U0,Ui,Resolution);
449   }
450 }
451
452 //=======================================================================
453 //function : Perform
454 //purpose  : 
455 //=======================================================================
456
457 void CPnts_AbscissaPoint::Perform(const Standard_Real   Abscissa,
458                                   const Standard_Real   U0,
459                                   const Standard_Real   Ui,
460                                   const Standard_Real   Resolution) 
461 {
462   if (myL < Precision::Confusion()) {
463     //
464     //  leave less violently :
465     //
466     myDone = Standard_True ;
467     myParam = U0 ;
468   }
469   else {
470     myDone = Standard_False;
471     myF.Init(U0, Abscissa);
472
473     math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
474     
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
477 // lbo 21/03/97
478 //    if (Solution.IsDone()) {
479 //      Standard_Real D;
480 //      myF.Derivative(Solution.Root(),D);
481 //      if (Abs(Solution.Value()) < Resolution * D) {
482 //      myDone = Standard_True;
483 //      myParam = Solution.Root();
484 //      }
485 //    }
486     if (Solution.IsDone()) {
487       myDone = Standard_True;
488       myParam = Solution.Root();
489     }
490   }
491 }
492
493 //=======================================================================
494 //function : AdvPerform
495 //purpose  : 
496 //=======================================================================
497
498 void CPnts_AbscissaPoint::AdvPerform(const Standard_Real   Abscissa,
499                                   const Standard_Real   U0,
500                                   const Standard_Real   Ui,
501                                   const Standard_Real   Resolution) 
502 {
503   if (myL < Precision::Confusion()) {
504     //
505     //  leave less violently :
506     //
507     myDone = Standard_True ;
508     myParam = U0 ;
509   }
510   else {
511     myDone = Standard_False;
512 //    myF.Init(U0, Abscissa);
513     myF.Init(U0, Abscissa, Resolution/10); // rbv's modification
514
515     math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
516     
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
519 // lbo 21/03/97
520 //    if (Solution.IsDone()) {
521 //      Standard_Real D;
522 //      myF.Derivative(Solution.Root(),D);
523 //      if (Abs(Solution.Value()) < Resolution * D) {
524 //      myDone = Standard_True;
525 //      myParam = Solution.Root();
526 //      }
527 //    }
528     if (Solution.IsDone()) {
529       myDone = Standard_True;
530       myParam = Solution.Root();
531     }
532   }
533 }