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