0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / GeomConvert / GeomConvert_1.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 //Jean-Claude Vauthier Novembre 1991
16 //Passage sur C1 Aout 1992 et ajout transformation Bezier->BSpline
17 //Modif JCV correction bug le 02/08/1993
18
19
20 #include <GeomConvert.ixx>
21
22
23 #include <BSplCLib.hxx>
24
25 #include <Standard_DomainError.hxx>
26 #include <Standard_NotImplemented.hxx>
27
28 #include <Convert_ElementarySurfaceToBSplineSurface.hxx>
29 #include <Convert_ConeToBSplineSurface.hxx>
30 #include <Convert_CylinderToBSplineSurface.hxx>
31 #include <Convert_SphereToBSplineSurface.hxx>
32 #include <Convert_TorusToBSplineSurface.hxx>
33 #include <GeomConvert_ApproxSurface.hxx>
34
35 #include <Geom_OffsetSurface.hxx>
36 #include <Geom_Surface.hxx>
37 #include <Geom_Plane.hxx>
38 #include <Geom_CylindricalSurface.hxx>
39 #include <Geom_ConicalSurface.hxx>
40 #include <Geom_SphericalSurface.hxx>
41 #include <Geom_ToroidalSurface.hxx>
42 #include <Geom_RectangularTrimmedSurface.hxx>
43 #include <Geom_SurfaceOfRevolution.hxx>
44 #include <Geom_SurfaceOfLinearExtrusion.hxx>
45 #include <Geom_BSplineSurface.hxx>
46 #include <Geom_BezierSurface.hxx>
47 #include <Geom_Geometry.hxx>
48 #include <Geom_TrimmedCurve.hxx>
49
50 #include <GeomAdaptor_Surface.hxx>
51
52 #include <TColgp_Array2OfPnt.hxx>
53 #include <TColgp_Array1OfPnt.hxx>
54 #include <TColStd_Array1OfReal.hxx>
55 #include <TColStd_Array2OfReal.hxx>
56 #include <TColStd_Array1OfInteger.hxx>
57 #include <TColStd_Array2OfInteger.hxx>
58 #include <TColStd_HArray1OfReal.hxx>
59 #include <TColStd_HArray1OfInteger.hxx>
60
61 #include <Precision.hxx>
62 #include <gp_Vec.hxx>
63 #include <gp_Sphere.hxx>
64 #include <gp_Cylinder.hxx>
65 #include <gp_Cone.hxx>
66 #include <gp_Torus.hxx>
67 #include <gp_Pln.hxx>
68 #include <gp_Trsf.hxx>
69 #include <gp_GTrsf.hxx>
70
71 typedef Geom_Surface                          Surface;
72 typedef Geom_BSplineSurface                   BSplineSurface;
73 typedef TColStd_Array1OfReal                 Array1OfReal;
74 typedef TColStd_Array2OfReal                 Array2OfReal;
75 typedef TColStd_Array1OfInteger              Array1OfInteger;
76 typedef TColStd_Array2OfInteger              Array2OfInteger;
77 typedef TColgp_Array2OfPnt                          Array2OfPnt;
78 typedef TColgp_Array1OfPnt                          Array1OfPnt;
79 typedef gp_Pnt Pnt;
80
81 //=======================================================================
82 //function : BSplineSurfaceBuilder
83 //purpose  : 
84 //=======================================================================
85
86 Handle(Geom_BSplineSurface) BSplineSurfaceBuilder 
87   (const Convert_ElementarySurfaceToBSplineSurface& Convert) 
88 {
89   Handle(Geom_BSplineSurface) TheSurface;
90   Standard_Integer UDegree  = Convert.UDegree ();
91   Standard_Integer VDegree  = Convert.VDegree ();
92   Standard_Integer NbUPoles = Convert.NbUPoles();
93   Standard_Integer NbVPoles = Convert.NbVPoles();
94   Standard_Integer NbUKnots = Convert.NbUKnots();
95   Standard_Integer NbVKnots = Convert.NbVKnots();
96   Array2OfPnt     Poles   (1, NbUPoles, 1, NbVPoles);
97   Array2OfReal    Weights (1, NbUPoles, 1, NbVPoles);
98   Array1OfReal    UKnots  (1, NbUKnots);
99   Array1OfReal    VKnots  (1, NbVKnots);
100   Array1OfInteger UMults  (1, NbUKnots);
101   Array1OfInteger VMults  (1, NbVKnots);
102   Standard_Integer i, j;
103   for (j = 1; j <= NbVPoles; j++) {
104     for (i = 1; i <= NbUPoles; i++) {
105       Poles   (i, j) = Convert.Pole   (i, j);
106       Weights (i, j) = Convert.Weight (i, j);         
107     }
108   }
109   for (i = 1; i <= NbUKnots; i++) {
110     UKnots (i) = Convert.UKnot (i);
111     UMults (i) = Convert.UMultiplicity (i);
112   }
113   for (i = 1; i <= NbVKnots; i++) {
114     VKnots (i) = Convert.VKnot (i);
115     VMults (i) = Convert.VMultiplicity (i);
116   }
117   TheSurface = new BSplineSurface (Poles, Weights, UKnots, VKnots, 
118     UMults, VMults, UDegree, VDegree,
119     Convert.IsUPeriodic(),
120     Convert.IsVPeriodic());
121   return TheSurface;
122 }
123
124 //=======================================================================
125 //function : SplitBSplineSurface
126 //purpose  : 
127 //=======================================================================
128
129 Handle(Geom_BSplineSurface) GeomConvert::SplitBSplineSurface 
130   (const Handle(Geom_BSplineSurface)& S,
131   const Standard_Integer FromUK1, 
132   const Standard_Integer ToUK2,
133   const Standard_Integer FromVK1, 
134   const Standard_Integer ToVK2,
135   const Standard_Boolean SameUOrientation, 
136   const Standard_Boolean SameVOrientation ) 
137 {
138   Standard_Integer FirstU = S->FirstUKnotIndex ();
139   Standard_Integer FirstV = S->FirstVKnotIndex ();
140   Standard_Integer LastU  = S->LastUKnotIndex  ();
141   Standard_Integer LastV  = S->LastVKnotIndex  ();
142   if (FromUK1 == ToUK2 || FromVK1 == ToVK2)   Standard_DomainError::Raise();
143   Standard_Integer FirstUK = Min (FromUK1, ToUK2);
144   Standard_Integer LastUK  = Max (FromUK1, ToUK2);
145   Standard_Integer FirstVK = Min (FromVK1, ToVK2);
146   Standard_Integer LastVK  = Max (FromVK1, ToVK2);
147   if (FirstUK < FirstU || LastUK > LastU || 
148     FirstVK < FirstV || LastVK > LastV) { Standard_DomainError::Raise(); }
149
150   Handle(Geom_BSplineSurface) S1= Handle(Geom_BSplineSurface)::DownCast(S->Copy());
151
152   S1->Segment(S1->UKnot(FirstUK),S1->UKnot(LastUK),
153     S1->VKnot(FirstVK),S1->VKnot(LastVK));
154
155   if (S->IsUPeriodic()) {
156     if (!SameUOrientation) S1->UReverse();
157   }
158   else {
159     if (FromUK1 > ToUK2)   S1->UReverse();
160   }
161   if (S->IsVPeriodic()) {
162     if (!SameVOrientation) S1->VReverse();
163   }
164   else {
165     if (FromVK1 > ToVK2)   S1->VReverse();
166   }
167   return S1;
168 }
169
170
171 //=======================================================================
172 //function : SplitBSplineSurface
173 //purpose  : 
174 //=======================================================================
175
176 Handle(Geom_BSplineSurface) GeomConvert::SplitBSplineSurface 
177   (const Handle(Geom_BSplineSurface)& S,
178   const Standard_Integer FromK1,
179   const Standard_Integer ToK2,
180   const Standard_Boolean USplit, 
181   const Standard_Boolean SameOrientation )
182 {
183   if (FromK1 == ToK2)   Standard_DomainError::Raise();
184
185
186   Handle(Geom_BSplineSurface) S1 = Handle(Geom_BSplineSurface)::DownCast(S->Copy());
187
188   if (USplit) {
189
190     Standard_Integer FirstU = S->FirstUKnotIndex ();
191     Standard_Integer LastU  = S->LastUKnotIndex  ();
192     Standard_Integer FirstUK = Min (FromK1, ToK2);
193     Standard_Integer LastUK  = Max (FromK1, ToK2);
194     if (FirstUK < FirstU || LastUK > LastU)  Standard_DomainError::Raise();
195
196     S1->Segment( S1->UKnot(FirstUK), 
197       S1->UKnot(LastUK),
198       S1->VKnot(S1->FirstVKnotIndex()),
199       S1->VKnot(S1->LastVKnotIndex()));
200
201     if (S->IsUPeriodic()) {
202       if (!SameOrientation) S1->UReverse();
203     }
204     else {
205       if (FromK1 > ToK2)    S1->UReverse();
206     }
207
208   }
209   else {
210
211     Standard_Integer FirstV = S->FirstVKnotIndex ();
212     Standard_Integer LastV  = S->LastVKnotIndex  ();
213     Standard_Integer FirstVK = Min (FromK1, ToK2);
214     Standard_Integer LastVK  = Max (FromK1, ToK2);
215     if (FirstVK < FirstV || LastVK > LastV)  Standard_DomainError::Raise();
216
217     S1->Segment( S1->UKnot(S1->FirstUKnotIndex()), 
218       S1->UKnot(S1->LastUKnotIndex()),
219       S1->VKnot(FirstVK),
220       S1->VKnot(LastVK));
221
222
223     if (S->IsVPeriodic()) {
224       if (!SameOrientation) S1->VReverse();
225     }
226     else {
227       if (FromK1 > ToK2)    S1->VReverse();
228     }
229   }
230   return S1;
231 }
232
233
234 //=======================================================================
235 //function : SplitBSplineSurface
236 //purpose  : 
237 //=======================================================================
238
239 Handle(Geom_BSplineSurface) GeomConvert::SplitBSplineSurface 
240   (const Handle(Geom_BSplineSurface)& S, 
241   const Standard_Real FromU1, 
242   const Standard_Real ToU2,
243   const Standard_Real FromV1, 
244   const Standard_Real ToV2,
245   //   const Standard_Real ParametricTolerance,
246   const Standard_Real ,
247   const Standard_Boolean SameUOrientation, 
248   const Standard_Boolean SameVOrientation )
249 {
250   Standard_Real FirstU = Min( FromU1, ToU2);
251   Standard_Real LastU  = Max( FromU1, ToU2);
252   Standard_Real FirstV = Min( FromV1, ToV2);
253   Standard_Real LastV  = Max( FromV1, ToV2);
254
255   Handle (Geom_BSplineSurface) NewSurface 
256     = Handle(Geom_BSplineSurface)::DownCast(S->Copy());
257
258   NewSurface->Segment(FirstU, LastU, FirstV, LastV);
259
260   if (S->IsUPeriodic()) { 
261     if (!SameUOrientation)  NewSurface->UReverse(); 
262   }
263   else { 
264     if (FromU1 > ToU2)    NewSurface->UReverse(); 
265   }
266   if (S->IsVPeriodic()) {
267     if (!SameVOrientation)  NewSurface->VReverse();
268   }
269   else {
270     if (FromV1 > ToV2)     NewSurface->VReverse();
271   }
272   return NewSurface;
273 }
274
275
276 //=======================================================================
277 //function : SplitBSplineSurface
278 //purpose  : 
279 //=======================================================================
280
281 Handle(Geom_BSplineSurface) GeomConvert::SplitBSplineSurface 
282   (const Handle(Geom_BSplineSurface)& S, 
283   const Standard_Real                    FromParam1, 
284   const Standard_Real                    ToParam2,
285   const Standard_Boolean                 USplit, 
286   const Standard_Real                    ParametricTolerance, 
287   const Standard_Boolean                 SameOrientation  )
288 {
289   if (Abs (FromParam1 - ToParam2) <= Abs(ParametricTolerance)) {
290     Standard_DomainError::Raise();
291   }
292   Handle(Geom_BSplineSurface) NewSurface
293     = Handle(Geom_BSplineSurface)::DownCast(S->Copy());
294
295   if (USplit) {
296     Standard_Real FirstU = Min( FromParam1, ToParam2);
297     Standard_Real LastU  = Max( FromParam1, ToParam2);
298     Standard_Real FirstV = S->VKnot(S->FirstVKnotIndex());
299     Standard_Real LastV  = S->VKnot(S->LastVKnotIndex());
300
301     NewSurface->Segment(FirstU, LastU, FirstV, LastV);
302
303     if (S->IsUPeriodic()) { 
304       if (!SameOrientation)  NewSurface->UReverse(); 
305     }
306     else { 
307       if (FromParam1 > ToParam2)    NewSurface->UReverse(); 
308     }
309
310   }
311   else {
312     Standard_Real FirstU = S->UKnot(S->FirstUKnotIndex());
313     Standard_Real LastU  = S->UKnot(S->LastUKnotIndex());
314     Standard_Real FirstV = Min( FromParam1, ToParam2);
315     Standard_Real LastV  = Max( FromParam1, ToParam2);
316
317     NewSurface->Segment(FirstU, LastU, FirstV, LastV);
318
319     if (S->IsUPeriodic()) { 
320       if (!SameOrientation)  NewSurface->UReverse(); 
321     }
322     else { 
323       if (FromParam1 > ToParam2)    NewSurface->UReverse(); 
324     }
325
326   }
327   return NewSurface;
328 }
329
330
331 //=======================================================================
332 //function : SurfaceToBSplineSurface
333 //purpose  : 
334 //=======================================================================
335
336 Handle(Geom_BSplineSurface) GeomConvert::SurfaceToBSplineSurface
337   (const Handle(Geom_Surface)& Sr) 
338 {
339   Standard_Real U1, U2, V1, V2;
340   Sr->Bounds (U1, U2, V1, V2);
341   Standard_Real UFirst = Min (U1, U2);
342   Standard_Real ULast  = Max (U1, U2);
343   Standard_Real VFirst = Min (V1, V2);
344   Standard_Real VLast  = Max (V1, V2);
345
346   //If the surface Sr is infinite stop the computation
347   if (Precision::IsNegativeInfinite(UFirst) || 
348     Precision::IsPositiveInfinite(ULast)  || 
349     Precision::IsNegativeInfinite(VFirst) || 
350     Precision::IsPositiveInfinite(VLast) )   {
351       Standard_DomainError::Raise("");
352   }
353
354   Handle(Geom_BSplineSurface) TheSurface;
355   Handle(Geom_Surface) S; 
356   Handle(Geom_OffsetSurface) OffsetSur;
357   if (Sr->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
358     OffsetSur = Handle(Geom_OffsetSurface)::DownCast (Sr);
359     S = OffsetSur->Surface();
360     if (!S.IsNull()) { // Convert the equivalent surface.
361       return SurfaceToBSplineSurface(S);
362     }
363   }
364   S = Sr;
365
366   if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
367     Handle(Geom_RectangularTrimmedSurface) Strim = 
368       Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
369
370     Handle(Geom_Surface) Surf = Strim->BasisSurface();
371     UFirst = U1;  ULast = U2; VFirst = V1; VLast = V2;
372     if (Surf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
373       Handle(Geom_OffsetSurface) OffsetSur = 
374         Handle(Geom_OffsetSurface)::DownCast(Surf);
375
376       S = OffsetSur->Surface();
377       if (!S.IsNull()) {
378         Surf = S;
379       } 
380       else S = Surf;
381     }
382
383     if  (Surf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
384       Handle(Geom_RectangularTrimmedSurface) Strim = new 
385         (Geom_RectangularTrimmedSurface) (Surf, 
386         UFirst, ULast, 
387         VFirst, VLast);
388       return SurfaceToBSplineSurface(Strim);
389     }
390
391     if (Surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
392       TColgp_Array2OfPnt Poles (1, 2, 1, 2);
393       Poles (1, 1) = Strim->Value (U1, V1);
394       Poles (1, 2) = Strim->Value (U1, V2);
395       Poles (2, 1) = Strim->Value (U2, V1);
396       Poles (2, 2) = Strim->Value (U2, V2);
397       TColStd_Array1OfReal UKnots (1, 2);
398       TColStd_Array1OfReal VKnots (1, 2);
399       TColStd_Array1OfInteger UMults (1, 2);
400       TColStd_Array1OfInteger VMults (1, 2);
401       UKnots (1) = U1;
402       UKnots (2) = U2;
403       VKnots (1) = V1;
404       VKnots (2) = V2;
405       UMults (1) = 2;
406       UMults (2) = 2;
407       VMults (1) = 2;
408       VMults (2) = 2;
409       Standard_Integer UDegree = 1;
410       Standard_Integer VDegree = 1;
411       TheSurface = new Geom_BSplineSurface (Poles, UKnots, VKnots, UMults,
412         VMults, UDegree, VDegree);
413     }
414     else if (Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
415       Handle(Geom_CylindricalSurface) TheElSurf= 
416         Handle(Geom_CylindricalSurface)::DownCast(Surf);
417
418       gp_Cylinder Cyl = TheElSurf->Cylinder();
419       if (Strim->IsUClosed()) {
420         Convert_CylinderToBSplineSurface Convert (Cyl, VFirst, VLast);
421         TheSurface = BSplineSurfaceBuilder (Convert);
422       }
423       else {
424         Convert_CylinderToBSplineSurface 
425           Conv (Cyl, UFirst, ULast, VFirst, VLast);
426         TheSurface = BSplineSurfaceBuilder (Conv);
427       }
428     }
429
430
431     else if (Surf->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) {
432       Handle(Geom_ConicalSurface) TheElSurf = 
433         Handle(Geom_ConicalSurface)::DownCast(Surf);
434       gp_Cone Co = TheElSurf->Cone();
435       if (Strim->IsUClosed()) {
436         Convert_ConeToBSplineSurface Convert (Co, VFirst, VLast);
437         TheSurface = BSplineSurfaceBuilder (Convert);
438       }
439       else {
440         Convert_ConeToBSplineSurface 
441           Convert (Co, UFirst, ULast, VFirst, VLast);
442         TheSurface = BSplineSurfaceBuilder (Convert);
443       }
444     }
445
446
447     else if (Surf->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) {
448       Handle(Geom_SphericalSurface) TheElSurf = 
449         Handle(Geom_SphericalSurface)::DownCast(Surf);
450       gp_Sphere Sph = TheElSurf->Sphere();
451       //OCC217
452       if (Strim->IsUClosed()) {
453         //if (Strim->IsVClosed()) {
454         //Convert_SphereToBSplineSurface Convert (Sph, UFirst, ULast);
455         Convert_SphereToBSplineSurface Convert (Sph, VFirst, VLast, Standard_False);
456         TheSurface = BSplineSurfaceBuilder (Convert);
457       }
458       else {
459         Convert_SphereToBSplineSurface 
460           Convert (Sph, UFirst, ULast, VFirst, VLast);
461         TheSurface = BSplineSurfaceBuilder (Convert);
462       }
463     }
464
465
466     else if (Surf->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
467       Handle(Geom_ToroidalSurface) TheElSurf = 
468         Handle(Geom_ToroidalSurface)::DownCast(Surf);
469
470       gp_Torus Tr = TheElSurf->Torus();
471       if (Strim->IsUClosed()) { 
472         Convert_TorusToBSplineSurface Convert (Tr, VFirst, VLast, 
473           Standard_False);
474         TheSurface = BSplineSurfaceBuilder (Convert);
475       }
476       else if (Strim->IsVClosed()) {
477         Convert_TorusToBSplineSurface Convert (Tr, UFirst, ULast);
478         TheSurface = BSplineSurfaceBuilder (Convert);
479       }
480       else {
481         Convert_TorusToBSplineSurface 
482           Convert (Tr, UFirst, ULast, VFirst, VLast);
483         TheSurface = BSplineSurfaceBuilder (Convert);
484       }
485     }
486
487
488     else if (Surf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
489       Handle(Geom_SurfaceOfRevolution) Revol = 
490         Handle(Geom_SurfaceOfRevolution)::DownCast(Surf);
491
492       Handle(Geom_Curve) Meridian = Revol->BasisCurve();
493       Handle(Geom_BSplineCurve) C; 
494       if (Strim->IsVClosed()) {
495         C =  GeomConvert::CurveToBSplineCurve (Meridian);
496       }
497       else {
498         Handle(Geom_TrimmedCurve) CT = 
499           new Geom_TrimmedCurve( Meridian, VFirst, VLast);
500         C =  GeomConvert::CurveToBSplineCurve (CT);
501       }
502       Standard_Integer NbUPoles, NbUKnots;
503       Standard_Integer NbVPoles, NbVKnots;
504       Standard_Boolean periodic = Standard_False;
505
506       // Poles of meridian = Vpoles
507       NbVPoles = C->NbPoles();
508       TColgp_Array1OfPnt Poles(1, NbVPoles);
509       C->Poles(Poles);
510       TColStd_Array1OfReal Weights( 1, NbVPoles);
511       Weights.Init(1.);
512       if ( C->IsRational()) C->Weights(Weights);
513
514       Standard_Integer nbUSpans;
515       Standard_Real AlfaU;
516       if (Strim->IsUPeriodic()) {
517         NbUKnots = 4;
518         nbUSpans = 3;
519         AlfaU    = M_PI / 3.;
520         NbUPoles = 6;
521         periodic = Standard_True;
522       }
523       else {
524         // Nombre de spans : ouverture maximale = 150 degres ( = PI / 1.2 rds)
525         nbUSpans = 
526           (Standard_Integer)IntegerPart( 1.2 * (ULast - UFirst) / M_PI) + 1;
527         AlfaU = (ULast - UFirst) / ( nbUSpans * 2);
528         NbUPoles = 2 * nbUSpans + 1;
529         NbUKnots = nbUSpans + 1;
530       }
531       // Compute Knots and Mults
532       TColStd_Array1OfReal    UKnots(1, NbUKnots);
533       TColStd_Array1OfInteger UMults( 1, NbUKnots);
534       Standard_Integer i,j;
535       for ( i = 1; i <= NbUKnots; i++) {
536         UKnots(i) = UFirst + (i-1) * 2 * AlfaU;
537         UMults(i) = 2;
538       }
539       if (!periodic) {
540         UMults(1)++; UMults(NbUKnots)++;
541       }
542       NbVKnots = C->NbKnots();
543       TColStd_Array1OfReal    VKnots(1, NbVKnots);
544       TColStd_Array1OfInteger VMults(1, NbVKnots);
545       C->Knots(VKnots);
546       C->Multiplicities(VMults);
547
548       // Compute the poles.
549       TColgp_Array2OfPnt   NewPoles  ( 1, NbUPoles, 1, NbVPoles);
550       TColStd_Array2OfReal NewWeights( 1, NbUPoles, 1, NbVPoles);
551       gp_Trsf Trsf;
552
553       for ( i = 1; i<= NbUPoles; i+=2) {
554         Trsf.SetRotation( Revol->Axis(), UFirst + (i-1)*AlfaU);
555         for ( j = 1; j <= NbVPoles; j++) {
556           NewPoles(i,j) = Poles(j).Transformed(Trsf);
557           NewWeights(i,j) = Weights(j);
558         }
559       }
560       gp_GTrsf Aff;
561       Aff.SetAffinity( Revol->Axis(), 1/Cos(AlfaU));
562       gp_XYZ coord;
563       for ( j= 1; j<= NbVPoles; j++) {
564         coord = Poles(j).XYZ();
565         Aff.Transforms(coord);
566         Poles(j).SetXYZ(coord);
567       }
568       for ( i = 2; i<= NbUPoles; i+=2) {
569         Trsf.SetRotation( Revol->Axis(), UFirst + (i-1)*AlfaU);
570         for ( j = 1; j <= NbVPoles; j++) {
571           NewPoles(i,j) = Poles(j).Transformed(Trsf);
572           NewWeights(i,j) = Weights(j) * Cos(AlfaU);
573         }
574       }
575
576       TheSurface = new Geom_BSplineSurface(NewPoles, NewWeights, 
577         UKnots, VKnots, 
578         UMults, VMults,
579         2 , C->Degree(),
580         periodic, C->IsPeriodic());
581
582
583     }
584
585
586     else if (Surf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
587       Handle(Geom_SurfaceOfLinearExtrusion) Extru = 
588         Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Surf);
589
590       Handle(Geom_Curve) Meridian = Extru->BasisCurve();
591       Handle(Geom_BSplineCurve) C; 
592       if (Strim->IsUClosed()) {
593         C =  GeomConvert::CurveToBSplineCurve (Meridian);
594       }
595       else {
596         Handle(Geom_TrimmedCurve) CT = 
597           new Geom_TrimmedCurve( Meridian, UFirst, ULast);
598         C =  GeomConvert::CurveToBSplineCurve (CT);
599       }
600       TColgp_Array2OfPnt      Poles  ( 1, C->NbPoles(), 1, 2);
601       TColStd_Array2OfReal    Weights( 1, C->NbPoles(), 1, 2);
602       TColStd_Array1OfReal    UKnots ( 1, C->NbKnots());
603       C->Knots(UKnots);
604       TColStd_Array1OfInteger UMults ( 1, C->NbKnots());
605       C->Multiplicities(UMults);
606       TColStd_Array1OfReal    VKnots ( 1, 2);
607       VKnots(1) = VFirst; 
608       VKnots(2) = VLast;
609       TColStd_Array1OfInteger VMults ( 1, 2);
610       VMults.Init(2);
611
612       gp_Vec D( Extru->Direction());
613       gp_Vec DV1 = VFirst * D;
614       gp_Vec DV2 = VLast  * D;
615       for (Standard_Integer i = 1; i <= C->NbPoles(); i++) {
616         Poles(i,1) = C->Pole(i).Translated(DV1);
617         Poles(i,2) = C->Pole(i).Translated(DV2);
618         Weights(i,1) = Weights(i,2) = C->Weight(i);
619       } 
620       TheSurface = new Geom_BSplineSurface(Poles, Weights, UKnots, VKnots, 
621         UMults, VMults,
622         C->Degree(), 1,
623         C->IsPeriodic(), Standard_False);
624     }
625
626
627     else if (Surf->IsKind(STANDARD_TYPE(Geom_BezierSurface))) {
628
629       Handle(Geom_BezierSurface) SBez = 
630         Handle(Geom_BezierSurface)::DownCast(Surf->Copy());
631
632       SBez->Segment (U1, U2, V1, V2);
633       Standard_Integer NbUPoles = SBez->NbUPoles();
634       Standard_Integer NbVPoles = SBez->NbVPoles();
635       Standard_Integer UDegree  = SBez->UDegree();
636       Standard_Integer VDegree  = SBez->VDegree();
637       TColgp_Array2OfPnt      Poles    (1, NbUPoles, 1, NbVPoles);
638       TColStd_Array1OfReal    UKnots   (1, 2);
639       TColStd_Array1OfInteger UMults   (1, 2);
640       TColStd_Array1OfReal    VKnots   (1, 2);
641       TColStd_Array1OfInteger VMults   (1, 2);
642       UKnots (1) = 0.0;
643       UKnots (2) = 1.0;
644       UMults (1) = UDegree + 1;
645       UMults (2) = UDegree + 1;
646       VKnots (1) = 0.0;
647       VKnots (2) = 1.0;
648       VMults (1) = VDegree + 1;
649       VMults (2) = VDegree + 1;
650       SBez->Poles (Poles);
651       if (SBez->IsURational() || SBez->IsVRational()) {    
652         TColStd_Array2OfReal Weights (1, NbUPoles, 1, NbVPoles);
653         SBez->Weights (Weights);
654         TheSurface = new Geom_BSplineSurface (Poles, Weights, UKnots, VKnots,
655           UMults, VMults,
656           UDegree, VDegree);
657       }
658       else {
659         TheSurface = new Geom_BSplineSurface (Poles, UKnots, VKnots, 
660           UMults, VMults,
661           UDegree, VDegree);
662       }
663     }
664
665     else if (Surf->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
666       Handle(Geom_BSplineSurface) BS = 
667         Handle(Geom_BSplineSurface)::DownCast(Surf->Copy());
668       Standard_Real umin, umax, vmin, vmax;
669       BS->Bounds(umin, umax, vmin, vmax);
670       if (!BS->IsUPeriodic()) {
671         if (U1 < umin)
672           U1 = umin;
673         if (U2 > umax) 
674           U2 = umax;
675       }
676
677       if (!BS->IsVPeriodic()) {
678         if (V1 < vmin)
679           V1 = vmin;
680         if (V2 > vmax)
681           V2 = vmax;
682       }
683       if (BS->IsUPeriodic() || BS->IsVPeriodic())
684         BS->CheckAndSegment (U1, U2, V1, V2);
685       else
686         BS->Segment (U1, U2, V1, V2);
687       TheSurface = BS;
688     }
689
690     else {
691       Standard_Real Tol3d=1.e-4;
692       Standard_Integer MaxDegree =14, MaxSeg;
693       GeomAbs_Shape cont;
694       GeomAdaptor_Surface AS(Sr);
695       if (AS.NbUIntervals(GeomAbs_C2) > 1 || AS.NbVIntervals(GeomAbs_C2) > 1 ) 
696         cont=GeomAbs_C1;
697       else
698         cont=GeomAbs_C2;
699       MaxSeg = 4*(AS.NbUIntervals(GeomAbs_CN)+1)*(AS.NbVIntervals(GeomAbs_CN)+1); 
700       GeomConvert_ApproxSurface BSpS(Sr, Tol3d, cont, cont,
701         MaxDegree, MaxDegree, MaxSeg, 1);
702       TheSurface = BSpS.Surface();
703     }
704   } // Fin du cas Rectangular::TrimmedSurface
705
706   else { 
707
708     if (S->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) {
709       Handle(Geom_SphericalSurface) TheElSurf = 
710         Handle(Geom_SphericalSurface)::DownCast(S);
711
712       gp_Sphere Sph = TheElSurf->Sphere();
713       Convert_SphereToBSplineSurface Convert(Sph);
714       TheSurface = BSplineSurfaceBuilder(Convert);
715     }
716
717
718     else if (S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
719       Handle(Geom_ToroidalSurface) TheElSurf = 
720         Handle(Geom_ToroidalSurface)::DownCast(S);
721
722       gp_Torus Tr = TheElSurf->Torus();
723       Convert_TorusToBSplineSurface Convert(Tr);
724       TheSurface = BSplineSurfaceBuilder(Convert);
725     }
726
727
728     else if (S->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
729
730       Handle(Geom_SurfaceOfRevolution) Revol = 
731         Handle(Geom_SurfaceOfRevolution)::DownCast(S);
732
733       Handle(Geom_Curve) Meridian = Revol->BasisCurve();
734       Handle(Geom_BSplineCurve) C 
735         = GeomConvert::CurveToBSplineCurve (Meridian);
736
737       Standard_Integer NbUPoles, NbUKnots;
738       Standard_Integer NbVPoles, NbVKnots;
739       Standard_Boolean periodic = Standard_True;
740
741       // Poles of meridian = Vpoles
742       NbVPoles = C->NbPoles();
743       TColgp_Array1OfPnt Poles(1, NbVPoles);
744       C->Poles(Poles);
745       TColStd_Array1OfReal Weights( 1, NbVPoles);
746       Weights.Init(1.);
747       if ( C->IsRational()) C->Weights(Weights);
748
749       Standard_Real AlfaU;
750       NbUKnots = 4;
751       AlfaU    = M_PI / 3.;
752       NbUPoles = 6;
753
754       // Compute Knots and Mults
755       TColStd_Array1OfReal    UKnots(1, NbUKnots);
756       TColStd_Array1OfInteger UMults( 1, NbUKnots);
757       Standard_Integer i,j;
758       for ( i = 1; i <= NbUKnots; i++) {
759         UKnots(i) = UFirst + (i-1) * 2 * AlfaU;
760         UMults(i) = 2;
761       }
762       NbVKnots = C->NbKnots();
763       TColStd_Array1OfReal    VKnots(1, NbVKnots);
764       TColStd_Array1OfInteger VMults(1, NbVKnots);
765       C->Knots(VKnots);
766       C->Multiplicities(VMults);
767
768       // Compute the poles.
769       TColgp_Array2OfPnt   NewPoles  ( 1, NbUPoles, 1, NbVPoles);
770       TColStd_Array2OfReal NewWeights( 1, NbUPoles, 1, NbVPoles);
771       gp_Trsf Trsf;
772
773       for ( i = 1; i<= NbUPoles; i+=2) {
774         Trsf.SetRotation( Revol->Axis(), UFirst + (i-1)*AlfaU);
775         for ( j = 1; j <= NbVPoles; j++) {
776           NewPoles(i,j) = Poles(j).Transformed(Trsf);
777           NewWeights(i,j) = Weights(j);
778         }
779       }
780       gp_GTrsf Aff;
781       Aff.SetAffinity( Revol->Axis(), 1/Cos(AlfaU));
782       gp_XYZ coord;
783       for ( j= 1; j<= NbVPoles; j++) {
784         coord = Poles(j).XYZ();
785         Aff.Transforms(coord);
786         Poles(j).SetXYZ(coord);
787       }
788       for ( i = 2; i<= NbUPoles; i+=2) {
789         Trsf.SetRotation( Revol->Axis(), UFirst + (i-1)*AlfaU);
790         for ( j = 1; j <= NbVPoles; j++) {
791           NewPoles(i,j) = Poles(j).Transformed(Trsf);
792           NewWeights(i,j) = Weights(j) * Cos(AlfaU);
793         }
794       }
795
796       TheSurface = new Geom_BSplineSurface(NewPoles, NewWeights, 
797         UKnots, VKnots, 
798         UMults, VMults,
799         2 , C->Degree(),
800         periodic, C->IsPeriodic());
801     }
802
803
804     else if (S->IsKind(STANDARD_TYPE(Geom_BezierSurface))) {
805
806       Handle(Geom_BezierSurface) SBez = 
807         Handle(Geom_BezierSurface)::DownCast(S);
808
809       Standard_Integer NbUPoles = SBez->NbUPoles();
810       Standard_Integer NbVPoles = SBez->NbVPoles();
811       Standard_Integer UDegree  = SBez->UDegree();
812       Standard_Integer VDegree  = SBez->VDegree();
813       TColgp_Array2OfPnt      Poles (1, NbUPoles, 1, NbVPoles);
814       TColStd_Array1OfReal    UKnots(1, 2);
815       TColStd_Array1OfInteger UMults(1, 2);
816       TColStd_Array1OfReal    VKnots(1, 2);
817       TColStd_Array1OfInteger VMults(1, 2);
818       UKnots (1) = 0.0;
819       UKnots (2) = 1.0;
820       UMults (1) = UDegree + 1;
821       UMults (2) = UDegree + 1;
822       VKnots (1) = 0.0;
823       VKnots (2) = 1.0;
824       VMults (1) = VDegree + 1;
825       VMults (2) = VDegree + 1;
826       SBez->Poles (Poles);
827       if (SBez->IsURational() || SBez->IsVRational()) {    
828         TColStd_Array2OfReal    Weights (1, NbUPoles, 1, NbVPoles);
829         SBez->Weights (Weights);
830         TheSurface = new Geom_BSplineSurface (Poles, Weights, UKnots, VKnots,
831           UMults, VMults,
832           UDegree, VDegree);
833       }
834       else {
835         TheSurface = new Geom_BSplineSurface (Poles, UKnots, VKnots, 
836           UMults, VMults,
837           UDegree, VDegree);
838       }
839     }
840
841     else if (S->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
842       TheSurface = Handle(Geom_BSplineSurface)::DownCast(S->Copy()); //Just a copy
843     }
844
845     else { // In other cases => Approx
846       Standard_Real Tol3d=1.e-4;
847       Standard_Integer MaxDegree = 14, MaxSeg;
848       GeomAbs_Shape ucont = GeomAbs_C0, vcont = GeomAbs_C0;
849       GeomAdaptor_Surface AS(Sr);
850       //
851       if (Sr->IsCNu(2)) 
852       {
853         ucont=GeomAbs_C2;
854       }
855       else if(Sr->IsCNu(1)) 
856       {
857         ucont=GeomAbs_C1;
858       }
859       //
860       if (Sr->IsCNv(2)) 
861       {
862         vcont=GeomAbs_C2;
863       }
864       else if(Sr->IsCNv(1)) 
865       {
866         vcont=GeomAbs_C1;
867       }
868       //
869       MaxSeg = 4*(AS.NbUIntervals(GeomAbs_CN)+1)*(AS.NbVIntervals(GeomAbs_CN)+1);      
870       GeomConvert_ApproxSurface BSpS(Sr, Tol3d, ucont, vcont,
871                                      MaxDegree, MaxDegree, MaxSeg, 1);
872       TheSurface = BSpS.Surface();
873     }
874   } // Fin du cas direct
875   return TheSurface;
876 }
877
878
879