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