0031668: Visualization - WebGL sample doesn't work on Emscripten 1.39
[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 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.
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 <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>
33 #include <gp_Vec.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>
40
41 // auxiliary functions to compute the length of the derivative
42 static Standard_Real f3d(const Standard_Real X, const Standard_Address C)
43 {
44   gp_Pnt P;
45   gp_Vec V;
46   ((Adaptor3d_Curve*)C)->D1(X,P,V);
47   return V.Magnitude();
48 }
49
50 static Standard_Real f2d(const Standard_Real X, const Standard_Address C)
51 {
52   gp_Pnt2d P;
53   gp_Vec2d V;
54   ((Adaptor2d_Curve2d*)C)->D1(X,P,V);
55   return V.Magnitude();
56 }
57
58 static Standard_Integer order(const Adaptor3d_Curve& C)
59 {
60   switch (C.GetType()) {
61     
62   case GeomAbs_Line :
63     return 2;
64
65   case GeomAbs_Parabola :
66     return 5;
67
68   case GeomAbs_BezierCurve :
69     return Min(24, 2*C.Degree());
70
71   case GeomAbs_BSplineCurve :
72     return Min(24, 2*C.NbPoles()-1);
73     
74     default :
75       return 10;
76   }
77 }
78
79 static Standard_Integer order(const Adaptor2d_Curve2d& C)
80 {
81   switch (C.GetType()) {
82     
83   case GeomAbs_Line :
84     return 2;
85
86   case GeomAbs_Parabola :
87     return 5;
88
89   case GeomAbs_BezierCurve :
90     return Min(24, 2*C.Bezier()->Degree());
91
92   case GeomAbs_BSplineCurve :
93     return Min(24, 2*C.BSpline()->NbPoles()-1);
94     
95     default :
96       return 10;
97   }
98 }
99
100
101 //=======================================================================
102 //function : Length
103 //purpose  : 3d
104 //=======================================================================
105
106 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C) 
107 {
108   return CPnts_AbscissaPoint::Length(C, C.FirstParameter(), 
109                                         C.LastParameter());
110 }
111
112 //=======================================================================
113 //function : Length
114 //purpose  : 2d
115 //=======================================================================
116
117 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C) 
118 {
119   return CPnts_AbscissaPoint::Length(C, C.FirstParameter(), 
120                                         C.LastParameter());
121 }
122
123 //=======================================================================
124 //function : Length
125 //purpose  : 3d with tolerance
126 //=======================================================================
127
128 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C, const Standard_Real Tol) 
129 {
130   return CPnts_AbscissaPoint::Length(C, C.FirstParameter(), 
131                                         C.LastParameter(), Tol);
132 }
133
134 //=======================================================================
135 //function : Length
136 //purpose  : 2d with tolerance
137 //=======================================================================
138
139 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C, const Standard_Real Tol) 
140 {
141   return CPnts_AbscissaPoint::Length(C, C.FirstParameter(), 
142                                         C.LastParameter(), Tol);
143 }
144
145
146 //=======================================================================
147 //function : Length
148 //purpose  : 3d with parameters
149 //=======================================================================
150
151 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor3d_Curve& C,
152                                           const Standard_Real U1,
153                                           const Standard_Real U2) 
154 {
155   CPnts_MyGaussFunction FG;
156 //POP pout WNT
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();
163   }
164   return Abs(TheLength.Value());
165 }
166
167 //=======================================================================
168 //function : Length
169 //purpose  : 2d with parameters
170 //=======================================================================
171
172 Standard_Real CPnts_AbscissaPoint::Length(const Adaptor2d_Curve2d& C,
173                                           const Standard_Real U1,
174                                           const Standard_Real U2) 
175 {
176   CPnts_MyGaussFunction FG;
177 //POP pout WNT
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();
184   }
185   return Abs(TheLength.Value());
186 }
187
188 //=======================================================================
189 //function : Length
190 //purpose  : 3d with parameters and tolerance
191 //=======================================================================
192
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) 
197 {
198   CPnts_MyGaussFunction FG;
199 //POP pout WNT
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();
206   }
207   return Abs(TheLength.Value());
208 }
209
210 //=======================================================================
211 //function : Length
212 //purpose  : 2d with parameters and tolerance
213 //=======================================================================
214
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) 
219 {
220   CPnts_MyGaussFunction FG;
221 //POP pout WNT
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();
228   }
229   return Abs(TheLength.Value());
230 }
231
232 //=======================================================================
233 //function : CPnts_AbscissaPoint
234 //purpose  : 
235 //=======================================================================
236
237 CPnts_AbscissaPoint::CPnts_AbscissaPoint() : myDone(Standard_False)
238 {
239 }
240
241 //=======================================================================
242 //function : CPnts_AbscissaPoint
243 //purpose  : 
244 //=======================================================================
245
246 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor3d_Curve& C,
247                                          const Standard_Real   Abscissa,
248                                          const Standard_Real   U0,
249                                          const Standard_Real   Resolution)
250 {
251 //  Init(C);
252   Init(C, Resolution); //rbv's modification
253 //
254   Perform(Abscissa, U0, Resolution);
255 }
256
257 //=======================================================================
258 //function : CPnts_AbscissaPoint
259 //purpose  : 
260 //=======================================================================
261
262 CPnts_AbscissaPoint::CPnts_AbscissaPoint(const Adaptor2d_Curve2d& C,
263                                          const Standard_Real   Abscissa,
264                                          const Standard_Real   U0,
265                                          const Standard_Real   Resolution)
266 {
267   Init(C);
268   Perform(Abscissa, U0, Resolution);
269 }
270
271
272 //=======================================================================
273 //function : CPnts_AbscissaPoint
274 //purpose  : 
275 //=======================================================================
276
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)
282 {
283   Init(C);
284   Perform(Abscissa, U0, Ui, Resolution);
285 }
286
287 //=======================================================================
288 //function : CPnts_AbscissaPoint
289 //purpose  : 
290 //=======================================================================
291
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)
297 {
298   Init(C);
299   Perform(Abscissa, U0, Ui, Resolution);
300 }
301
302
303 //=======================================================================
304 //function : Init
305 //purpose  : 
306 //=======================================================================
307
308 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C)
309 {
310   Init(C,C.FirstParameter(),C.LastParameter());
311 }
312
313 //=======================================================================
314 //function : Init
315 //purpose  : 
316 //=======================================================================
317
318 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C)
319 {
320   Init(C,C.FirstParameter(),C.LastParameter());
321 }
322
323 //=======================================================================
324 //function : Init
325 //purpose  : introduced by rbv for curvilinear parametrization
326 //=======================================================================
327
328 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C, const Standard_Real Tol)
329 {
330   Init(C,C.FirstParameter(),C.LastParameter(), Tol);
331 }
332
333 //=======================================================================
334 //function : Init
335 //purpose  : 
336 //=======================================================================
337
338 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C, const Standard_Real Tol)
339 {
340   Init(C,C.FirstParameter(),C.LastParameter(), Tol);
341 }
342
343 //=======================================================================
344 //function : Init
345 //purpose  : 
346 //=======================================================================
347
348 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
349                                const Standard_Real  U1,
350                                const Standard_Real  U2)
351 {
352 //POP pout WNT
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;
362 }
363
364 //=======================================================================
365 //function : Init
366 //purpose  : 
367 //=======================================================================
368
369 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
370                                const Standard_Real    U1,
371                                const Standard_Real    U2)
372 {
373 //POP pout WNT
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;
383 }
384
385
386 //=======================================================================
387 //function : Init
388 //purpose  : introduced by rbv for curvilinear parametrization
389 //=======================================================================
390
391 void CPnts_AbscissaPoint::Init(const Adaptor3d_Curve& C,
392                                const Standard_Real  U1,
393                                const Standard_Real  U2,
394                                const Standard_Real  Tol)
395 {
396 //POP pout WNT
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;
406 }
407
408 //=======================================================================
409 //function : Init
410 //purpose  : 
411 //=======================================================================
412
413 void CPnts_AbscissaPoint::Init(const Adaptor2d_Curve2d& C,
414                                const Standard_Real    U1,
415                                const Standard_Real    U2,
416                                const Standard_Real    Tol)
417 {
418 //POP pout WNT
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;
428 }
429
430 //=======================================================================
431 //function : Perform
432 //purpose  : 
433 //=======================================================================
434
435 void CPnts_AbscissaPoint::Perform(const Standard_Real   Abscissa,
436                                   const Standard_Real   U0,
437                                   const Standard_Real   Resolution) 
438 {
439   if (myL < Precision::Confusion()) {
440     //
441     //  leave less violently : it is expected that 
442     //  the increment of the level of myParam will not be great
443     //
444     myDone = Standard_True ;
445     myParam = U0 ;
446   
447   }
448   else {
449     Standard_Real Ui = U0 + (Abscissa / myL) * (myUMax - myUMin) / 3.;
450     // exercice : why 3 ?
451     Perform(Abscissa,U0,Ui,Resolution);
452   }
453 }
454
455 //=======================================================================
456 //function : Perform
457 //purpose  : 
458 //=======================================================================
459
460 void CPnts_AbscissaPoint::Perform(const Standard_Real   Abscissa,
461                                   const Standard_Real   U0,
462                                   const Standard_Real   Ui,
463                                   const Standard_Real   Resolution) 
464 {
465   if (myL < Precision::Confusion()) {
466     //
467     //  leave less violently :
468     //
469     myDone = Standard_True ;
470     myParam = U0 ;
471   }
472   else {
473     myDone = Standard_False;
474     myF.Init(U0, Abscissa);
475
476     math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
477     
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
480 // lbo 21/03/97
481 //    if (Solution.IsDone()) {
482 //      Standard_Real D;
483 //      myF.Derivative(Solution.Root(),D);
484 //      if (Abs(Solution.Value()) < Resolution * D) {
485 //      myDone = Standard_True;
486 //      myParam = Solution.Root();
487 //      }
488 //    }
489     if (Solution.IsDone()) {
490       myDone = Standard_True;
491       myParam = Solution.Root();
492     }
493   }
494 }
495
496 //=======================================================================
497 //function : AdvPerform
498 //purpose  : 
499 //=======================================================================
500
501 void CPnts_AbscissaPoint::AdvPerform(const Standard_Real   Abscissa,
502                                   const Standard_Real   U0,
503                                   const Standard_Real   Ui,
504                                   const Standard_Real   Resolution) 
505 {
506   if (myL < Precision::Confusion()) {
507     //
508     //  leave less violently :
509     //
510     myDone = Standard_True ;
511     myParam = U0 ;
512   }
513   else {
514     myDone = Standard_False;
515 //    myF.Init(U0, Abscissa);
516     myF.Init(U0, Abscissa, Resolution/10); // rbv's modification
517
518     math_FunctionRoot Solution(myF, Ui, Resolution, myUMin, myUMax);
519     
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
522 // lbo 21/03/97
523 //    if (Solution.IsDone()) {
524 //      Standard_Real D;
525 //      myF.Derivative(Solution.Root(),D);
526 //      if (Abs(Solution.Value()) < Resolution * D) {
527 //      myDone = Standard_True;
528 //      myParam = Solution.Root();
529 //      }
530 //    }
531     if (Solution.IsDone()) {
532       myDone = Standard_True;
533       myParam = Solution.Root();
534     }
535   }
536 }