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