0022792: Globally defined symbol PI conflicts with VTK definition (Intel compiler)
[occt.git] / src / Geom2d / Geom2d_OffsetCurve.cxx
1 // File:        Geom2d_OffsetCurve.cxx
2 // Created:     Wed Mar 24 19:23:58 1993
3 // Author:      JCV
4 //              <fid@sdsun2>
5 // Copyright:   Matra Datavision 1993
6
7 // File:        Geom2d_OffsetCurve.cxx
8 // Created:     Tue Jun 25 15:36:30 1991
9 // Author:      JCV
10
11 //  modified by Edward AGAPOV (eap) Jan 28 2002 --- DN(), occ143(BUC60654)
12
13
14
15 #include <Geom2d_OffsetCurve.ixx>
16 #include <gp.hxx>
17 #include <Standard_ConstructionError.hxx>
18 #include <Standard_RangeError.hxx>
19 #include <Standard_NotImplemented.hxx>
20 #include <Geom2d_UndefinedDerivative.hxx>
21 #include <Geom2d_UndefinedValue.hxx>
22 #include <Geom2d_Line.hxx>
23 #include <Geom2d_Circle.hxx>
24 #include <Geom2d_Ellipse.hxx>
25 #include <Geom2d_Hyperbola.hxx>
26 #include <Geom2d_Parabola.hxx>
27 #include <Geom2d_BezierCurve.hxx>
28 #include <Geom2d_BSplineCurve.hxx>
29 #include <Geom2d_TrimmedCurve.hxx>
30 #include <gp_XY.hxx>
31
32 typedef Handle(Geom2d_OffsetCurve) Handle(OffsetCurve);
33 typedef Geom2d_OffsetCurve         OffsetCurve;
34 typedef Handle(Geom2d_Geometry)    Handle(Geometry);
35 typedef Handle(Geom2d_Curve)       Handle(Curve);
36 typedef Geom2d_Curve               Curve;
37 typedef gp_Dir2d  Dir2d;
38 typedef gp_Pnt2d  Pnt2d;
39 typedef gp_Vec2d  Vec2d;
40 typedef gp_Trsf2d Trsf2d;
41 typedef gp_XY     XY;
42
43
44
45 static const int MaxDegree = 9;
46 //ordre de derivation maximum pour la recherche de la premiere 
47 //derivee non nulle
48
49
50
51 //=======================================================================
52 //function : Copy
53 //purpose  : 
54 //=======================================================================
55
56 Handle(Geom2d_Geometry) Geom2d_OffsetCurve::Copy () const 
57 {
58   Handle(OffsetCurve) C;
59   C = new OffsetCurve (basisCurve, offsetValue);
60   return C;
61 }
62
63
64 //=======================================================================
65 //function : Geom2d_OffsetCurve
66 //purpose  : 
67 //=======================================================================
68
69 Geom2d_OffsetCurve::Geom2d_OffsetCurve (const Handle(Curve)& C,
70                                         const Standard_Real Offset)  
71 : offsetValue (Offset) 
72 {
73   if (C->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)) {
74     Handle(OffsetCurve) OC = Handle(OffsetCurve)::DownCast(C->Copy());
75     if ((OC->BasisCurve())->Continuity() == GeomAbs_C0)  
76       Standard_ConstructionError::Raise();
77
78     basisCurve = Handle(Curve)::DownCast((OC->BasisCurve())->Copy());
79     offsetValue += OC->Offset();
80   } else {
81     if (C->Continuity() == GeomAbs_C0)  
82       Standard_ConstructionError::Raise();
83
84     basisCurve = Handle(Curve)::DownCast(C->Copy());
85   }
86 }
87
88 //=======================================================================
89 //function : Reverse
90 //purpose  : 
91 //=======================================================================
92
93 void Geom2d_OffsetCurve::Reverse () 
94 {
95   basisCurve->Reverse(); 
96   offsetValue = -offsetValue;
97 }
98
99 //=======================================================================
100 //function : ReversedParameter
101 //purpose  : 
102 //=======================================================================
103
104 Standard_Real Geom2d_OffsetCurve::ReversedParameter( const Standard_Real U) const
105 {
106   return basisCurve->ReversedParameter( U); 
107 }
108
109 //=======================================================================
110 //function : SetBasisCurve
111 //purpose  : 
112 //=======================================================================
113
114 void Geom2d_OffsetCurve::SetBasisCurve (const Handle(Curve)& C) 
115 {
116   if (C->Continuity() == GeomAbs_C0)  Standard_ConstructionError::Raise();
117   basisCurve = Handle(Geom2d_Curve)::DownCast(C->Copy());
118 }
119
120 //=======================================================================
121 //function : SetOffsetValue
122 //purpose  : 
123 //=======================================================================
124
125 void Geom2d_OffsetCurve::SetOffsetValue (const Standard_Real D) { offsetValue = D; }
126
127 //=======================================================================
128 //function : BasisCurve
129 //purpose  : 
130 //=======================================================================
131
132 Handle(Curve) Geom2d_OffsetCurve::BasisCurve () const 
133
134   return basisCurve;
135 }
136
137 //=======================================================================
138 //function : Continuity
139 //purpose  : 
140 //=======================================================================
141
142 GeomAbs_Shape Geom2d_OffsetCurve::Continuity () const 
143 {
144   GeomAbs_Shape OffsetShape=GeomAbs_C0;
145   switch (basisCurve->Continuity()) {
146      case GeomAbs_C0 : OffsetShape = GeomAbs_C0;   break;
147      case GeomAbs_C1 : OffsetShape = GeomAbs_C0;   break;
148      case GeomAbs_C2 : OffsetShape = GeomAbs_C1;   break;
149      case GeomAbs_C3 : OffsetShape = GeomAbs_C2;   break;
150      case GeomAbs_CN : OffsetShape = GeomAbs_CN;   break;
151      case GeomAbs_G1 : OffsetShape = GeomAbs_G1;   break;
152      case GeomAbs_G2 : OffsetShape = GeomAbs_G2;   break;
153   }
154   return OffsetShape;
155 }
156
157 //=======================================================================
158 //function : D0
159 //purpose  : 
160 //=======================================================================
161
162 void Geom2d_OffsetCurve::D0 (const Standard_Real   U,
163                                    Pnt2d& P ) const 
164 {
165   Vec2d V1;
166
167   basisCurve->D1 (U, P, V1);
168   Standard_Integer Index = 2;
169   while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
170     V1 = basisCurve->DN (U, Index);
171     Index++;
172   }
173   Standard_Real A = V1.Y();
174   Standard_Real B = - V1.X();
175   Standard_Real R = Sqrt(A*A + B * B);
176   if (R <= gp::Resolution())  Geom2d_UndefinedValue::Raise();
177   A = A * offsetValue/R;
178   B = B * offsetValue/R;
179   P.SetCoord(P.X() + A, P.Y() + B);
180 }
181
182 //=======================================================================
183 //function : D1
184 //purpose  : 
185 //=======================================================================
186
187 void Geom2d_OffsetCurve::D1 (const Standard_Real U, Pnt2d& P, Vec2d& V1) const {
188
189    // P(u) = p(u) + Offset * Ndir / R
190    // with R = || p' ^ Z|| and Ndir = P' ^ Z
191
192    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
193
194
195 #ifdef DEB
196   GeomAbs_Shape Continuity = basisCurve->Continuity();
197 #else
198   basisCurve->Continuity();
199 #endif
200   Vec2d V2;
201   basisCurve->D2 (U, P, V1, V2);
202   Standard_Integer Index = 2;
203   while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
204     V1 = basisCurve->DN (U, Index);
205     Index++;
206   }
207   if (Index != 2) { V2 = basisCurve->DN (U, Index); }
208   XY Ndir  (V1.Y(), -V1.X());
209   XY DNdir (V2.Y(), -V2.X());
210   Standard_Real R2 = Ndir.SquareModulus();
211   Standard_Real R  = Sqrt (R2);
212   Standard_Real R3 = R * R2;
213   Standard_Real Dr = Ndir.Dot (DNdir);
214   if (R3 <= gp::Resolution()) {
215     //We try another computation but the stability is not very good.
216     if (R2 <= gp::Resolution()) Geom2d_UndefinedDerivative::Raise();
217     DNdir.Multiply(R);
218     DNdir.Subtract (Ndir.Multiplied (Dr/R));
219     DNdir.Multiply (offsetValue/R2);
220     V1.Add (Vec2d(DNdir));
221   }
222   else {
223     // Same computation as IICURV in EUCLID-IS because the stability is
224     // better
225     DNdir.Multiply (offsetValue/R);
226     DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
227     V1.Add (Vec2d(DNdir));
228   }
229   Ndir.Multiply (offsetValue/R);
230   Ndir.Add (P.XY());
231   P.SetXY (Ndir);
232 }
233
234 //=======================================================================
235 //function : D2
236 //purpose  : 
237 //=======================================================================
238
239 void Geom2d_OffsetCurve::D2 (const Standard_Real U, 
240                                    Pnt2d& P, 
241                                    Vec2d& V1, Vec2d& V2) const 
242 {
243    // P(u) = p(u) + Offset * Ndir / R
244    // with R = || p' ^ Z|| and Ndir = P' ^ Z
245
246    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
247
248    // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
249    //         Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
250
251 #ifdef DEB
252   GeomAbs_Shape Continuity = basisCurve->Continuity();
253 #else
254   basisCurve->Continuity();
255 #endif
256   Vec2d V3;
257   basisCurve->D3 (U, P, V1, V2, V3);
258   Standard_Integer Index = 2;
259   while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
260     V1 = basisCurve->DN (U, Index);
261     Index++;
262   }
263   if (Index != 2) {
264     V2 = basisCurve->DN (U, Index);
265     V3 = basisCurve->DN (U, Index + 1);
266   }
267   XY Ndir (V1.Y(), -V1.X());
268   XY DNdir (V2.Y(), -V2.X());
269   XY D2Ndir (V3.Y(), -V3.X());
270   Standard_Real R2  = Ndir.SquareModulus();
271   Standard_Real R   = Sqrt (R2);
272   Standard_Real R3  = R2 * R;
273   Standard_Real R4  = R2 * R2;
274   Standard_Real R5  = R3 * R2;
275   Standard_Real Dr  = Ndir.Dot (DNdir);
276   Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
277   if (R5 <= gp::Resolution()) {
278     //We try another computation but the stability is not very good
279     //dixit ISG.
280     if (R4 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
281     // V2 = P" (U) :
282      Standard_Real R4 = R2 * R2;
283      D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
284      D2Ndir.Add (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
285      D2Ndir.Multiply (offsetValue / R);
286      V2.Add (Vec2d(D2Ndir));
287      // V1 = P' (U) :
288      DNdir.Multiply(R);
289      DNdir.Subtract (Ndir.Multiplied (Dr/R));
290      DNdir.Multiply (offsetValue/R2);
291      V1.Add (Vec2d(DNdir));
292    }
293    else {
294      // Same computation as IICURV in EUCLID-IS because the stability is
295      // better.
296      // V2 = P" (U) :
297     D2Ndir.Multiply (offsetValue/R);
298     D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
299     D2Ndir.Add (Ndir.Multiplied 
300                      (offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))));
301     V2.Add (Vec2d(D2Ndir));
302     // V1 = P' (U) 
303      DNdir.Multiply (offsetValue/R);
304      DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
305      V1.Add (Vec2d(DNdir));
306    }
307    //P (U) :
308    Ndir.Multiply (offsetValue/R);
309    Ndir.Add (P.XY());
310    P.SetXY (Ndir);
311 }
312
313
314 //=======================================================================
315 //function : D3
316 //purpose  : 
317 //=======================================================================
318
319 void Geom2d_OffsetCurve::D3 (const Standard_Real U, 
320                                    Pnt2d& P, 
321                                    Vec2d& V1, Vec2d& V2, Vec2d& V3) const {
322
323
324    // P(u) = p(u) + Offset * Ndir / R
325    // with R = || p' ^ Z|| and Ndir = P' ^ Z
326
327    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
328
329    // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
330    //         Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
331
332    //P"'(u) = p"'(u) + (Offset / R) * (D3Ndir - (3.0 * Dr/R**2 ) * D2Ndir -
333    //         (3.0 * D2r / R2) * DNdir) + (3.0 * Dr * Dr / R4) * DNdir -
334    //         (D3r/R2) * Ndir + (6.0 * Dr * Dr / R4) * Ndir +
335    //         (6.0 * Dr * D2r / R4) * Ndir - (15.0 * Dr* Dr* Dr /R6) * Ndir
336
337
338
339    basisCurve->D3 (U, P, V1, V2, V3);
340    Vec2d V4 = basisCurve->DN (U, 4);
341    Standard_Integer Index = 2;
342    while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
343      V1 = basisCurve->DN (U, Index);
344      Index++;
345    }
346    if (Index != 2) {
347      V2 = basisCurve->DN (U, Index);
348      V3 = basisCurve->DN (U, Index + 1);
349      V4 = basisCurve->DN (U, Index + 2);
350    }
351    XY Ndir   (V1.Y(), -V1.X());
352    XY DNdir  (V2.Y(), -V2.X());
353    XY D2Ndir (V3.Y(), -V3.X());
354    XY D3Ndir (V4.Y(), -V4.X());
355    Standard_Real R2  = Ndir.SquareModulus();
356    Standard_Real R   = Sqrt (R2);
357    Standard_Real R3  = R2 * R;
358    Standard_Real R4  = R2 * R2;
359    Standard_Real R5  = R3 * R2;
360    Standard_Real R6  = R3 * R3;
361    Standard_Real R7  = R5 * R2;
362    Standard_Real Dr  = Ndir.Dot (DNdir);
363    Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
364    Standard_Real D3r = Ndir.Dot (D3Ndir) + 3.0 * DNdir.Dot (D2Ndir);
365    if (R7 <= gp::Resolution()) {
366      //We try another computation but the stability is not very good
367      //dixit ISG.
368      if (R6 <= gp::Resolution()) Geom2d_UndefinedDerivative::Raise();
369      // V3 = P"' (U) :
370      D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R2));
371      D3Ndir.Subtract (
372      (DNdir.Multiplied ((3.0 * offsetValue) * ((D2r/R2) + (Dr*Dr)/R4))));
373      D3Ndir.Add (Ndir.Multiplied (
374      (offsetValue * (6.0*Dr*Dr/R4 + 6.0*Dr*D2r/R4 - 15.0*Dr*Dr*Dr/R6 - D3r))
375      ));
376      D3Ndir.Multiply (offsetValue/R);
377      V3.Add (Vec2d(D3Ndir));
378      // V2 = P" (U) :
379      Standard_Real R4 = R2 * R2;
380      D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
381      D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
382      D2Ndir.Multiply (offsetValue / R);
383      V2.Add (Vec2d(D2Ndir));
384      // V1 = P' (U) :
385      DNdir.Multiply(R);
386      DNdir.Subtract (Ndir.Multiplied (Dr/R));
387      DNdir.Multiply (offsetValue/R2);
388      V1.Add (Vec2d(DNdir));
389    }
390    else {
391      // Same computation as IICURV in EUCLID-IS because the stability is
392      // better.
393      // V3 = P"' (U) :
394       D3Ndir.Multiply (offsetValue/R);
395      D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R3));
396      D3Ndir.Subtract (DNdir.Multiplied (
397      ((3.0 * offsetValue) * ((D2r/R3) + (Dr*Dr)/R5))) );
398      D3Ndir.Add (Ndir.Multiplied (
399      (offsetValue * (6.0*Dr*Dr/R5 + 6.0*Dr*D2r/R5 - 15.0*Dr*Dr*Dr/R7 - D3r))
400      ));
401      V3.Add (Vec2d(D3Ndir));
402      // V2 = P" (U) :
403      D2Ndir.Multiply (offsetValue/R);
404      D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
405      D2Ndir.Subtract (Ndir.Multiplied (
406                       offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))
407                                       )
408                      );
409      V2.Add (Vec2d(D2Ndir));
410      // V1 = P' (U) :
411      DNdir.Multiply (offsetValue/R);
412      DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
413      V1.Add (Vec2d(DNdir));
414    }
415    //P (U) :
416    Ndir.Multiply (offsetValue/R);
417    Ndir.Add (P.XY());
418    P.SetXY (Ndir);
419 }
420
421 //=======================================================================
422 //function : DN
423 //purpose  : 
424 //=======================================================================
425
426 Vec2d Geom2d_OffsetCurve::DN (const Standard_Real U, 
427                               const Standard_Integer N) const 
428 {
429   Standard_RangeError_Raise_if (N < 1, "Geom2d_OffsetCurve::DN()");
430
431   gp_Vec2d VN, VBidon;
432   gp_Pnt2d PBidon;
433   switch (N) {
434   case 1: D1( U, PBidon, VN); break;
435   case 2: D2( U, PBidon, VBidon, VN); break;
436   case 3: D3( U, PBidon, VBidon, VBidon, VN); break;
437   default:
438     Standard_NotImplemented::Raise();
439   }
440   
441   return VN;
442 }
443
444
445 //=======================================================================
446 //function : Value
447 //purpose  : 
448 //=======================================================================
449
450 void Geom2d_OffsetCurve::Value (const Standard_Real U, 
451                                 Pnt2d& P, Pnt2d& Pbasis,
452                                 Vec2d& V1basis ) const 
453 {
454
455   basisCurve->D1 (U, Pbasis, V1basis);
456   Standard_Integer Index = 2;
457   while (V1basis.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
458     V1basis = basisCurve->DN (U, Index);
459     Index++;
460   }
461   Standard_Real A = V1basis.Y();
462   Standard_Real B = - V1basis.X();
463   Standard_Real R = Sqrt(A*A + B * B);
464   if (R <= gp::Resolution())  Geom2d_UndefinedValue::Raise();
465   A = A * offsetValue/R;
466   B = B * offsetValue/R;
467   P.SetCoord (A + Pbasis.X(), B + Pbasis.Y());
468 }
469
470
471 //=======================================================================
472 //function : D1
473 //purpose  : 
474 //=======================================================================
475
476 void Geom2d_OffsetCurve::D1 (const Standard_Real U, 
477                              Pnt2d& P, Pnt2d& Pbasis,
478                              Vec2d& V1, Vec2d& V1basis, 
479                              Vec2d& V2basis ) const 
480 {
481    // P(u) = p(u) + Offset * Ndir / R
482    // with R = || p' ^ Z|| and Ndir = P' ^ Z
483
484    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
485
486 #ifdef DEB
487    GeomAbs_Shape Continuity = basisCurve->Continuity();
488 #else
489    basisCurve->Continuity();
490 #endif
491
492    basisCurve->D2 (U, Pbasis, V1basis, V2basis);
493    V1 = V1basis;
494    Vec2d V2 = V2basis;
495    Standard_Integer Index = 2;
496    while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
497      V1 = basisCurve->DN (U, Index);
498      Index++;
499    }
500    if (Index != 2) {
501      V2 = basisCurve->DN (U, Index);
502    }
503    XY Ndir (V1.Y(), -V1.X());
504    XY DNdir (V2.Y(), -V2.X());
505    Standard_Real R2 = Ndir.SquareModulus();
506    Standard_Real R = Sqrt (R2);
507    Standard_Real R3 = R * R2;
508    Standard_Real Dr = Ndir.Dot (DNdir);
509    if (R3 <= gp::Resolution()) {
510       //We try another computation but the stability is not very good.
511       if (R2 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
512       DNdir.Multiply(R);
513       DNdir.Subtract (Ndir.Multiplied (Dr/R));
514       DNdir.Multiply (offsetValue / R2);
515       V1.Add (Vec2d(DNdir));
516    }
517    else {
518       // Same computation as IICURV in EUCLID-IS because the stability is
519       // better
520       DNdir.Multiply (offsetValue/R);
521       DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
522       V1.Add (Vec2d(DNdir));
523    }
524    Ndir.Multiply (offsetValue/R);
525    Ndir.Add (Pbasis.XY());
526    P.SetXY (Ndir);
527 }
528
529
530 //=======================================================================
531 //function : D2
532 //purpose  : 
533 //=======================================================================
534
535 void Geom2d_OffsetCurve::D2 (const Standard_Real U, 
536                              Pnt2d& P, Pnt2d& Pbasis,
537                              Vec2d& V1, Vec2d& V2, 
538                              Vec2d& V1basis, Vec2d& V2basis,
539                              Vec2d& V3basis ) const 
540 {
541    // P(u) = p(u) + Offset * Ndir / R
542    // with R = || p' ^ Z|| and Ndir = P' ^ Z
543
544    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
545
546    // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
547    //         Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
548
549 #ifdef DEB
550   GeomAbs_Shape Continuity = basisCurve->Continuity();
551 #else
552   basisCurve->Continuity();
553 #endif
554
555   basisCurve->D3 (U, Pbasis, V1basis, V2basis, V3basis);
556   Standard_Integer Index = 2;
557   V1 = V1basis;
558   V2 = V2basis;
559   Vec2d V3 = V3basis;
560   while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
561     V1 = basisCurve->DN (U, Index);
562     Index++;
563   }
564   if (Index != 2) {
565     V2 = basisCurve->DN (U, Index);
566     V3 = basisCurve->DN (U, Index + 1);
567   }
568   XY Ndir (V1.Y(), -V1.X());
569   XY DNdir (V2.Y(), -V2.X());
570   XY D2Ndir (V3.Y(), -V3.X());
571   Standard_Real R2  = Ndir.SquareModulus();
572   Standard_Real R   = Sqrt (R2);
573   Standard_Real R3  = R2 * R;
574   Standard_Real R4  = R2 * R2;
575   Standard_Real R5  = R3 * R2;
576   Standard_Real Dr  = Ndir.Dot (DNdir);
577   Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
578   if (R5 <= gp::Resolution()) {
579      //We try another computation but the stability is not very good
580      //dixit ISG.
581      if (R4 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
582      // V2 = P" (U) :
583      Standard_Real R4 = R2 * R2;
584      D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
585      D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
586      D2Ndir.Multiply (offsetValue / R);
587      V2.Add (Vec2d(D2Ndir));
588      // V1 = P' (U) :
589      DNdir.Multiply(R);
590      DNdir.Subtract (Ndir.Multiplied (Dr/R));
591      DNdir.Multiply (offsetValue/R2);
592      V1.Add (Vec2d(DNdir));
593   }
594   else {
595      // Same computation as IICURV in EUCLID-IS because the stability is
596      // better.
597      // V2 = P" (U) :
598      D2Ndir.Multiply (offsetValue/R);
599      D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
600      D2Ndir.Subtract (Ndir.Multiplied (
601                       offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))
602                                       )
603                      );
604      V2.Add (Vec2d(D2Ndir));
605      // V1 = P' (U) :
606      DNdir.Multiply (offsetValue/R);
607      DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
608      V1.Add (Vec2d(DNdir));
609   }
610   //P (U) :
611   Ndir.Multiply (offsetValue/R);
612   Ndir.Add (Pbasis.XY());
613   P.SetXY (Ndir);
614 }
615
616 //=======================================================================
617 //function : FirstParameter
618 //purpose  : 
619 //=======================================================================
620
621 Standard_Real Geom2d_OffsetCurve::FirstParameter () const 
622 {
623   return basisCurve->FirstParameter();
624 }
625
626 //=======================================================================
627 //function : LastParameter
628 //purpose  : 
629 //=======================================================================
630
631 Standard_Real Geom2d_OffsetCurve::LastParameter () const 
632 {
633   return basisCurve->LastParameter();
634 }
635
636
637 //=======================================================================
638 //function : Offset
639 //purpose  : 
640 //=======================================================================
641
642 Standard_Real Geom2d_OffsetCurve::Offset () const { return offsetValue; }
643
644 //=======================================================================
645 //function : IsClosed
646 //purpose  : 
647 //=======================================================================
648
649 Standard_Boolean Geom2d_OffsetCurve::IsClosed () const 
650
651   gp_Pnt2d PF, PL;
652   D0(FirstParameter(),PF);
653   D0(LastParameter(),PL);
654   return ( PF.Distance(PL) <= gp::Resolution());
655 }
656
657 //=======================================================================
658 //function : IsCN
659 //purpose  : 
660 //=======================================================================
661
662 Standard_Boolean Geom2d_OffsetCurve::IsCN (const Standard_Integer N) const 
663 {
664   Standard_RangeError_Raise_if (N < 0, " " );
665   return basisCurve->IsCN (N + 1);
666 }
667
668 //=======================================================================
669 //function : IsPeriodic
670 //purpose  : 
671 //=======================================================================
672
673 Standard_Boolean Geom2d_OffsetCurve::IsPeriodic () const 
674
675   return basisCurve->IsPeriodic();
676 }
677
678 //=======================================================================
679 //function : Period
680 //purpose  : 
681 //=======================================================================
682
683 Standard_Real Geom2d_OffsetCurve::Period() const
684 {
685   return basisCurve->Period();
686 }
687
688 //=======================================================================
689 //function : Transform
690 //purpose  : 
691 //=======================================================================
692
693 void Geom2d_OffsetCurve::Transform (const Trsf2d& T) 
694 {
695   basisCurve->Transform (T);
696   offsetValue *= Abs(T.ScaleFactor());
697 }
698
699
700 //=======================================================================
701 //function : TransformedParameter
702 //purpose  : 
703 //=======================================================================
704
705 Standard_Real Geom2d_OffsetCurve::TransformedParameter(const Standard_Real U,
706                                                         const gp_Trsf2d& T) const
707 {
708   return basisCurve->TransformedParameter(U,T);
709 }
710
711 //=======================================================================
712 //function : ParametricTransformation
713 //purpose  : 
714 //=======================================================================
715
716 Standard_Real Geom2d_OffsetCurve::ParametricTransformation(const gp_Trsf2d& T) const
717 {
718   return basisCurve->ParametricTransformation(T);
719 }