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