0022922: Clean up warnings on uninitialized / unused variables
[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   Vec2d V2;
195   basisCurve->D2 (U, P, V1, V2);
196   Standard_Integer Index = 2;
197   while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
198     V1 = basisCurve->DN (U, Index);
199     Index++;
200   }
201   if (Index != 2) { V2 = basisCurve->DN (U, Index); }
202   XY Ndir  (V1.Y(), -V1.X());
203   XY DNdir (V2.Y(), -V2.X());
204   Standard_Real R2 = Ndir.SquareModulus();
205   Standard_Real R  = Sqrt (R2);
206   Standard_Real R3 = R * R2;
207   Standard_Real Dr = Ndir.Dot (DNdir);
208   if (R3 <= gp::Resolution()) {
209     //We try another computation but the stability is not very good.
210     if (R2 <= gp::Resolution()) Geom2d_UndefinedDerivative::Raise();
211     DNdir.Multiply(R);
212     DNdir.Subtract (Ndir.Multiplied (Dr/R));
213     DNdir.Multiply (offsetValue/R2);
214     V1.Add (Vec2d(DNdir));
215   }
216   else {
217     // Same computation as IICURV in EUCLID-IS because the stability is
218     // better
219     DNdir.Multiply (offsetValue/R);
220     DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
221     V1.Add (Vec2d(DNdir));
222   }
223   Ndir.Multiply (offsetValue/R);
224   Ndir.Add (P.XY());
225   P.SetXY (Ndir);
226 }
227
228 //=======================================================================
229 //function : D2
230 //purpose  : 
231 //=======================================================================
232
233 void Geom2d_OffsetCurve::D2 (const Standard_Real U, 
234                                    Pnt2d& P, 
235                                    Vec2d& V1, Vec2d& V2) const 
236 {
237    // P(u) = p(u) + Offset * Ndir / R
238    // with R = || p' ^ Z|| and Ndir = P' ^ Z
239
240    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
241
242    // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
243    //         Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
244
245   Vec2d V3;
246   basisCurve->D3 (U, P, V1, V2, V3);
247   Standard_Integer Index = 2;
248   while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
249     V1 = basisCurve->DN (U, Index);
250     Index++;
251   }
252   if (Index != 2) {
253     V2 = basisCurve->DN (U, Index);
254     V3 = basisCurve->DN (U, Index + 1);
255   }
256   XY Ndir (V1.Y(), -V1.X());
257   XY DNdir (V2.Y(), -V2.X());
258   XY D2Ndir (V3.Y(), -V3.X());
259   Standard_Real R2  = Ndir.SquareModulus();
260   Standard_Real R   = Sqrt (R2);
261   Standard_Real R3  = R2 * R;
262   Standard_Real R4  = R2 * R2;
263   Standard_Real R5  = R3 * R2;
264   Standard_Real Dr  = Ndir.Dot (DNdir);
265   Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
266   if (R5 <= gp::Resolution()) {
267     //We try another computation but the stability is not very good
268     //dixit ISG.
269     if (R4 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
270     // V2 = P" (U) :
271      Standard_Real R4 = R2 * R2;
272      D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
273      D2Ndir.Add (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
274      D2Ndir.Multiply (offsetValue / R);
275      V2.Add (Vec2d(D2Ndir));
276      // V1 = P' (U) :
277      DNdir.Multiply(R);
278      DNdir.Subtract (Ndir.Multiplied (Dr/R));
279      DNdir.Multiply (offsetValue/R2);
280      V1.Add (Vec2d(DNdir));
281    }
282    else {
283      // Same computation as IICURV in EUCLID-IS because the stability is
284      // better.
285      // V2 = P" (U) :
286     D2Ndir.Multiply (offsetValue/R);
287     D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
288     D2Ndir.Add (Ndir.Multiplied 
289                      (offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))));
290     V2.Add (Vec2d(D2Ndir));
291     // V1 = P' (U) 
292      DNdir.Multiply (offsetValue/R);
293      DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
294      V1.Add (Vec2d(DNdir));
295    }
296    //P (U) :
297    Ndir.Multiply (offsetValue/R);
298    Ndir.Add (P.XY());
299    P.SetXY (Ndir);
300 }
301
302
303 //=======================================================================
304 //function : D3
305 //purpose  : 
306 //=======================================================================
307
308 void Geom2d_OffsetCurve::D3 (const Standard_Real U, 
309                                    Pnt2d& P, 
310                                    Vec2d& V1, Vec2d& V2, Vec2d& V3) const {
311
312
313    // P(u) = p(u) + Offset * Ndir / R
314    // with R = || p' ^ Z|| and Ndir = P' ^ Z
315
316    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
317
318    // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
319    //         Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
320
321    //P"'(u) = p"'(u) + (Offset / R) * (D3Ndir - (3.0 * Dr/R**2 ) * D2Ndir -
322    //         (3.0 * D2r / R2) * DNdir) + (3.0 * Dr * Dr / R4) * DNdir -
323    //         (D3r/R2) * Ndir + (6.0 * Dr * Dr / R4) * Ndir +
324    //         (6.0 * Dr * D2r / R4) * Ndir - (15.0 * Dr* Dr* Dr /R6) * Ndir
325
326
327
328    basisCurve->D3 (U, P, V1, V2, V3);
329    Vec2d V4 = basisCurve->DN (U, 4);
330    Standard_Integer Index = 2;
331    while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
332      V1 = basisCurve->DN (U, Index);
333      Index++;
334    }
335    if (Index != 2) {
336      V2 = basisCurve->DN (U, Index);
337      V3 = basisCurve->DN (U, Index + 1);
338      V4 = basisCurve->DN (U, Index + 2);
339    }
340    XY Ndir   (V1.Y(), -V1.X());
341    XY DNdir  (V2.Y(), -V2.X());
342    XY D2Ndir (V3.Y(), -V3.X());
343    XY D3Ndir (V4.Y(), -V4.X());
344    Standard_Real R2  = Ndir.SquareModulus();
345    Standard_Real R   = Sqrt (R2);
346    Standard_Real R3  = R2 * R;
347    Standard_Real R4  = R2 * R2;
348    Standard_Real R5  = R3 * R2;
349    Standard_Real R6  = R3 * R3;
350    Standard_Real R7  = R5 * R2;
351    Standard_Real Dr  = Ndir.Dot (DNdir);
352    Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
353    Standard_Real D3r = Ndir.Dot (D3Ndir) + 3.0 * DNdir.Dot (D2Ndir);
354    if (R7 <= gp::Resolution()) {
355      //We try another computation but the stability is not very good
356      //dixit ISG.
357      if (R6 <= gp::Resolution()) Geom2d_UndefinedDerivative::Raise();
358      // V3 = P"' (U) :
359      D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R2));
360      D3Ndir.Subtract (
361      (DNdir.Multiplied ((3.0 * offsetValue) * ((D2r/R2) + (Dr*Dr)/R4))));
362      D3Ndir.Add (Ndir.Multiplied (
363      (offsetValue * (6.0*Dr*Dr/R4 + 6.0*Dr*D2r/R4 - 15.0*Dr*Dr*Dr/R6 - D3r))
364      ));
365      D3Ndir.Multiply (offsetValue/R);
366      V3.Add (Vec2d(D3Ndir));
367      // V2 = P" (U) :
368      Standard_Real R4 = R2 * R2;
369      D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
370      D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
371      D2Ndir.Multiply (offsetValue / R);
372      V2.Add (Vec2d(D2Ndir));
373      // V1 = P' (U) :
374      DNdir.Multiply(R);
375      DNdir.Subtract (Ndir.Multiplied (Dr/R));
376      DNdir.Multiply (offsetValue/R2);
377      V1.Add (Vec2d(DNdir));
378    }
379    else {
380      // Same computation as IICURV in EUCLID-IS because the stability is
381      // better.
382      // V3 = P"' (U) :
383       D3Ndir.Multiply (offsetValue/R);
384      D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R3));
385      D3Ndir.Subtract (DNdir.Multiplied (
386      ((3.0 * offsetValue) * ((D2r/R3) + (Dr*Dr)/R5))) );
387      D3Ndir.Add (Ndir.Multiplied (
388      (offsetValue * (6.0*Dr*Dr/R5 + 6.0*Dr*D2r/R5 - 15.0*Dr*Dr*Dr/R7 - D3r))
389      ));
390      V3.Add (Vec2d(D3Ndir));
391      // V2 = P" (U) :
392      D2Ndir.Multiply (offsetValue/R);
393      D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
394      D2Ndir.Subtract (Ndir.Multiplied (
395                       offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))
396                                       )
397                      );
398      V2.Add (Vec2d(D2Ndir));
399      // V1 = P' (U) :
400      DNdir.Multiply (offsetValue/R);
401      DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
402      V1.Add (Vec2d(DNdir));
403    }
404    //P (U) :
405    Ndir.Multiply (offsetValue/R);
406    Ndir.Add (P.XY());
407    P.SetXY (Ndir);
408 }
409
410 //=======================================================================
411 //function : DN
412 //purpose  : 
413 //=======================================================================
414
415 Vec2d Geom2d_OffsetCurve::DN (const Standard_Real U, 
416                               const Standard_Integer N) const 
417 {
418   Standard_RangeError_Raise_if (N < 1, "Geom2d_OffsetCurve::DN()");
419
420   gp_Vec2d VN, VBidon;
421   gp_Pnt2d PBidon;
422   switch (N) {
423   case 1: D1( U, PBidon, VN); break;
424   case 2: D2( U, PBidon, VBidon, VN); break;
425   case 3: D3( U, PBidon, VBidon, VBidon, VN); break;
426   default:
427     Standard_NotImplemented::Raise();
428   }
429   
430   return VN;
431 }
432
433
434 //=======================================================================
435 //function : Value
436 //purpose  : 
437 //=======================================================================
438
439 void Geom2d_OffsetCurve::Value (const Standard_Real U, 
440                                 Pnt2d& P, Pnt2d& Pbasis,
441                                 Vec2d& V1basis ) const 
442 {
443
444   basisCurve->D1 (U, Pbasis, V1basis);
445   Standard_Integer Index = 2;
446   while (V1basis.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
447     V1basis = basisCurve->DN (U, Index);
448     Index++;
449   }
450   Standard_Real A = V1basis.Y();
451   Standard_Real B = - V1basis.X();
452   Standard_Real R = Sqrt(A*A + B * B);
453   if (R <= gp::Resolution())  Geom2d_UndefinedValue::Raise();
454   A = A * offsetValue/R;
455   B = B * offsetValue/R;
456   P.SetCoord (A + Pbasis.X(), B + Pbasis.Y());
457 }
458
459
460 //=======================================================================
461 //function : D1
462 //purpose  : 
463 //=======================================================================
464
465 void Geom2d_OffsetCurve::D1 (const Standard_Real U, 
466                              Pnt2d& P, Pnt2d& Pbasis,
467                              Vec2d& V1, Vec2d& V1basis, 
468                              Vec2d& V2basis ) const 
469 {
470    // P(u) = p(u) + Offset * Ndir / R
471    // with R = || p' ^ Z|| and Ndir = P' ^ Z
472
473    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
474
475    basisCurve->D2 (U, Pbasis, V1basis, V2basis);
476    V1 = V1basis;
477    Vec2d V2 = V2basis;
478    Standard_Integer Index = 2;
479    while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
480      V1 = basisCurve->DN (U, Index);
481      Index++;
482    }
483    if (Index != 2) {
484      V2 = basisCurve->DN (U, Index);
485    }
486    XY Ndir (V1.Y(), -V1.X());
487    XY DNdir (V2.Y(), -V2.X());
488    Standard_Real R2 = Ndir.SquareModulus();
489    Standard_Real R = Sqrt (R2);
490    Standard_Real R3 = R * R2;
491    Standard_Real Dr = Ndir.Dot (DNdir);
492    if (R3 <= gp::Resolution()) {
493       //We try another computation but the stability is not very good.
494       if (R2 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
495       DNdir.Multiply(R);
496       DNdir.Subtract (Ndir.Multiplied (Dr/R));
497       DNdir.Multiply (offsetValue / R2);
498       V1.Add (Vec2d(DNdir));
499    }
500    else {
501       // Same computation as IICURV in EUCLID-IS because the stability is
502       // better
503       DNdir.Multiply (offsetValue/R);
504       DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
505       V1.Add (Vec2d(DNdir));
506    }
507    Ndir.Multiply (offsetValue/R);
508    Ndir.Add (Pbasis.XY());
509    P.SetXY (Ndir);
510 }
511
512
513 //=======================================================================
514 //function : D2
515 //purpose  : 
516 //=======================================================================
517
518 void Geom2d_OffsetCurve::D2 (const Standard_Real U, 
519                              Pnt2d& P, Pnt2d& Pbasis,
520                              Vec2d& V1, Vec2d& V2, 
521                              Vec2d& V1basis, Vec2d& V2basis,
522                              Vec2d& V3basis ) const 
523 {
524    // P(u) = p(u) + Offset * Ndir / R
525    // with R = || p' ^ Z|| and Ndir = P' ^ Z
526
527    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
528
529    // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
530    //         Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
531
532   basisCurve->D3 (U, Pbasis, V1basis, V2basis, V3basis);
533   Standard_Integer Index = 2;
534   V1 = V1basis;
535   V2 = V2basis;
536   Vec2d V3 = V3basis;
537   while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
538     V1 = basisCurve->DN (U, Index);
539     Index++;
540   }
541   if (Index != 2) {
542     V2 = basisCurve->DN (U, Index);
543     V3 = basisCurve->DN (U, Index + 1);
544   }
545   XY Ndir (V1.Y(), -V1.X());
546   XY DNdir (V2.Y(), -V2.X());
547   XY D2Ndir (V3.Y(), -V3.X());
548   Standard_Real R2  = Ndir.SquareModulus();
549   Standard_Real R   = Sqrt (R2);
550   Standard_Real R3  = R2 * R;
551   Standard_Real R4  = R2 * R2;
552   Standard_Real R5  = R3 * R2;
553   Standard_Real Dr  = Ndir.Dot (DNdir);
554   Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
555   if (R5 <= gp::Resolution()) {
556      //We try another computation but the stability is not very good
557      //dixit ISG.
558      if (R4 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
559      // V2 = P" (U) :
560      Standard_Real R4 = R2 * R2;
561      D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
562      D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
563      D2Ndir.Multiply (offsetValue / R);
564      V2.Add (Vec2d(D2Ndir));
565      // V1 = P' (U) :
566      DNdir.Multiply(R);
567      DNdir.Subtract (Ndir.Multiplied (Dr/R));
568      DNdir.Multiply (offsetValue/R2);
569      V1.Add (Vec2d(DNdir));
570   }
571   else {
572      // Same computation as IICURV in EUCLID-IS because the stability is
573      // better.
574      // V2 = P" (U) :
575      D2Ndir.Multiply (offsetValue/R);
576      D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
577      D2Ndir.Subtract (Ndir.Multiplied (
578                       offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))
579                                       )
580                      );
581      V2.Add (Vec2d(D2Ndir));
582      // V1 = P' (U) :
583      DNdir.Multiply (offsetValue/R);
584      DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));        
585      V1.Add (Vec2d(DNdir));
586   }
587   //P (U) :
588   Ndir.Multiply (offsetValue/R);
589   Ndir.Add (Pbasis.XY());
590   P.SetXY (Ndir);
591 }
592
593 //=======================================================================
594 //function : FirstParameter
595 //purpose  : 
596 //=======================================================================
597
598 Standard_Real Geom2d_OffsetCurve::FirstParameter () const 
599 {
600   return basisCurve->FirstParameter();
601 }
602
603 //=======================================================================
604 //function : LastParameter
605 //purpose  : 
606 //=======================================================================
607
608 Standard_Real Geom2d_OffsetCurve::LastParameter () const 
609 {
610   return basisCurve->LastParameter();
611 }
612
613
614 //=======================================================================
615 //function : Offset
616 //purpose  : 
617 //=======================================================================
618
619 Standard_Real Geom2d_OffsetCurve::Offset () const { return offsetValue; }
620
621 //=======================================================================
622 //function : IsClosed
623 //purpose  : 
624 //=======================================================================
625
626 Standard_Boolean Geom2d_OffsetCurve::IsClosed () const 
627
628   gp_Pnt2d PF, PL;
629   D0(FirstParameter(),PF);
630   D0(LastParameter(),PL);
631   return ( PF.Distance(PL) <= gp::Resolution());
632 }
633
634 //=======================================================================
635 //function : IsCN
636 //purpose  : 
637 //=======================================================================
638
639 Standard_Boolean Geom2d_OffsetCurve::IsCN (const Standard_Integer N) const 
640 {
641   Standard_RangeError_Raise_if (N < 0, " " );
642   return basisCurve->IsCN (N + 1);
643 }
644
645 //=======================================================================
646 //function : IsPeriodic
647 //purpose  : 
648 //=======================================================================
649
650 Standard_Boolean Geom2d_OffsetCurve::IsPeriodic () const 
651
652   return basisCurve->IsPeriodic();
653 }
654
655 //=======================================================================
656 //function : Period
657 //purpose  : 
658 //=======================================================================
659
660 Standard_Real Geom2d_OffsetCurve::Period() const
661 {
662   return basisCurve->Period();
663 }
664
665 //=======================================================================
666 //function : Transform
667 //purpose  : 
668 //=======================================================================
669
670 void Geom2d_OffsetCurve::Transform (const Trsf2d& T) 
671 {
672   basisCurve->Transform (T);
673   offsetValue *= Abs(T.ScaleFactor());
674 }
675
676
677 //=======================================================================
678 //function : TransformedParameter
679 //purpose  : 
680 //=======================================================================
681
682 Standard_Real Geom2d_OffsetCurve::TransformedParameter(const Standard_Real U,
683                                                         const gp_Trsf2d& T) const
684 {
685   return basisCurve->TransformedParameter(U,T);
686 }
687
688 //=======================================================================
689 //function : ParametricTransformation
690 //purpose  : 
691 //=======================================================================
692
693 Standard_Real Geom2d_OffsetCurve::ParametricTransformation(const gp_Trsf2d& T) const
694 {
695   return basisCurve->ParametricTransformation(T);
696 }