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