c393920a121d1ae6c0c734e9c884aff1ea331e9a
[occt.git] / src / Geom / Geom_SurfaceOfRevolution.cxx
1 // Created on: 1993-03-10
2 // Created by: JCV
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BSplCLib.hxx>
19 #include <BSplSLib.hxx>
20 #include <Geom_BSplineCurve.hxx>
21 #include <Geom_Circle.hxx>
22 #include <Geom_Curve.hxx>
23 #include <Geom_Geometry.hxx>
24 #include <Geom_SurfaceOfRevolution.hxx>
25 #include <Geom_UndefinedDerivative.hxx>
26 #include <gp.hxx>
27 #include <gp_Ax1.hxx>
28 #include <gp_Ax2.hxx>
29 #include <gp_Ax2d.hxx>
30 #include <gp_Dir.hxx>
31 #include <gp_GTrsf2d.hxx>
32 #include <gp_Lin.hxx>
33 #include <gp_Pnt.hxx>
34 #include <gp_Trsf.hxx>
35 #include <gp_Vec.hxx>
36 #include <gp_XYZ.hxx>
37 #include <Precision.hxx>
38 #include <Standard_ConstructionError.hxx>
39 #include <Standard_NotImplemented.hxx>
40 #include <Standard_RangeError.hxx>
41 #include <Standard_Type.hxx>
42
43 #define  POLES    (poles->Array2())
44 #define  WEIGHTS  (weights->Array2())
45 #define  UKNOTS   (uknots->Array1())
46 #define  VKNOTS   (vknots->Array1())
47 #define  UFKNOTS  (ufknots->Array1())
48 #define  VFKNOTS  (vfknots->Array1())
49 #define  FMULTS   (BSplCLib::NoMults())
50
51 typedef Geom_SurfaceOfRevolution         SurfaceOfRevolution;
52 typedef Geom_Curve                       Curve;
53 typedef gp_Ax1  Ax1;
54 typedef gp_Ax2  Ax2;
55 typedef gp_Dir  Dir;
56 typedef gp_Lin  Lin;
57 typedef gp_Pnt  Pnt;
58 typedef gp_Trsf Trsf;
59 typedef gp_Vec  Vec;
60 typedef gp_XYZ  XYZ;
61
62 //=======================================================================
63 //function : LocateSide
64 //purpose  : This  method locates U parameter on basis BSpline curve 
65 //             and calls LocalDi  methods corresponding an  order of  
66 //             derivative and  position of the surface side contained      
67 //             the point relatively the curve knots.
68 //=======================================================================
69 static void LocateSide(const Standard_Real U,
70                        const Standard_Integer Side,
71                        const Handle(Geom_BSplineCurve)& BSplC,
72                        const Standard_Integer NDir,
73                        gp_Pnt& P,
74                        gp_Vec& D1U,
75                        gp_Vec& D2U,
76                        gp_Vec& D3U) 
77
78   Standard_Integer Ideb, Ifin;
79   Standard_Real ParTol=Precision::PConfusion()/2;
80   BSplC->Geom_BSplineCurve::LocateU(U,ParTol,Ideb,Ifin,Standard_False);   
81   if(Side == 1)
82     {
83       if(Ideb<1) Ideb=1;
84       if ((Ideb>=Ifin))  Ifin = Ideb+1;
85     }else
86       if(Side ==-1)
87         { 
88           if(Ifin > BSplC -> NbKnots()) Ifin=BSplC->NbKnots();
89           if ((Ideb>=Ifin))  Ideb = Ifin-1;
90         }
91    
92   switch(NDir) {
93   case 0 :  BSplC->Geom_BSplineCurve::LocalD0(U,Ideb,Ifin,P); break;
94   case 1 :  BSplC->Geom_BSplineCurve::LocalD1(U,Ideb,Ifin,P,D1U);  break;
95   case 2 :  BSplC->Geom_BSplineCurve::LocalD2(U,Ideb,Ifin,P,D1U,D2U); break;
96   case 3 :  BSplC->Geom_BSplineCurve::LocalD3(U,Ideb,Ifin,P,D1U,D2U,D3U); break;
97   }
98 }
99
100 //=======================================================================
101 //function : LocateSideN
102 //purpose  : This  method locates U parameter on basis BSpline curve 
103 //             and calls LocalDN  method corresponding  position of  surface side 
104 //             contained the point relatively the curve knots.  
105 //=======================================================================
106 static gp_Vec LocateSideN(const Standard_Real V,
107                           const Standard_Integer Side,
108                           const Handle(Geom_BSplineCurve)& BSplC,
109                           const Standard_Integer  Nv ) 
110
111   Standard_Integer Ideb, Ifin;
112   Standard_Real ParTol=Precision::PConfusion()/2;
113   BSplC->Geom_BSplineCurve::LocateU(V,ParTol,Ideb,Ifin,Standard_False);   
114   if(Side == 1)
115     {
116       if(Ideb<1) Ideb=1;
117       if ((Ideb>=Ifin))  Ifin = Ideb+1;
118     }else
119       if(Side ==-1)
120         { 
121           if(Ifin > BSplC -> NbKnots()) Ifin=BSplC->NbKnots();
122           if ((Ideb>=Ifin))  Ideb = Ifin-1;
123         }
124   return BSplC->Geom_BSplineCurve::LocalDN(V,Ideb,Ifin,Nv);
125 }
126
127
128
129
130 //=======================================================================
131 //function : Copy
132 //purpose  : 
133 //=======================================================================
134
135 Handle(Geom_Geometry) Geom_SurfaceOfRevolution::Copy () const {
136
137   return new Geom_SurfaceOfRevolution (basisCurve, Axis());
138 }
139
140
141 //=======================================================================
142 //function : Geom_SurfaceOfRevolution
143 //purpose  : 
144 //=======================================================================
145
146 Geom_SurfaceOfRevolution::Geom_SurfaceOfRevolution 
147   (const Handle(Geom_Curve)& C , 
148    const Ax1&           A1 ) : loc (A1.Location()) {
149
150   basisCurve = Handle(Geom_Curve)::DownCast(C->Copy());
151   direction  = A1.Direction();
152   smooth     = C->Continuity();
153 }
154
155
156 //=======================================================================
157 //function : UReverse
158 //purpose  : 
159 //=======================================================================
160
161 void Geom_SurfaceOfRevolution::UReverse () { 
162
163   direction.Reverse(); 
164 }
165
166
167 //=======================================================================
168 //function : UReversedParameter
169 //purpose  : 
170 //=======================================================================
171
172 Standard_Real Geom_SurfaceOfRevolution::UReversedParameter (const Standard_Real U) const {
173
174   return ( 2.*M_PI - U);
175 }
176
177
178 //=======================================================================
179 //function : VReverse
180 //purpose  : 
181 //=======================================================================
182
183 void Geom_SurfaceOfRevolution::VReverse () { 
184
185   basisCurve->Reverse(); 
186 }
187
188
189 //=======================================================================
190 //function : VReversedParameter
191 //purpose  : 
192 //=======================================================================
193
194 Standard_Real Geom_SurfaceOfRevolution::VReversedParameter (const Standard_Real V) const {
195
196   return basisCurve->ReversedParameter(V);
197 }
198
199
200 //=======================================================================
201 //function : Location
202 //purpose  : 
203 //=======================================================================
204
205 const gp_Pnt& Geom_SurfaceOfRevolution::Location () const { 
206
207   return loc; 
208 }
209
210 //=======================================================================
211 //function : IsUPeriodic
212 //purpose  : 
213 //=======================================================================
214
215 Standard_Boolean Geom_SurfaceOfRevolution::IsUPeriodic () const {
216
217   return Standard_True; 
218 }
219
220 //=======================================================================
221 //function : IsCNu
222 //purpose  : 
223 //=======================================================================
224
225 Standard_Boolean Geom_SurfaceOfRevolution::IsCNu (const Standard_Integer ) const  {
226
227   return Standard_True;
228 }
229
230 //=======================================================================
231 //function : Axis
232 //purpose  : 
233 //=======================================================================
234
235 Ax1 Geom_SurfaceOfRevolution::Axis () const  { 
236
237   return Ax1 (loc, direction); 
238 }
239
240 //=======================================================================
241 //function : IsCNv
242 //purpose  : 
243 //=======================================================================
244
245 Standard_Boolean Geom_SurfaceOfRevolution::IsCNv (const Standard_Integer N) const {
246
247   Standard_RangeError_Raise_if (N < 0, " ");
248   return basisCurve->IsCN(N);
249 }
250
251
252 //=======================================================================
253 //function : IsUClosed
254 //purpose  : 
255 //=======================================================================
256
257 Standard_Boolean Geom_SurfaceOfRevolution::IsUClosed () const { 
258
259   return Standard_True; 
260 }
261
262 //=======================================================================
263 //function : IsVClosed
264 //purpose  : 
265 //=======================================================================
266
267 Standard_Boolean Geom_SurfaceOfRevolution::IsVClosed () const 
268
269   return basisCurve->IsClosed();
270 }
271
272
273 //=======================================================================
274 //function : IsVPeriodic
275 //purpose  : 
276 //=======================================================================
277
278 Standard_Boolean Geom_SurfaceOfRevolution::IsVPeriodic () const { 
279
280   return basisCurve->IsPeriodic(); 
281 }
282
283
284 //=======================================================================
285 //function : SetAxis
286 //purpose  : 
287 //=======================================================================
288
289 void Geom_SurfaceOfRevolution::SetAxis (const Ax1& A1) {
290
291    direction = A1.Direction();
292    loc = A1.Location();
293 }
294
295
296 //=======================================================================
297 //function : SetDirection
298 //purpose  : 
299 //=======================================================================
300
301 void Geom_SurfaceOfRevolution::SetDirection (const Dir& V) {
302
303    direction = V;
304 }
305
306
307 //=======================================================================
308 //function : SetBasisCurve
309 //purpose  : 
310 //=======================================================================
311
312 void Geom_SurfaceOfRevolution::SetBasisCurve (const Handle(Geom_Curve)& C) {
313
314    basisCurve = Handle(Geom_Curve)::DownCast(C->Copy());
315    smooth     = C->Continuity();
316 }
317
318
319 //=======================================================================
320 //function : SetLocation
321 //purpose  : 
322 //=======================================================================
323
324 void Geom_SurfaceOfRevolution::SetLocation (const Pnt& P) {
325
326    loc = P;
327 }
328
329
330 //=======================================================================
331 //function : Bounds
332 //purpose  : 
333 //=======================================================================
334
335 void Geom_SurfaceOfRevolution::Bounds ( Standard_Real& U1, 
336                                         Standard_Real& U2, 
337                                         Standard_Real& V1, 
338                                         Standard_Real& V2 ) const {
339
340   U1 = 0.0; 
341   U2 = 2.0 * M_PI; 
342   V1 = basisCurve->FirstParameter();  
343   V2 = basisCurve->LastParameter();
344 }
345
346
347 //=======================================================================
348 //function : D0
349 //purpose  : 
350 //=======================================================================
351
352 void Geom_SurfaceOfRevolution::D0 
353   (const Standard_Real U, const Standard_Real V, Pnt& P) const {
354
355    // C origine sur l'axe de revolution
356    // Vdir vecteur unitaire definissant la direction de l'axe de revolution
357    // Q(v) point de parametre V sur la courbe de revolution
358    // OM (u,v) = OC + CQ * Cos(U) + (CQ.Vdir)(1-Cos(U)) * Vdir +
359    //            (Vdir^CQ)* Sin(U)
360
361
362    Pnt Pc = basisCurve->Value (V);                  //Q(v)
363    XYZ Q  = Pc.XYZ();                               //Q
364    XYZ C  = loc.XYZ();                              //C
365    Q.Subtract(C);                                   //CQ
366    XYZ Vdir     = direction.XYZ();                  //Vdir
367    XYZ VcrossCQ = Vdir.Crossed (Q);                 //Vdir^CQ
368    VcrossCQ.Multiply (Sin(U));                      //(Vdir^CQ)*Sin(U)
369    XYZ VdotCQ =
370      Vdir.Multiplied ((Vdir.Dot(Q))*(1.0 - Cos(U)));//(CQ.Vdir)(1-Cos(U))Vdir
371    VdotCQ.Add (VcrossCQ);                           //addition des composantes
372    Q.Multiply (Cos(U));
373    Q.Add (VdotCQ);
374    Q.Add (C);
375    P.SetXYZ(Q);
376 }
377
378
379 //=======================================================================
380 //function : D1
381 //purpose  : 
382 //=======================================================================
383
384 void Geom_SurfaceOfRevolution::D1 
385   (const Standard_Real U, const Standard_Real V, 
386          Pnt& P, 
387          Vec& D1U, Vec& D1V   ) const {
388
389    // C origine sur l'axe de revolution
390    // Vdir vecteur unitaire definissant la direction de l'axe de revolution
391    // Q(v) point de parametre V sur la courbe de revolution
392    // Q'(v) = DQ/DV
393    // OM (u,v) = OC + CQ * Cos(U) + (CQ.Vdir)(1-Cos(U)) * Vdir + 
394    //            (Vdir^CQ) * Sin(U)
395    // D1U_M(u,v) = - CQ * Sin(U) + (CQ.Vdir)(Sin(U)) * Vdir +
396    //              (Vdir^CQ) * Cos(U)
397    // D1V_M(u,v) = Q' * Cos(U) + (Q'.Vdir)(1-Cos(U)) * Vdir +
398    //              (Vdir^Q') * Sin(U)
399            
400       Pnt Pc;
401       Vec V1;
402       basisCurve->D1 (V, Pc, V1);
403       XYZ Q    = Pc.XYZ();                               //Q
404       XYZ DQv  = V1.XYZ();                               //Q'
405       XYZ C    = loc.XYZ();                              //C
406       XYZ Vdir = direction.XYZ();                        //Vdir
407       Q.Subtract(C);                                     //CQ
408       XYZ VcrossCQ  = Vdir.Crossed (Q);                  //Vdir^CQ
409       // If the point is placed on the axis of revolution then derivatives on U are undefined.
410       // Manually set them to zero.
411       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
412         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
413       XYZ VcrossDQv = Vdir.Crossed (DQv);                //(Vdir^Q')
414       XYZ VdotCQ    = Vdir.Multiplied (Vdir.Dot(Q));     //(Vdir.CQ)Vdir
415       XYZ VdotDQv   = Vdir.Multiplied (Vdir.Dot(DQv));   //(Vdir.Q')Vdir
416
417       VcrossDQv.Multiply (Sin(U));
418       VdotDQv.Multiply   (1.0 - Cos(U));
419       VdotDQv.Add        (VcrossDQv);
420       DQv.Multiply       (Cos(U));
421       DQv.Add            (VdotDQv);
422       D1V.SetXYZ         (DQv);
423
424       XYZ DQu = Q.Multiplied       (-Sin(U));
425       DQu.Add (VcrossCQ.Multiplied (Cos(U)));
426       DQu.Add (VdotCQ.Multiplied (Sin(U)));
427       D1U.SetXYZ (DQu);
428
429       Q.Multiply (Cos(U));
430       Q.Add      (C);
431       VcrossCQ.Multiply (Sin(U));
432       Q.Add             (VcrossCQ);   
433       VdotCQ.Multiply (1.0-Cos(U));
434       Q.Add           (VdotCQ);   
435       P.SetXYZ (Q);      
436     }
437
438 //=======================================================================
439 //function : D2
440 //purpose  : 
441 //=======================================================================
442
443 void Geom_SurfaceOfRevolution::D2 
444   (const Standard_Real   U, const Standard_Real V,
445          Pnt&   P, 
446          Vec& D1U, Vec& D1V, 
447          Vec& D2U, Vec& D2V, Vec& D2UV ) const {
448
449
450    // C origine sur l'axe de revolution
451    // V vecteur unitaire definissant la direction de l'axe de revolution
452    // Q(v) point de parametre V sur la courbe de revolution
453    // Q'(v) = D1Q/DV
454    // Q"(v) = D2Q/DV
455    // OM (u,v) = OC + CQ * Cos(U) + (CQ.Vdir)(1-Cos(U)) * Vdir +
456    //            (Vdir^CQ) * Sin(U)
457    // D1U_M(u,v) = - CQ * Sin(U) + (CQ.Vdir)(Sin(U)) * Vdir +
458    //              (Vdir^CQ) * Cos(U)
459    // D1V_M(u,v) = Q' * Cos(U) + (Q'.Vdir)(1-Cos(U)) * Vdir +
460    //              (Vdir^Q') * Sin(U)
461    // D2U_M(u,v) = -CQ * Cos(U) + (CQ.Vdir)(Cos(U)) * Vdir + 
462    //              (Vdir^CQ) * -(Sin(U))
463    // D2V_M(u,v) = Q" * Cos(U) + (Q".Vdir)(1-Cos(U)) * Vdir +
464    //              (Vdir^Q") * Sin(U)
465    // D2UV_M(u,v)= -Q' * Sin(U) + (Q'.Vdir)(Sin(U)) * Vdir +
466    //              (Vdir^Q') * Cos(U)
467
468
469       Pnt Pc;
470       Vec V1 , V2;
471       basisCurve->D2 (V, Pc, V1, V2);
472       XYZ Q     = Pc.XYZ();                                 //Q
473       XYZ D1Qv  = V1.XYZ();                                 //Q'
474       XYZ D2Qv  = V2.XYZ();                                 //Q"
475       XYZ C     = loc.XYZ();                                //C
476       XYZ Vdir  = direction.XYZ();                          //Vdir
477       Q.Subtract(C);                                        //CQ
478       XYZ VcrossCQ   = Vdir.Crossed (Q);                    //Vdir^CQ
479       // If the point is placed on the axis of revolution then derivatives on U are undefined.
480       // Manually set them to zero.
481       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
482         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
483       XYZ VcrossD1Qv = Vdir.Crossed (D1Qv);                 //(Vdir^Q')
484       XYZ VcrossD2Qv = Vdir.Crossed (D2Qv);                 //(Vdir^Q")
485       XYZ VdotCQ     = Vdir.Multiplied (Vdir.Dot(Q));       //(Vdir.CQ)Vdir
486       XYZ VdotD1Qv   = Vdir.Multiplied (Vdir.Dot(D1Qv));    //(Vdir.Q')Vdir
487       XYZ VdotD2Qv   = Vdir.Multiplied (Vdir.Dot(D2Qv));    //(Vdir.Q")Vdir
488
489       
490       XYZ D2Quv = D1Qv.Multiplied(-Sin(U));
491       D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));      
492       D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
493       D2UV.SetXYZ (D2Quv);
494
495       D1Qv.Multiply       (Cos(U));
496       VcrossD1Qv.Multiply (Sin(U));
497       VdotD1Qv.Multiply   (1.0 - Cos(U));
498       D1Qv.Add            (VcrossD1Qv);
499       D1Qv.Add            (VdotD1Qv);
500       D1V.SetXYZ          (D1Qv);
501
502       VcrossD2Qv.Multiply (Sin(U));
503       VdotD2Qv.Multiply (1.0 - Cos(U));
504       VdotD2Qv.Add (VcrossD2Qv);
505       D2Qv.Multiply (Cos(U));
506       D2Qv.Add (VdotD2Qv);
507       D2V.SetXYZ (D2Qv);
508
509       XYZ D1Qu = Q.Multiplied (-Sin(U));
510       D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
511       D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
512       D1U.SetXYZ (D1Qu);
513
514       Q.Multiply (Cos(U));
515       VcrossCQ.Multiply (Sin(U));
516       Q.Add (VcrossCQ);   
517       XYZ D2Qu = Q.Multiplied(-1.0);
518       D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
519       D2U.SetXYZ (D2Qu);
520       VdotCQ.Multiply (1.0-Cos(U));
521       Q.Add (VdotCQ);   
522       Q.Add (C);
523       P.SetXYZ (Q);      
524 }
525
526
527
528 //=======================================================================
529 //function : D3
530 //purpose  : 
531 //=======================================================================
532
533 void Geom_SurfaceOfRevolution::D3 
534   (const Standard_Real U, const Standard_Real V,
535          Pnt& P,
536          Vec& D1U, Vec& D1V, 
537          Vec& D2U, Vec& D2V, Vec& D2UV,
538          Vec& D3U, Vec& D3V, Vec& D3UUV, Vec& D3UVV ) const {
539
540    // C origine sur l'axe de revolution
541    // Vdir vecteur unitaire definissant la direction de l'axe de revolution
542    // Q(v) point de parametre V sur la courbe de revolution
543    // Q'(v) = D1Q/DV
544    // Q"(v) = D2Q/DV
545    // OM (u,v) = OC + CQ * Cos(u) + (CQ.Vdir)(1-Cos(u)) * Vdir +
546    //            (Vdir^CQ) * Sin(u)
547    // D1U_M(u,v) = - CQ * Sin(u) + (CQ.Vdir)(Sin(u)) * Vdir +
548    //              (Vdir^CQ) * Cos(u)
549    // D2U_M(u,v) = -CQ * Cos(u) + (CQ.Vdir)(Cos(u)) * Vdir +
550    //              (Vdir^CQ) * -Sin(u)
551    // D2UV_M(u,v)= -Q' * Sin(u) + (Q'.Vdir)(Sin(u)) * Vdir +
552    //              (Vdir^Q') * Cos(u)
553    // D3UUV_M(u,v) = -Q' * Cos(u) + (Q'.Vdir)(Cos(u)) * Vdir +
554    //                (Vdir^Q') * -Sin(u)
555    // D3U_M(u,v) = CQ * Sin(u) + (CQ.Vdir)(-Sin(u)) * Vdir +
556    //              (Vdir^CQ) * -Cos(u)
557    // D1V_M(u,v) = Q' * Cos(u) + (Q'.Vdir)(1-Cos(u)) * Vdir + 
558    //              (Vdir^Q') * Sin(u)
559    // D2V_M(u,v) = Q" * Cos(u) + (Q".Vdir)(1-Cos(u)) * Vdir +
560    //              (Vdir^Q") * Sin(u)
561    // D3UVV_M(u,v) = -Q" * Sin(u) + (Q".Vdir)(Sin(u)) * Vdir +
562    //                (Vdir^Q") * Cos(u)
563    // D3V_M(u,v) = Q'''* Cos(u) + (Q'''.Vdir)(1-Cos(u)) * Vdir +
564    //             (Vdir^Q''') * Sin(u)
565    
566
567       Pnt Pc;
568       Vec V1 , V2, V3;
569       basisCurve->D3 (V, Pc, V1, V2, V3);
570       XYZ Q     = Pc.XYZ();                                 //Q
571       XYZ D1Qv  = V1.XYZ();                                 //Q'
572       XYZ D2Qv  = V2.XYZ();                                 //Q"
573       XYZ D3Qv  = V3.XYZ();                                 //Q'''
574       XYZ C     = loc.XYZ();                                //C
575       XYZ Vdir  = direction.XYZ();                          //Vdir
576       Q.Subtract(C);                                        //CQ
577       XYZ VcrossCQ   = Vdir.Crossed (Q);                    //Vdir^CQ
578       // If the point is placed on the axis of revolution then derivatives on U are undefined.
579       // Manually set them to zero.
580       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
581         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
582       XYZ VcrossD1Qv = Vdir.Crossed (D1Qv);                 //(Vdir^Q')
583       XYZ VcrossD2Qv = Vdir.Crossed (D2Qv);                 //(Vdir^Q")
584       XYZ VcrossD3Qv = Vdir.Crossed (D3Qv);                 //(Vdir^Q''')
585       XYZ VdotCQ     = Vdir.Multiplied (Vdir.Dot(Q));       //(Vdir.CQ)Vdir
586       XYZ VdotD1Qv   = Vdir.Multiplied (Vdir.Dot(D1Qv));    //(Vdir.Q')Vdir
587       XYZ VdotD2Qv   = Vdir.Multiplied (Vdir.Dot(D2Qv));    //(Vdir.Q")Vdir
588       XYZ VdotD3Qv   = Vdir.Multiplied (Vdir.Dot(D3Qv));    //(Vdir.Q''')Vdir
589
590       XYZ D3Quuv = D1Qv.Multiplied (-Cos(U));
591       D3Quuv.Add (VcrossD1Qv.Multiplied (-Sin(U)));      
592       D3Quuv.Add (VdotD1Qv.Multiplied (Cos(U)));
593       D3UUV.SetXYZ (D3Quuv);
594
595       XYZ D2Quv = D1Qv.Multiplied (-Sin(U));
596       D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));      
597       D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
598       D2UV.SetXYZ (D2Quv);
599
600       D1Qv.Multiply (Cos(U));
601       VcrossD1Qv.Multiply (Sin(U));
602       VdotD1Qv.Multiply (1.0 - Cos(U));
603       D1Qv.Add (VcrossD1Qv);
604       D1Qv.Add (VdotD1Qv);
605       D1V.SetXYZ (D1Qv);
606
607       XYZ D3Qvvu = D2Qv.Multiplied (-Sin(U));
608       D3Qvvu.Add (VcrossD2Qv.Multiplied (Cos(U)));
609       D3Qvvu.Add (VdotD2Qv.Multiplied (Sin(U)));
610       D3UVV.SetXYZ (D3Qvvu);
611       
612       VcrossD2Qv.Multiply (Sin(U));
613       VdotD2Qv.Multiply (1.0 - Cos(U));
614       VdotD2Qv.Add (VcrossD2Qv);
615       D2Qv.Multiply (Cos(U));
616       D2Qv.Add (VdotD2Qv);
617       D2V.SetXYZ (D2Qv);
618
619       VcrossD3Qv.Multiply (Sin(U));
620       VdotD3Qv.Multiply (1.0 - Cos(U));
621       VdotD3Qv.Add (VcrossD2Qv);
622       D3Qv.Multiply (Cos(U));
623       D3Qv.Add (VdotD3Qv);
624       D3V.SetXYZ (D3Qv);
625
626       XYZ D1Qu = Q.Multiplied (- Sin(U));
627       D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
628       XYZ D3Qu = D1Qu.Multiplied (-1.0);
629       D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
630       D3Qu.Add (VdotCQ.Multiplied (-Sin(U)));
631       D1U.SetXYZ (D1Qu);
632       D3U.SetXYZ (D3Qu);
633
634       Q.Multiply (Cos(U));
635       VcrossCQ.Multiply (Sin(U));
636       Q.Add (VcrossCQ);   
637       XYZ D2Qu = Q.Multiplied(-1.0);
638       D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
639       D2U.SetXYZ (D2Qu);
640       VdotCQ.Multiply (1.0-Cos(U));
641       Q.Add (VdotCQ);   
642       Q.Add (C);
643       P.SetXYZ (Q);      
644 }
645
646
647 //=======================================================================
648 //function : DN
649 //purpose  : 
650 //=======================================================================
651
652 Vec Geom_SurfaceOfRevolution::DN (const Standard_Real    U , const Standard_Real    V, 
653                                   const Standard_Integer Nu, const Standard_Integer Nv) const {
654
655    Standard_RangeError_Raise_if (Nu + Nv < 1 || Nu < 0 || Nv < 0, " ");
656    if (Nu == 0) {
657      XYZ Vn = (basisCurve->DN (V, Nv)).XYZ();
658      XYZ Vdir = direction.XYZ();
659      XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
660      VDot.Multiply (1-Cos(U));
661      XYZ VCross = Vdir.Crossed (Vn);
662      VCross.Multiply (Sin(U));
663      Vn.Multiply (Cos(U));
664      Vn.Add (VDot);
665      Vn.Add (VCross);     
666      return Vec (Vn);
667    }
668    else if (Nv == 0) {
669      XYZ CQ = (basisCurve->Value (V)).XYZ() - loc.XYZ();
670      XYZ Vdir = direction.XYZ();
671      XYZ VDot = Vdir.Multiplied (CQ.Dot (Vdir));
672      XYZ VCross = Vdir.Crossed (CQ);
673      if ((Nu + 6) % 4 == 0) {
674        CQ.Multiply (-Cos (U));
675        VDot.Multiply (Cos(U));
676        VCross.Multiply (-Sin(U));
677      }
678      else if ((Nu + 5) % 4 == 0) {
679        CQ.Multiply (Sin (U));
680        VDot.Multiply (-Sin(U));
681        VCross.Multiply (-Cos(U));
682      }
683      else if ((Nu+3) % 4 == 0) {
684        CQ.Multiply (-Sin (U));
685        VDot.Multiply (+Sin(U));
686        VCross.Multiply (Cos(U));
687      }
688      else if (Nu+4 % 4 == 0) {
689        CQ.Multiply (Cos (U));
690        VDot.Multiply (-Cos(U));
691        VCross.Multiply (Sin(U));
692      }
693      CQ.Add (VDot);
694      CQ.Add (VCross);
695      return Vec (CQ);
696    }
697    else {
698      XYZ Vn = (basisCurve->DN (V, Nv)).XYZ();
699      XYZ Vdir = direction.XYZ();
700      XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
701      XYZ VCross = Vdir.Crossed (Vn);
702      if ((Nu + 6) % 4 == 0) {
703        Vn.Multiply (-Cos (U));
704        VDot.Multiply (Cos(U));
705        VCross.Multiply (-Sin(U));
706      }
707      else if ((Nu + 5) % 4 == 0) {
708        Vn.Multiply (Sin (U));
709        VDot.Multiply (-Sin(U));
710        VCross.Multiply (-Cos(U));
711      }
712      else if ((Nu+3) % 4 == 0) {
713        Vn.Multiply (-Sin (U));
714        VDot.Multiply (+Sin(U));
715        VCross.Multiply (Cos(U));
716      }
717      else if (Nu+4 % 4 == 0) {
718        Vn.Multiply (Cos (U));
719        VDot.Multiply (-Cos(U));
720        VCross.Multiply (Sin(U));
721      }
722      Vn.Add (VDot);
723      Vn.Add (VCross);     
724      return Vec (Vn);
725    }
726 }
727
728 //=======================================================================
729 //function : LocalD0
730 //purpose  : 
731 //=======================================================================
732
733 void Geom_SurfaceOfRevolution::LocalD0 (const Standard_Real    U,
734                                    const Standard_Real    V, 
735                                    const Standard_Integer VSide,
736                                          gp_Pnt&          P     )  const
737 {
738   if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
739     { 
740       gp_Vec D1V,D2V,D3V;
741       Handle( Geom_BSplineCurve) BSplC;
742       BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
743
744           LocateSide(V,VSide,BSplC,0,P,D1V,D2V,D3V);
745           XYZ Q  = P.XYZ();                               //Q
746           XYZ C  = loc.XYZ();                              //C
747           Q.Subtract(C);                                   //CQ
748           XYZ Vdir     = direction.XYZ();                  //Vdir
749           XYZ VcrossCQ = Vdir.Crossed (Q);                 //Vdir^CQ
750           VcrossCQ.Multiply (Sin(U));                      //(Vdir^CQ)*Sin(U)
751           XYZ VdotCQ =
752             Vdir.Multiplied ((Vdir.Dot(Q))*(1.0 - Cos(U)));//(CQ.Vdir)(1-Cos(U))Vdir
753           VdotCQ.Add (VcrossCQ);                           //addition des composantes
754           Q.Multiply (Cos(U));
755           Q.Add (VdotCQ);
756           Q.Add (C);
757           P.SetXYZ(Q);
758     }
759   else  D0(U,V,P);
760 }
761
762 //=======================================================================
763 //function : LocalD1
764 //purpose  : 
765 //=======================================================================
766
767 void Geom_SurfaceOfRevolution::LocalD1 (const Standard_Real    U, 
768                                    const Standard_Real    V,
769                                    const Standard_Integer VSide, 
770                                          gp_Pnt&          P,
771                                          gp_Vec&          D1U, 
772                                          gp_Vec&          D1V)     const
773 {
774  if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
775    {
776      Handle( Geom_BSplineCurve) BSplC;
777      BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
778          Vec D2V,D3V; 
779          Vec V1; 
780          LocateSide(V,VSide,BSplC,1,P,V1,D2V,D3V);
781          XYZ Q    = P.XYZ();                               //Q
782          XYZ DQv  = V1.XYZ();                               //Q'
783          XYZ C    = loc.XYZ();                              //C
784          XYZ Vdir = direction.XYZ();                        //Vdir
785          Q.Subtract(C);                                     //CQ
786          XYZ VcrossCQ  = Vdir.Crossed (Q);                  //Vdir^CQ
787       // If the point is placed on the axis of revolution then derivatives on U are undefined.
788       // Manually set them to zero.
789       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
790         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
791
792          XYZ VcrossDQv = Vdir.Crossed (DQv);                //(Vdir^Q')
793          XYZ VdotCQ    = Vdir.Multiplied (Vdir.Dot(Q));     //(Vdir.CQ)Vdir
794          XYZ VdotDQv   = Vdir.Multiplied (Vdir.Dot(DQv));   //(Vdir.Q')Vdir
795          
796          VcrossDQv.Multiply (Sin(U));
797          VdotDQv.Multiply   (1.0 - Cos(U));
798          VdotDQv.Add        (VcrossDQv);
799          DQv.Multiply       (Cos(U));
800          DQv.Add            (VdotDQv);
801          D1V.SetXYZ         (DQv);
802          
803          XYZ DQu = Q.Multiplied       (-Sin(U));
804          DQu.Add (VcrossCQ.Multiplied (Cos(U)));
805          DQu.Add (VdotCQ.Multiplied (Sin(U)));
806          D1U.SetXYZ (DQu);
807          
808          Q.Multiply (Cos(U));
809          Q.Add      (C);
810          VcrossCQ.Multiply (Sin(U));
811          Q.Add             (VcrossCQ);   
812          VdotCQ.Multiply (1.0-Cos(U));
813          Q.Add           (VdotCQ);   
814          P.SetXYZ (Q);  
815    }else 
816      D1(U,V,P,D1U,D1V);
817 }
818
819 //=======================================================================
820 //function : LocalD2
821 //purpose  : 
822 //=======================================================================
823
824 void Geom_SurfaceOfRevolution::LocalD2 (const Standard_Real    U,
825                                    const Standard_Real    V,
826                                    const Standard_Integer VSide,
827                                          gp_Pnt&          P,
828                                          gp_Vec&          D1U,
829                                          gp_Vec&          D1V,
830                                          gp_Vec&          D2U,
831                                          gp_Vec&          D2V,
832                                          gp_Vec&          D2UV) const
833 {
834   if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
835     {
836       Handle( Geom_BSplineCurve) BSplC;
837       BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
838           Vec d3v;
839           LocateSide(V,VSide,BSplC,2,P,D1V,D2V,d3v);
840           XYZ Q     = P.XYZ();                                   //Q
841           XYZ D1Qv  = D1V.XYZ();                                 //Q'
842           XYZ D2Qv  = D2V.XYZ();                                 //Q"
843           XYZ C     = loc.XYZ();                                 //C
844           XYZ Vdir  = direction.XYZ();                           //Vdir
845           Q.Subtract(C);                                         //CQ
846           XYZ VcrossCQ   = Vdir.Crossed (Q);                     //Vdir^CQ
847       // If the point is placed on the axis of revolution then derivatives on U are undefined.
848       // Manually set them to zero.
849       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
850         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
851
852           XYZ VcrossD1Qv = Vdir.Crossed (D1Qv);                  //(Vdir^Q')
853           XYZ VcrossD2Qv = Vdir.Crossed (D2Qv);                  //(Vdir^Q")
854           XYZ VdotCQ     = Vdir.Multiplied (Vdir.Dot(Q));        //(Vdir.CQ)Vdir
855           XYZ VdotD1Qv   = Vdir.Multiplied (Vdir.Dot(D1Qv));     //(Vdir.Q')Vdir
856           XYZ VdotD2Qv   = Vdir.Multiplied (Vdir.Dot(D2Qv));     //(Vdir.Q")Vdir
857           
858           
859           XYZ D2Quv = D1Qv.Multiplied(-Sin(U));
860           D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));      
861           D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
862           D2UV.SetXYZ (D2Quv);
863           
864           D1Qv.Multiply       (Cos(U));
865           VcrossD1Qv.Multiply (Sin(U));
866           VdotD1Qv.Multiply   (1.0 - Cos(U));
867           D1Qv.Add            (VcrossD1Qv);
868           D1Qv.Add            (VdotD1Qv);
869           D1V.SetXYZ          (D1Qv);
870           
871           VcrossD2Qv.Multiply (Sin(U));
872           VdotD2Qv.Multiply (1.0 - Cos(U));
873           VdotD2Qv.Add (VcrossD2Qv);
874           D2Qv.Multiply (Cos(U));
875           D2Qv.Add (VdotD2Qv);
876           D2V.SetXYZ (D2Qv);
877
878           XYZ D1Qu = Q.Multiplied (-Sin(U));
879           D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
880           D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
881           D1U.SetXYZ (D1Qu);
882           
883           Q.Multiply (Cos(U));
884           VcrossCQ.Multiply (Sin(U));
885           Q.Add (VcrossCQ);   
886           XYZ D2Qu = Q.Multiplied(-1.0);
887           D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
888           D2U.SetXYZ (D2Qu);
889           VdotCQ.Multiply (1.0-Cos(U));
890           Q.Add (VdotCQ);   
891           Q.Add (C);
892           P.SetXYZ (Q);      
893     } 
894   else
895     D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
896 }
897 //=======================================================================
898 //function : LocalD3
899 //purpose  : 
900 //=======================================================================
901
902 void Geom_SurfaceOfRevolution::LocalD3 (const Standard_Real    U, 
903                                    const Standard_Real    V,
904                                    const Standard_Integer VSide, 
905                                          gp_Pnt&          P,
906                                          gp_Vec&          D1U,
907                                          gp_Vec&          D1V, 
908                                          gp_Vec&          D2U, 
909                                          gp_Vec&          D2V, 
910                                          gp_Vec&          D2UV, 
911                                          gp_Vec&          D3U,
912                                          gp_Vec&          D3V,
913                                          gp_Vec&          D3UUV,
914                                          gp_Vec&          D3UVV) const
915 {
916   if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
917     {
918       Handle( Geom_BSplineCurve) BSplC;
919       BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
920
921           LocateSide(V,VSide,BSplC,3,P,D1V,D2V,D3V);
922           XYZ Q     = P.XYZ();                                   //Q
923           XYZ D1Qv  = D1V.XYZ();                                 //Q'
924           XYZ D2Qv  = D2V.XYZ();                                 //Q"
925           XYZ D3Qv  = D3V.XYZ();                                 //Q'''
926           XYZ C     = loc.XYZ();                                //C
927           XYZ Vdir  = direction.XYZ();                          //Vdir
928           Q.Subtract(C);                                        //CQ
929           XYZ VcrossCQ   = Vdir.Crossed (Q);                    //Vdir^CQ
930       // If the point is placed on the axis of revolution then derivatives on U are undefined.
931       // Manually set them to zero.
932       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
933         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
934
935           XYZ VcrossD1Qv = Vdir.Crossed (D1Qv);                 //(Vdir^Q')
936           XYZ VcrossD2Qv = Vdir.Crossed (D2Qv);                 //(Vdir^Q")
937           XYZ VcrossD3Qv = Vdir.Crossed (D3Qv);                 //(Vdir^Q''')
938           XYZ VdotCQ     = Vdir.Multiplied (Vdir.Dot(Q));       //(Vdir.CQ)Vdir
939           XYZ VdotD1Qv   = Vdir.Multiplied (Vdir.Dot(D1Qv));    //(Vdir.Q')Vdir
940           XYZ VdotD2Qv   = Vdir.Multiplied (Vdir.Dot(D2Qv));    //(Vdir.Q")Vdir
941           XYZ VdotD3Qv   = Vdir.Multiplied (Vdir.Dot(D3Qv));    //(Vdir.Q''')Vdir
942
943           XYZ D3Quuv = D1Qv.Multiplied (-Cos(U));
944           D3Quuv.Add (VcrossD1Qv.Multiplied (-Sin(U)));      
945           D3Quuv.Add (VdotD1Qv.Multiplied (Cos(U)));
946           D3UUV.SetXYZ (D3Quuv);
947           
948           XYZ D2Quv = D1Qv.Multiplied (-Sin(U));
949           D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));      
950           D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
951           D2UV.SetXYZ (D2Quv);
952           
953           D1Qv.Multiply (Cos(U));
954           VcrossD1Qv.Multiply (Sin(U));
955           VdotD1Qv.Multiply (1.0 - Cos(U));
956           D1Qv.Add (VcrossD1Qv);
957           D1Qv.Add (VdotD1Qv);
958           D1V.SetXYZ (D1Qv);
959
960           XYZ D3Qvvu = D2Qv.Multiplied (-Sin(U));
961           D3Qvvu.Add (VcrossD2Qv.Multiplied (Cos(U)));
962           D3Qvvu.Add (VdotD2Qv.Multiplied (Sin(U)));
963           D3UVV.SetXYZ (D3Qvvu);
964           
965           VcrossD2Qv.Multiply (Sin(U));
966           VdotD2Qv.Multiply (1.0 - Cos(U));
967           VdotD2Qv.Add (VcrossD2Qv);
968           D2Qv.Multiply (Cos(U));
969           D2Qv.Add (VdotD2Qv);
970           D2V.SetXYZ (D2Qv);
971           
972           VcrossD3Qv.Multiply (Sin(U));
973           VdotD3Qv.Multiply (1.0 - Cos(U));
974           VdotD3Qv.Add (VcrossD2Qv);
975           D3Qv.Multiply (Cos(U));
976           D3Qv.Add (VdotD3Qv);
977           D3V.SetXYZ (D3Qv);
978           
979           XYZ D1Qu = Q.Multiplied (- Sin(U));
980           D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
981           XYZ D3Qu = D1Qu.Multiplied (-1.0);
982           D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
983           D3Qu.Add (VdotCQ.Multiplied (-Sin(U)));
984           D1U.SetXYZ (D1Qu);
985           D3U.SetXYZ (D3Qu);
986           
987           Q.Multiply (Cos(U));
988           VcrossCQ.Multiply (Sin(U));
989           Q.Add (VcrossCQ);   
990           XYZ D2Qu = Q.Multiplied(-1.0);
991           D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
992           D2U.SetXYZ (D2Qu);
993           VdotCQ.Multiply (1.0-Cos(U));
994           Q.Add (VdotCQ);   
995           Q.Add (C);
996           P.SetXYZ (Q); 
997     }
998   else
999     D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
1000 }
1001 //=======================================================================
1002 //function : LocalDN
1003 //purpose  : 
1004 //=======================================================================
1005
1006 gp_Vec Geom_SurfaceOfRevolution::LocalDN  (const Standard_Real    U, 
1007                                       const Standard_Real    V,
1008                                       const Standard_Integer VSide,
1009                                       const Standard_Integer Nu,
1010                                       const Standard_Integer Nv) const
1011 {
1012   Standard_RangeError_Raise_if (Nu + Nv < 1 || Nu < 0 || Nv < 0, " "); 
1013   XYZ Vn, CQ;
1014   if (Nu == 0) {
1015     if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
1016       {
1017         Handle( Geom_BSplineCurve) BSplC;
1018         BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);  
1019         Vn = LocateSideN(V,VSide,BSplC,Nv).XYZ();
1020       }else
1021         return DN(U,V,Nu,Nv);
1022     XYZ Vdir = direction.XYZ();
1023     XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
1024     VDot.Multiply (1-Cos(U));
1025     XYZ VCross = Vdir.Crossed (Vn);
1026     VCross.Multiply (Sin(U));
1027     Vn.Multiply (Cos(U));
1028     Vn.Add (VDot);
1029     Vn.Add (VCross);     
1030     return Vec (Vn);
1031   }
1032   
1033   else if (Nv == 0) {
1034     if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
1035       {
1036         Handle( Geom_BSplineCurve) BSplC;
1037         BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
1038         CQ = LocateSideN(V,VSide,BSplC,Nv).XYZ() - loc.XYZ();
1039       }else
1040         return DN(U,V,Nu,Nv);
1041     XYZ Vdir = direction.XYZ();
1042     XYZ VDot = Vdir.Multiplied (CQ.Dot (Vdir));
1043     XYZ VCross = Vdir.Crossed (CQ);
1044     if ((Nu + 6) % 4 == 0) {
1045       CQ.Multiply (-Cos (U));
1046       VDot.Multiply (Cos(U));
1047       VCross.Multiply (-Sin(U));
1048     }
1049     else if ((Nu + 5) % 4 == 0) {
1050       CQ.Multiply (Sin (U));
1051       VDot.Multiply (-Sin(U));
1052       VCross.Multiply (-Cos(U));
1053     }
1054     else if ((Nu+3) % 4 == 0) {
1055       CQ.Multiply (-Sin (U));
1056       VDot.Multiply (+Sin(U));
1057       VCross.Multiply (Cos(U));
1058     }
1059     else if (Nu+4 % 4 == 0) {
1060       CQ.Multiply (Cos (U));
1061       VDot.Multiply (-Cos(U));
1062       VCross.Multiply (Sin(U));
1063     }
1064     CQ.Add (VDot);
1065     CQ.Add (VCross);
1066     return Vec (CQ);
1067   }
1068   
1069   else {
1070     if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
1071       {
1072         Handle( Geom_BSplineCurve) BSplC;
1073         BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
1074         Vn = LocateSideN(V,VSide,BSplC,Nv).XYZ();
1075       }else 
1076         return DN(U,V,Nu,Nv);
1077     XYZ Vdir = direction.XYZ();
1078     XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
1079     XYZ VCross = Vdir.Crossed (Vn);
1080     if ((Nu + 6) % 4 == 0) {
1081       Vn.Multiply (-Cos (U));
1082       VDot.Multiply (Cos(U));
1083       VCross.Multiply (-Sin(U));
1084     }
1085     else if ((Nu + 5) % 4 == 0) {
1086       Vn.Multiply (Sin (U));
1087       VDot.Multiply (-Sin(U));
1088       VCross.Multiply (-Cos(U));
1089     }
1090     else if ((Nu+3) % 4 == 0) {
1091       Vn.Multiply (-Sin (U));
1092       VDot.Multiply (+Sin(U));
1093       VCross.Multiply (Cos(U));
1094     }
1095     else if (Nu+4 % 4 == 0) {
1096       Vn.Multiply (Cos (U));
1097       VDot.Multiply (-Cos(U));
1098       VCross.Multiply (Sin(U));
1099     }
1100     Vn.Add (VDot);
1101     Vn.Add (VCross);     
1102     return Vec (Vn);
1103   }
1104 }
1105
1106 //=======================================================================
1107 //function : ReferencePlane
1108 //purpose  : 
1109 //=======================================================================
1110
1111 Ax2 Geom_SurfaceOfRevolution::ReferencePlane() const {
1112         
1113    Standard_NotImplemented::Raise ();
1114    return gp_Ax2();
1115 }
1116
1117
1118 //=======================================================================
1119 //function : UIso
1120 //purpose  : 
1121 //=======================================================================
1122
1123 Handle(Geom_Curve) Geom_SurfaceOfRevolution::UIso (const Standard_Real U) const {
1124
1125    Handle(Geom_Curve) C = Handle(Geom_Curve)::DownCast(basisCurve->Copy());
1126    Ax1 RotAxis = Ax1 (loc, direction);
1127    C->Rotate (RotAxis, U);
1128    return C;
1129 }
1130
1131
1132 //=======================================================================
1133 //function : VIso
1134 //purpose  : 
1135 //=======================================================================
1136
1137 Handle(Geom_Curve) Geom_SurfaceOfRevolution::VIso (const Standard_Real V) const {
1138
1139   Handle(Geom_Circle) Circ;
1140   Pnt Pc = basisCurve->Value (V);
1141   gp_Lin L1(loc,direction);
1142   Standard_Real Rad= L1.Distance(Pc);
1143
1144   Ax2 Rep ;
1145   if ( Rad > gp::Resolution()) { 
1146     XYZ P  = Pc.XYZ(); 
1147     XYZ C;
1148     C.SetLinearForm((P-loc.XYZ()).Dot(direction.XYZ()), 
1149                     direction.XYZ(), loc.XYZ() );
1150     P = P-C;
1151     if(P.Modulus() > gp::Resolution()) {
1152       gp_Dir D = P.Normalized();
1153       Rep = gp_Ax2(C, direction, D);
1154     }
1155     else 
1156       Rep = gp_Ax2(C, direction);
1157   }
1158   else
1159     Rep = gp_Ax2(Pc, direction);
1160
1161   Circ   = new Geom_Circle (Rep, Rad);
1162   return Circ;
1163 }
1164
1165
1166 //=======================================================================
1167 //function : Transform
1168 //purpose  : 
1169 //=======================================================================
1170
1171 void Geom_SurfaceOfRevolution::Transform (const Trsf& T) {
1172
1173   loc.Transform (T);
1174   direction.Transform (T);
1175   basisCurve->Transform (T);
1176   if(T.ScaleFactor()*T.HVectorialPart().Determinant() < 0.) UReverse(); 
1177 }
1178
1179 //=======================================================================
1180 //function : TransformParameters
1181 //purpose  : 
1182 //=======================================================================
1183
1184 void Geom_SurfaceOfRevolution::TransformParameters(Standard_Real& ,
1185                                                    Standard_Real& V,
1186                                                    const gp_Trsf& T) 
1187 const
1188 {
1189   V = basisCurve->TransformedParameter(V,T);
1190 }
1191
1192 //=======================================================================
1193 //function : ParametricTransformation
1194 //purpose  : 
1195 //=======================================================================
1196
1197 gp_GTrsf2d Geom_SurfaceOfRevolution::ParametricTransformation
1198 (const gp_Trsf& T) const
1199 {
1200   gp_GTrsf2d T2;
1201   gp_Ax2d Axis(gp::Origin2d(),gp::DX2d());
1202   T2.SetAffinity(Axis, basisCurve->ParametricTransformation(T));
1203   return T2;
1204 }
1205