601f041c1bf8c079c4bf4351d4c9efef788fb7a0
[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       if (BS->IsUPeriodic() || BS->IsVPeriodic())
706         BS->CheckAndSegment (U1, U2, V1, V2);
707       else
708         BS->Segment (U1, U2, V1, V2);
709       TheSurface = BS;
710     }
711
712     else {
713       Standard_Real Tol3d=1.e-4;
714       Standard_Integer MaxDegree =14, MaxSeg;
715       GeomAbs_Shape cont;
716       GeomAdaptor_Surface AS(Sr);
717       if (AS.NbUIntervals(GeomAbs_C2) > 1 || AS.NbVIntervals(GeomAbs_C2) > 1 ) 
718         cont=GeomAbs_C1;
719       else
720         cont=GeomAbs_C2;
721       MaxSeg = 4*(AS.NbUIntervals(GeomAbs_CN)+1)*(AS.NbVIntervals(GeomAbs_CN)+1); 
722       GeomConvert_ApproxSurface BSpS(Sr, Tol3d, cont, cont,
723         MaxDegree, MaxDegree, MaxSeg, 1);
724       TheSurface = BSpS.Surface();
725     }
726   } // Fin du cas Rectangular::TrimmedSurface
727
728   else { 
729
730     if (S->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) {
731       Handle(Geom_SphericalSurface) TheElSurf = 
732         Handle(Geom_SphericalSurface)::DownCast(S);
733
734       gp_Sphere Sph = TheElSurf->Sphere();
735       Convert_SphereToBSplineSurface Convert(Sph);
736       TheSurface = BSplineSurfaceBuilder(Convert);
737     }
738
739
740     else if (S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
741       Handle(Geom_ToroidalSurface) TheElSurf = 
742         Handle(Geom_ToroidalSurface)::DownCast(S);
743
744       gp_Torus Tr = TheElSurf->Torus();
745       Convert_TorusToBSplineSurface Convert(Tr);
746       TheSurface = BSplineSurfaceBuilder(Convert);
747     }
748
749
750     else if (S->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
751
752       Handle(Geom_SurfaceOfRevolution) Revol = 
753         Handle(Geom_SurfaceOfRevolution)::DownCast(S);
754
755       Handle(Geom_Curve) Meridian = Revol->BasisCurve();
756       Handle(Geom_BSplineCurve) C 
757         = GeomConvert::CurveToBSplineCurve (Meridian);
758
759       Standard_Integer NbUPoles, NbUKnots;
760       Standard_Integer NbVPoles, NbVKnots;
761       Standard_Boolean periodic = Standard_True;
762
763       // Poles of meridian = Vpoles
764       NbVPoles = C->NbPoles();
765       TColgp_Array1OfPnt Poles(1, NbVPoles);
766       C->Poles(Poles);
767       TColStd_Array1OfReal Weights( 1, NbVPoles);
768       Weights.Init(1.);
769       if ( C->IsRational()) C->Weights(Weights);
770
771       Standard_Real AlfaU;
772       NbUKnots = 4;
773       AlfaU    = M_PI / 3.;
774       NbUPoles = 6;
775
776       // Compute Knots and Mults
777       TColStd_Array1OfReal    UKnots(1, NbUKnots);
778       TColStd_Array1OfInteger UMults( 1, NbUKnots);
779       Standard_Integer i,j;
780       for ( i = 1; i <= NbUKnots; i++) {
781         UKnots(i) = UFirst + (i-1) * 2 * AlfaU;
782         UMults(i) = 2;
783       }
784       NbVKnots = C->NbKnots();
785       TColStd_Array1OfReal    VKnots(1, NbVKnots);
786       TColStd_Array1OfInteger VMults(1, NbVKnots);
787       C->Knots(VKnots);
788       C->Multiplicities(VMults);
789
790       // Compute the poles.
791       TColgp_Array2OfPnt   NewPoles  ( 1, NbUPoles, 1, NbVPoles);
792       TColStd_Array2OfReal NewWeights( 1, NbUPoles, 1, NbVPoles);
793       gp_Trsf Trsf;
794
795       for ( i = 1; i<= NbUPoles; i+=2) {
796         Trsf.SetRotation( Revol->Axis(), UFirst + (i-1)*AlfaU);
797         for ( j = 1; j <= NbVPoles; j++) {
798           NewPoles(i,j) = Poles(j).Transformed(Trsf);
799           NewWeights(i,j) = Weights(j);
800         }
801       }
802       gp_GTrsf Aff;
803       Aff.SetAffinity( Revol->Axis(), 1/Cos(AlfaU));
804       gp_XYZ coord;
805       for ( j= 1; j<= NbVPoles; j++) {
806         coord = Poles(j).XYZ();
807         Aff.Transforms(coord);
808         Poles(j).SetXYZ(coord);
809       }
810       for ( i = 2; i<= NbUPoles; i+=2) {
811         Trsf.SetRotation( Revol->Axis(), UFirst + (i-1)*AlfaU);
812         for ( j = 1; j <= NbVPoles; j++) {
813           NewPoles(i,j) = Poles(j).Transformed(Trsf);
814           NewWeights(i,j) = Weights(j) * Cos(AlfaU);
815         }
816       }
817
818       TheSurface = new Geom_BSplineSurface(NewPoles, NewWeights, 
819         UKnots, VKnots, 
820         UMults, VMults,
821         2 , C->Degree(),
822         periodic, C->IsPeriodic());
823     }
824
825
826     else if (S->IsKind(STANDARD_TYPE(Geom_BezierSurface))) {
827
828       Handle(Geom_BezierSurface) SBez = 
829         Handle(Geom_BezierSurface)::DownCast(S);
830
831       Standard_Integer NbUPoles = SBez->NbUPoles();
832       Standard_Integer NbVPoles = SBez->NbVPoles();
833       Standard_Integer UDegree  = SBez->UDegree();
834       Standard_Integer VDegree  = SBez->VDegree();
835       TColgp_Array2OfPnt      Poles (1, NbUPoles, 1, NbVPoles);
836       TColStd_Array1OfReal    UKnots(1, 2);
837       TColStd_Array1OfInteger UMults(1, 2);
838       TColStd_Array1OfReal    VKnots(1, 2);
839       TColStd_Array1OfInteger VMults(1, 2);
840       UKnots (1) = 0.0;
841       UKnots (2) = 1.0;
842       UMults (1) = UDegree + 1;
843       UMults (2) = UDegree + 1;
844       VKnots (1) = 0.0;
845       VKnots (2) = 1.0;
846       VMults (1) = VDegree + 1;
847       VMults (2) = VDegree + 1;
848       SBez->Poles (Poles);
849       if (SBez->IsURational() || SBez->IsVRational()) {    
850         TColStd_Array2OfReal    Weights (1, NbUPoles, 1, NbVPoles);
851         SBez->Weights (Weights);
852         TheSurface = new Geom_BSplineSurface (Poles, Weights, UKnots, VKnots,
853           UMults, VMults,
854           UDegree, VDegree);
855       }
856       else {
857         TheSurface = new Geom_BSplineSurface (Poles, UKnots, VKnots, 
858           UMults, VMults,
859           UDegree, VDegree);
860       }
861     }
862
863     else if (S->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
864       TheSurface = Handle(Geom_BSplineSurface)::DownCast(S->Copy()); //Just a copy
865     }
866
867     else { // In other cases => Approx
868       Standard_Real Tol3d=1.e-4;
869       Standard_Integer MaxDegree = 14, MaxSeg;
870       GeomAbs_Shape ucont = GeomAbs_C0, vcont = GeomAbs_C0;
871       GeomAdaptor_Surface AS(Sr);
872       //
873       if (Sr->IsCNu(2)) 
874       {
875         ucont=GeomAbs_C2;
876       }
877       else if(Sr->IsCNu(1)) 
878       {
879         ucont=GeomAbs_C1;
880       }
881       //
882       if (Sr->IsCNv(2)) 
883       {
884         vcont=GeomAbs_C2;
885       }
886       else if(Sr->IsCNv(1)) 
887       {
888         vcont=GeomAbs_C1;
889       }
890       //
891       MaxSeg = 4*(AS.NbUIntervals(GeomAbs_CN)+1)*(AS.NbVIntervals(GeomAbs_CN)+1);      
892       GeomConvert_ApproxSurface BSpS(Sr, Tol3d, ucont, vcont,
893                                      MaxDegree, MaxDegree, MaxSeg, 1);
894       TheSurface = BSpS.Surface();
895     }
896   } // Fin du cas direct
897   return TheSurface;
898 }
899
900
901