0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / ShapeCustom / ShapeCustom_BSplineRestriction.cxx
1 // Created on: 1999-06-18
2 // Created by: Galina Koulikova
3 // Copyright (c) 1999-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_GCurve.hxx>
20 #include <BRep_TEdge.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepTools.hxx>
23 #include <BRepTools_Modifier.hxx>
24 #include <Geom2d_BezierCurve.hxx>
25 #include <Geom2d_Conic.hxx>
26 #include <Geom2d_Curve.hxx>
27 #include <Geom2d_Line.hxx>
28 #include <Geom2d_OffsetCurve.hxx>
29 #include <Geom2d_TrimmedCurve.hxx>
30 #include <Geom2dConvert.hxx>
31 #include <Geom2dConvert_ApproxCurve.hxx>
32 #include <Geom_BezierCurve.hxx>
33 #include <Geom_BezierSurface.hxx>
34 #include <Geom_Conic.hxx>
35 #include <Geom_ConicalSurface.hxx>
36 #include <Geom_Curve.hxx>
37 #include <Geom_CylindricalSurface.hxx>
38 #include <Geom_Line.hxx>
39 #include <Geom_OffsetCurve.hxx>
40 #include <Geom_OffsetSurface.hxx>
41 #include <Geom_Plane.hxx>
42 #include <Geom_RectangularTrimmedSurface.hxx>
43 #include <Geom_SphericalSurface.hxx>
44 #include <Geom_Surface.hxx>
45 #include <Geom_SurfaceOfLinearExtrusion.hxx>
46 #include <Geom_SurfaceOfRevolution.hxx>
47 #include <Geom_SweptSurface.hxx>
48 #include <Geom_ToroidalSurface.hxx>
49 #include <Geom_TrimmedCurve.hxx>
50 #include <GeomAdaptor_Surface.hxx>
51 #include <GeomConvert.hxx>
52 #include <GeomConvert_ApproxCurve.hxx>
53 #include <GeomConvert_ApproxSurface.hxx>
54 #include <gp_Pnt.hxx>
55 #include <Message_Msg.hxx>
56 #include <Precision.hxx>
57 #include <ShapeAnalysis_Curve.hxx>
58 #include <ShapeConstruct.hxx>
59 #include <ShapeCustom_BSplineRestriction.hxx>
60 #include <ShapeCustom_RestrictionParameters.hxx>
61 #include <Standard_ErrorHandler.hxx>
62 #include <Standard_Failure.hxx>
63 #include <Standard_Type.hxx>
64 #include <TColgp_Array1OfPnt.hxx>
65 #include <TColgp_Array2OfPnt.hxx>
66 #include <TColStd_Array1OfInteger.hxx>
67 #include <TColStd_Array1OfReal.hxx>
68 #include <TColStd_Array2OfReal.hxx>
69 #include <TopLoc_Location.hxx>
70 #include <TopoDS_Edge.hxx>
71 #include <TopoDS_Face.hxx>
72 #include <TopoDS_Vertex.hxx>
73
74 IMPLEMENT_STANDARD_RTTIEXT(ShapeCustom_BSplineRestriction,ShapeCustom_Modification)
75
76 static GeomAbs_Shape IntegerToGeomAbsShape(const Standard_Integer i)
77 {
78   GeomAbs_Shape result = GeomAbs_C0;
79   switch (i) {
80     case 0: result = GeomAbs_C0; break;
81     case 1: result = GeomAbs_C1; break;
82     case 2: result = GeomAbs_C2; break;
83     case 3: result = GeomAbs_C3; break;
84     default : result = GeomAbs_CN; break;
85   }
86   return result;
87 }
88
89 static Standard_Integer ContToInteger( const GeomAbs_Shape Cont)
90 {
91   Standard_Integer result =0;
92   switch(Cont) {
93     case GeomAbs_C0:
94     case GeomAbs_G1: result = 0; break;
95     case GeomAbs_C1:
96     case GeomAbs_G2: result = 1; break;
97     case GeomAbs_C2: result = 2; break;  
98     case GeomAbs_C3: result = 3; break;
99     default : result = 4; break;
100   }
101   return result;
102 }
103
104 static Standard_Boolean IsConvertCurve3d(const Handle(Geom_Curve)& aCurve,
105                                          Standard_Integer Degree,
106                                          Standard_Integer NbSeg,
107                                          Standard_Boolean myRational,
108                                          const Handle(ShapeCustom_RestrictionParameters)& aParameters)
109 {
110   if(aCurve.IsNull()) return Standard_False;
111   if(aParameters->ConvertCurve3d()) return Standard_True;
112   if (aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
113     Handle(Geom_TrimmedCurve) tmp = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
114     Handle(Geom_Curve) BasCurve = tmp->BasisCurve();
115     return IsConvertCurve3d(BasCurve,Degree,NbSeg,myRational,aParameters);
116   }
117
118   if (aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
119     if(aParameters->ConvertOffsetCurv3d()) return Standard_True;
120     Handle(Geom_OffsetCurve) tmp = Handle(Geom_OffsetCurve)::DownCast (aCurve);
121     Handle(Geom_Curve) BasCurve = tmp->BasisCurve();
122     return IsConvertCurve3d(BasCurve,Degree,NbSeg,myRational,aParameters); 
123   }
124   if (aCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
125     Handle(Geom_BSplineCurve) BsC = Handle(Geom_BSplineCurve)::DownCast(aCurve);
126     if( BsC->Degree() > Degree || ((BsC->NbKnots() - 1) >= NbSeg))
127       return Standard_True;
128     if(myRational && BsC->IsRational())
129       return Standard_True;
130     else return Standard_False;
131   }
132   if (aCurve->IsKind(STANDARD_TYPE(Geom_BezierCurve)) && 
133     (Handle(Geom_BezierCurve)::DownCast(aCurve)->Degree() > Degree ||
134     (myRational &&  Handle(Geom_BezierCurve)::DownCast(aCurve)->IsRational())))
135     return Standard_True;
136   // else return Standard_False;
137   return Standard_False;
138 }
139
140 static Standard_Boolean IsConvertSurface(const Handle(Geom_Surface)& aSurface,
141                                          const Standard_Integer Degree,
142                                          const Standard_Integer NbSeg,
143                                          const Standard_Boolean myRational,
144                                          const Handle(ShapeCustom_RestrictionParameters)& aParameters)
145 {
146   if (aSurface.IsNull()) return Standard_False;
147   if (aSurface->IsKind(STANDARD_TYPE(Geom_Plane))) {
148     return aParameters->ConvertPlane();
149   }
150   else if(aSurface->IsKind(STANDARD_TYPE(Geom_ConicalSurface)))
151     return aParameters->ConvertConicalSurf();
152   else if(aSurface->IsKind(STANDARD_TYPE(Geom_SphericalSurface)))
153     return aParameters->ConvertSphericalSurf();
154   else if(aSurface->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)))
155     return aParameters->ConvertCylindricalSurf();
156   else if(aSurface->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)))
157     return aParameters->ConvertToroidalSurf();
158
159   //else if(aSurface->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))    {
160   //  return aParameters->ConvertElementarySurf();
161   // }
162   if (aSurface->IsKind(STANDARD_TYPE(Geom_SweptSurface))) {
163     if(aSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution)) && aParameters->ConvertRevolutionSurf())
164       return Standard_True;
165     if(aSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) && aParameters->ConvertExtrusionSurf())
166       return Standard_True;   
167     Handle(Geom_SweptSurface) aSurf = Handle(Geom_SweptSurface)::DownCast(aSurface);
168     Handle(Geom_Curve) BasCurve = aSurf->BasisCurve();
169     return IsConvertCurve3d(BasCurve,Degree,NbSeg,myRational,aParameters);
170   }
171   if (aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
172     Handle(Geom_RectangularTrimmedSurface) aSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
173     Handle(Geom_Surface) theSurf = aSurf->BasisSurface();
174     return IsConvertSurface(theSurf,Degree,NbSeg,myRational,aParameters);
175   }
176   if(aSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) { 
177     if(aParameters->ConvertOffsetSurf()) return Standard_True;
178     Handle(Geom_OffsetSurface) aSurf = Handle(Geom_OffsetSurface)::DownCast(aSurface);
179     Handle(Geom_Surface) theSurf = aSurf->BasisSurface();
180     return IsConvertSurface(theSurf,Degree,NbSeg,myRational,aParameters);
181   }
182   if (aSurface->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
183
184     Handle(Geom_BSplineSurface) theSurf = Handle(Geom_BSplineSurface)::DownCast(aSurface);
185     if(theSurf->UDegree() > Degree || theSurf->VDegree() > Degree)  
186       return Standard_True;
187     if((theSurf->NbUKnots()-1) * (theSurf->NbVKnots()-1) > NbSeg)
188       return Standard_True;
189     if(myRational && (theSurf->IsURational() || theSurf->IsVRational())) 
190       return Standard_True; 
191     return Standard_False;
192   } 
193
194   if (aSurface->IsKind(STANDARD_TYPE(Geom_BezierSurface))) {
195     if(aParameters->ConvertBezierSurf())
196       return Standard_True;
197     Handle(Geom_BezierSurface) theSurf = Handle(Geom_BezierSurface)::DownCast(aSurface);
198     if(theSurf->UDegree() > Degree || theSurf->VDegree() > Degree)
199       return Standard_True;
200     if( myRational && (theSurf->IsURational() || theSurf->IsVRational()))
201       return Standard_True;
202     return Standard_False;
203   }
204   return Standard_False;
205 }
206
207 static Standard_Boolean IsConvertCurve2d(const Handle(Geom2d_Curve)& aCurve,
208                                          Standard_Integer Degree,
209                                          Standard_Integer NbSeg,
210                                          Standard_Boolean myRational,
211                                          const Handle(ShapeCustom_RestrictionParameters)& aParameters)
212 {
213   if (aCurve.IsNull()) return Standard_False;
214   if (aParameters->ConvertCurve2d()) return Standard_True;
215   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
216     Handle(Geom2d_TrimmedCurve) tmp = Handle(Geom2d_TrimmedCurve)::DownCast (aCurve);
217     Handle(Geom2d_Curve) BasCurve = tmp->BasisCurve();
218     return IsConvertCurve2d(BasCurve,Degree,NbSeg,myRational,aParameters);
219   }
220   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) {
221     if(aParameters->ConvertOffsetCurv2d()) return Standard_True;
222     Handle(Geom2d_OffsetCurve) tmp = Handle(Geom2d_OffsetCurve)::DownCast (aCurve);
223     Handle(Geom2d_Curve) BasCurve = tmp->BasisCurve();
224     return IsConvertCurve2d(BasCurve,Degree,NbSeg,myRational,aParameters);
225   }
226   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) &&
227     ((Handle(Geom2d_BSplineCurve)::DownCast(aCurve)->Degree() > Degree || 
228     ((Handle(Geom2d_BSplineCurve)::DownCast(aCurve)->NbKnots() -1) > NbSeg )) ||
229     (myRational && Handle(Geom2d_BSplineCurve)::DownCast(aCurve)->IsRational()))) 
230     return Standard_True;
231   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) && 
232     ((Handle(Geom2d_BezierCurve)::DownCast(aCurve)->Degree() > Degree) ||
233     (myRational && Handle(Geom2d_BezierCurve)::DownCast(aCurve)->IsRational())))
234     return Standard_True;
235   // else return Standard_False;
236   return Standard_False;
237 }
238
239 //=======================================================================
240 //function : ShapeCustom_BSplineRestriction
241 //purpose  : 
242 //=======================================================================
243
244 ShapeCustom_BSplineRestriction::ShapeCustom_BSplineRestriction()
245 {
246   myApproxSurfaceFlag = Standard_True;
247   myApproxCurve3dFlag = Standard_True;
248   myApproxCurve2dFlag = Standard_True; 
249   myTol3d = 0.01;
250   myTol2d = 1E-6;
251   myContinuity3d = GeomAbs_C1;
252   myContinuity2d =GeomAbs_C2 ;
253   myMaxDegree = 9;
254   myNbMaxSeg = 10000;
255   mySurfaceError = Precision::Confusion();
256   myCurve3dError = Precision::Confusion();
257   myCurve2dError = Precision::PConfusion();
258   myNbOfSpan = 0;
259   myConvert = Standard_False;
260   myDeg =Standard_True;
261   myRational = Standard_False;
262   myParameters = new ShapeCustom_RestrictionParameters;
263
264 }
265
266 ShapeCustom_BSplineRestriction::ShapeCustom_BSplineRestriction(const Standard_Boolean anApproxSurfaceFlag,
267                                                                const Standard_Boolean anApproxCurve3dFlag,
268                                                                const Standard_Boolean anApproxCurve2dFlag,
269                                                                const Standard_Real aTol3d,
270                                                                const Standard_Real aTol2d,
271                                                                const GeomAbs_Shape aContinuity3d,
272                                                                const GeomAbs_Shape aContinuity2d,
273                                                                const Standard_Integer aMaxDegree,
274                                                                const Standard_Integer aNbMaxSeg,
275                                                                const Standard_Boolean Deg,
276                                                                const Standard_Boolean Rational)
277 {
278   myApproxSurfaceFlag = anApproxSurfaceFlag;
279   myApproxCurve3dFlag = anApproxCurve3dFlag;
280   myApproxCurve2dFlag = anApproxCurve2dFlag;
281   myTol3d = aTol3d;
282   myTol2d = aTol2d;
283   myMaxDegree = aMaxDegree;
284   myContinuity3d = aContinuity3d;
285   myContinuity2d = aContinuity2d;
286   myNbMaxSeg = aNbMaxSeg;
287   mySurfaceError = Precision::Confusion();
288   myCurve3dError = Precision::Confusion();
289   myCurve2dError = Precision::PConfusion();
290   myNbOfSpan = 0;
291   myConvert = Standard_False;
292   myDeg = Deg;
293   myRational = Rational;
294   myParameters = new ShapeCustom_RestrictionParameters;
295
296 }
297
298 ShapeCustom_BSplineRestriction::ShapeCustom_BSplineRestriction(const Standard_Boolean anApproxSurfaceFlag,
299                                                                const Standard_Boolean anApproxCurve3dFlag,
300                                                                const Standard_Boolean anApproxCurve2dFlag,
301                                                                const Standard_Real aTol3d,
302                                                                const Standard_Real aTol2d,
303                                                                const GeomAbs_Shape aContinuity3d,
304                                                                const GeomAbs_Shape aContinuity2d,
305                                                                const Standard_Integer aMaxDegree,
306                                                                const Standard_Integer aNbMaxSeg,
307                                                                const Standard_Boolean Deg,
308                                                                const Standard_Boolean Rational,
309                                                                const Handle(ShapeCustom_RestrictionParameters)& aModes)
310 {
311   myApproxSurfaceFlag = anApproxSurfaceFlag;
312   myApproxCurve3dFlag = anApproxCurve3dFlag;
313   myApproxCurve2dFlag = anApproxCurve2dFlag;
314   myTol3d = aTol3d;
315   myTol2d = aTol2d;
316   myMaxDegree = aMaxDegree;
317   myContinuity3d = aContinuity3d;
318   myContinuity2d = aContinuity2d;
319   myNbMaxSeg = aNbMaxSeg;
320   mySurfaceError = Precision::Confusion();
321   myCurve3dError = Precision::Confusion();
322   myCurve2dError = Precision::PConfusion();
323   myNbOfSpan = 0;
324   myConvert = Standard_False;
325   myDeg = Deg;
326   myRational = Rational;
327   myParameters = aModes;
328
329 }
330
331 //=======================================================================
332 //function : NewSurface
333 //purpose  : 
334 //=======================================================================
335
336 Standard_Boolean ShapeCustom_BSplineRestriction::NewSurface(const TopoDS_Face& F,
337                                                             Handle(Geom_Surface)& S,
338                                                             TopLoc_Location& L,
339                                                             Standard_Real& Tol,
340                                                             Standard_Boolean& RevWires,
341                                                             Standard_Boolean& RevFace)
342 {
343   if ( ! myApproxSurfaceFlag )
344     return Standard_False;
345   RevWires = Standard_False;
346   RevFace = Standard_False;
347   myConvert = Standard_False;
348   Handle(Geom_Surface) aSurface = BRep_Tool::Surface(F,L);
349   if(aSurface.IsNull()) return Standard_False;
350   Standard_Boolean IsOf = Standard_True;
351   if(myParameters->ConvertOffsetSurf()) IsOf = Standard_False;
352   Standard_Real UF,UL,VF,VL;
353   aSurface->Bounds(UF,UL,VF,VL);
354   Standard_Real Umin, Umax, Vmin, Vmax;
355   BRepTools::UVBounds(F,Umin, Umax, Vmin, Vmax);
356   if(myParameters->SegmentSurfaceMode()) {
357     UF = Umin; UL =  Umax;
358     VF = Vmin; VL =  Vmax;
359   }
360   else {
361     if(Precision::IsInfinite(UF) || Precision::IsInfinite(UL)) {
362       UF = Umin;
363       UL = Umax;
364     }
365     if(Precision::IsInfinite(VF) || Precision::IsInfinite(VL)) {
366       VF = Vmin;
367       VL = Vmax;
368     }
369   }
370
371   Standard_Boolean IsConv = ConvertSurface(aSurface,S,UF,UL,VF,VL,IsOf);
372   Tol = Precision::Confusion();//mySurfaceError;
373
374   if ( IsConv )
375   {
376     Standard_Boolean wasBSpline = aSurface->IsKind(STANDARD_TYPE(Geom_BSplineSurface));
377     Handle(Geom_RectangularTrimmedSurface) rts = Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
378     if ( !rts.IsNull() )
379       wasBSpline = rts->BasisSurface()->IsKind(STANDARD_TYPE(Geom_BSplineSurface));
380
381     if ( wasBSpline )
382       SendMsg( F, Message_Msg("BSplineRestriction.NewSurface.MSG1"));
383     else
384       SendMsg( F, Message_Msg("BSplineRestriction.NewSurface.MSG0"));
385   }
386
387   return IsConv;
388 }
389
390 //=======================================================================
391 //function : ConvertSurface
392 //purpose  : 
393 //=======================================================================
394
395 static void ConvertExtrusion(const Handle(Geom_Curve)& C,/*const gp_Dir& direction,*/
396                              gp_Trsf& shiftF,gp_Trsf& shiftL,
397                              const Standard_Real VF,const Standard_Real VL,
398                              Handle(Geom_Surface)& bspline)
399 {
400   Handle(Geom_BSplineCurve) bspl = Handle(Geom_BSplineCurve)::DownCast(C);  
401   Standard_Integer nbPoles = bspl->NbPoles();
402   TColgp_Array1OfPnt poles(1,nbPoles);
403   TColStd_Array1OfReal weights(1,nbPoles);
404   Standard_Integer nbKnots = bspl->NbKnots();
405   TColStd_Array1OfReal knots(1,nbKnots);
406   TColStd_Array1OfInteger mults(1,nbKnots);
407
408   bspl->Poles(poles);
409   bspl->Knots(knots);
410   bspl->Multiplicities(mults);
411   bspl->Weights(weights);
412
413   TColgp_Array2OfPnt resPoles(1,nbPoles,1,2);
414   TColStd_Array2OfReal resWeigth(1,nbPoles,1,2);
415   for(Standard_Integer j = 1; j <= nbPoles; j++) {
416     resPoles(j,1) = poles(j).Transformed(shiftF);
417     resPoles(j,2) = poles(j).Transformed(shiftL);
418     resWeigth(j,1)= weights(j);
419     resWeigth(j,2)= weights(j);
420   }
421
422   TColStd_Array1OfReal vknots(1,2);
423   TColStd_Array1OfInteger vmults(1,2);
424   vknots(1) = VF;
425   vknots(2) = VL;
426   vmults(1) = vmults(2) = 2;
427
428   bspline = new Geom_BSplineSurface(resPoles, resWeigth, knots, vknots, mults, vmults,
429     bspl->Degree(),1,bspl->IsPeriodic(),Standard_False);
430 }
431
432
433 Standard_Boolean ShapeCustom_BSplineRestriction::ConvertSurface(const Handle(Geom_Surface)& aSurface,
434                                                                 Handle(Geom_Surface)& S,
435                                                                 const Standard_Real UF,
436                                                                 const Standard_Real UL,
437                                                                 const Standard_Real VF,
438                                                                 const Standard_Real VL,
439                                                                 const Standard_Boolean IsOf)
440
441   if(!IsConvertSurface(aSurface,myMaxDegree,myNbMaxSeg,myRational,myParameters))
442     return Standard_False;
443
444   Handle(Geom_Surface) aSurf = aSurface;
445   if (aSurf->IsKind(STANDARD_TYPE(Geom_Plane)) && myParameters->ConvertPlane()) {
446     Handle(Geom_Plane) pln = Handle(Geom_Plane)::DownCast(aSurf);
447     TColgp_Array2OfPnt poles(1,2,1,2);
448     TColStd_Array1OfReal uknots(1,2);
449     TColStd_Array1OfInteger umults(1,2);
450     TColStd_Array1OfReal vknots(1,2);
451     TColStd_Array1OfInteger vmults(1,2);
452
453     poles(1,1) = pln->Value(UF,VF); poles(1,2) = pln->Value(UF,VL);
454     poles(2,1) = pln->Value(UL,VF);  poles(2,2) = pln->Value(UL,VL);
455     uknots(1) = UF; uknots(2) = UL; 
456     vknots(1) = VF; vknots(2) = VL;
457     umults(1) = umults(2) = vmults(1) = vmults(2) = 2;
458     S = new Geom_BSplineSurface(poles, uknots, vknots, umults, vmults, 1, 1, Standard_False, Standard_False);
459     return Standard_True;    
460   }
461   if (aSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {      
462     Handle(Geom_SurfaceOfRevolution) Surface = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
463     Handle(Geom_Curve) BasCurve = Surface->BasisCurve();
464     Handle(Geom_Curve) ResCurve;
465     Standard_Real TolS = Precision::Confusion(); 
466     if(myParameters->ConvertRevolutionSurf()) {
467       if(BasCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
468         GeomAbs_Shape cnt = BasCurve->Continuity();
469         cnt = (cnt > GeomAbs_C2 ? GeomAbs_C2: cnt);
470         if(ConvertCurve(BasCurve,ResCurve,Standard_False,Max(VF,BasCurve->FirstParameter()),Min(VL,BasCurve->LastParameter()),TolS,Standard_False)) {
471           Handle(Geom_SurfaceOfRevolution) newRevol = new Geom_SurfaceOfRevolution(ResCurve,Surface->Axis());
472           aSurf = newRevol;
473 #ifdef OCCT_DEBUG
474           std::cout <<" Revolution on offset converted" << std::endl;
475 #endif
476         }
477       }
478
479     }
480     else {
481       if(ConvertCurve(BasCurve,ResCurve,Standard_False,Max(VF,BasCurve->FirstParameter()),Min(VL,BasCurve->LastParameter()),TolS,IsOf)) {
482         S = new Geom_SurfaceOfRevolution(ResCurve,Surface->Axis());
483         return Standard_True;
484       }
485       else 
486         return Standard_False;
487     }
488   }
489   if (aSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
490     Handle(Geom_SurfaceOfLinearExtrusion) Surface = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aSurf);
491     Handle(Geom_Curve) BasCurve = Surface->BasisCurve();
492     Handle(Geom_Curve) ResCurve;
493     Standard_Real TolS = Precision::Confusion();
494     if(myParameters->ConvertExtrusionSurf()) {
495       GeomAbs_Shape cnt = Surface->Continuity();
496       cnt = (cnt > GeomAbs_C2 ? GeomAbs_C2: cnt);
497       Handle(Geom_BSplineCurve) bspl = ShapeConstruct::ConvertCurveToBSpline(BasCurve, UF, UL, TolS, cnt, myNbMaxSeg, myMaxDegree);
498       BasCurve = bspl;
499       ConvertCurve(BasCurve,ResCurve,Standard_True,Max(UF,BasCurve->FirstParameter()),Min(UL,BasCurve->LastParameter()),TolS,IsOf);
500       gp_Trsf shiftF,shiftL;
501       shiftF.SetTranslation(Surface->Value(UF,0),Surface->Value(UF,VF));
502       shiftL.SetTranslation(Surface->Value(UF,0),Surface->Value(UF,VL));
503       ConvertExtrusion(ResCurve,/*Surface->Direction(),*/shiftF,shiftL,VF,VL,S);
504       return Standard_True;
505     }
506     else {
507       if(ConvertCurve(BasCurve,ResCurve,Standard_False,Max(UF,BasCurve->FirstParameter()),Min(UL,BasCurve->LastParameter()),TolS,IsOf)) {
508         S = new Geom_SurfaceOfLinearExtrusion(ResCurve,Surface->Direction());
509         return Standard_True;
510       }
511       else 
512         return Standard_False;
513     }
514   }
515   if (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
516     Handle(Geom_RectangularTrimmedSurface) tmp = Handle(Geom_RectangularTrimmedSurface)::
517       DownCast (aSurf);
518     Standard_Real U1,U2,V1,V2;
519     tmp->Bounds(U1,U2,V1,V2);
520     Handle(Geom_Surface) theSurf = tmp->BasisSurface();
521     Handle(Geom_Surface) ResSurface;
522     if(ConvertSurface(theSurf,ResSurface,U1,U2,V1,V2,IsOf)) {
523       //S = new Geom_RectangularTrimmedSurface(ResSurface,U1,U2,V1,V2);
524       S = ResSurface;
525       return Standard_True;
526     }
527     else 
528       return Standard_False;
529
530   }
531   if (aSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)) && IsOf) {
532     Handle(Geom_OffsetSurface) tmp = Handle(Geom_OffsetSurface)::DownCast (aSurf);
533     Handle(Geom_Surface) theSurf = tmp->BasisSurface();
534     Handle(Geom_Surface) ResSurface;
535     if(ConvertSurface(theSurf,ResSurface,UF,UL,VF,VL)) {
536       if(ResSurface->Continuity() != GeomAbs_C0) {
537         S = new Geom_OffsetSurface(ResSurface,tmp->Offset());
538         return Standard_True;
539       }
540       else if(ConvertSurface(aSurf,S,UF,UL,VF,VL,Standard_False)) 
541         return Standard_True;
542       else return Standard_False;
543     }
544     else 
545       return Standard_False;
546
547   }
548   if (aSurf->IsKind(STANDARD_TYPE(Geom_BezierSurface)) && myParameters->ConvertBezierSurf()) {
549     Handle(Geom_BezierSurface) bezier = Handle(Geom_BezierSurface)::DownCast(aSurf);
550     Standard_Integer nbUPoles = bezier->NbUPoles();
551     Standard_Integer nbVPoles = bezier->NbVPoles();
552     Standard_Integer uDegree = bezier->UDegree();
553     Standard_Integer vDegree = bezier->VDegree();
554     TColgp_Array2OfPnt aPoles(1,nbUPoles,1,nbVPoles);
555     TColStd_Array2OfReal aWeights(1,nbUPoles,1,nbVPoles);
556     bezier->Poles(aPoles);
557     bezier->Weights(aWeights);
558     TColStd_Array1OfReal uKnots(1,2), vKnots(1,2);
559     uKnots(1) = 0; uKnots(2) = 1;
560     vKnots(1) = 0; vKnots(2) = 1;
561     TColStd_Array1OfInteger uMults(1,2), vMults(1,2);
562     uMults.Init(uDegree+1);
563     vMults.Init(vDegree+1);
564     Handle(Geom_BSplineSurface) bspline = new Geom_BSplineSurface(aPoles,aWeights,uKnots,vKnots,
565       uMults,vMults,uDegree,vDegree);
566
567     if(!ConvertSurface(bspline,S,UF,UL,VF,VL,IsOf))
568       S = bspline;
569     return Standard_True;
570   }
571
572   Standard_Integer NbSeg = 1;
573   Standard_Boolean URat = Standard_False;
574   Standard_Boolean VRat = Standard_False;
575   //if (aSurf->IsKind(STANDARD_TYPE(Geom_BSplineSurface)) || 
576   //    aSurf->IsKind(STANDARD_TYPE(Geom_BezierSurface)) || 
577   //    (aSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)) && !IsOf) ||
578   //    aSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution)) ||
579   //    aSurface->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))) {
580   Standard_Integer UDeg=1,VDeg=1;
581   if (aSurf->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
582     Handle(Geom_BSplineSurface) BsS =  Handle(Geom_BSplineSurface)::DownCast (aSurf);
583     UDeg = BsS->UDegree();
584     VDeg = BsS->VDegree();
585     NbSeg = (BsS->NbUKnots()-1)*(BsS->NbVKnots()-1);
586     URat = BsS->IsURational();
587     VRat = BsS->IsVRational();
588     Standard_Boolean IsR = (myRational && (URat || VRat));
589     if( UDeg <= myMaxDegree &&  VDeg <= myMaxDegree && NbSeg <=  myNbMaxSeg && !IsR ) 
590       return Standard_False;
591   }
592   if (aSurf->IsKind(STANDARD_TYPE(Geom_BezierSurface))) {
593     Handle(Geom_BezierSurface) BsZ = Handle(Geom_BezierSurface)::DownCast (aSurf);
594     UDeg = BsZ->UDegree();
595     VDeg = BsZ->VDegree();
596     NbSeg =1;
597     URat = BsZ->IsURational();
598     VRat = BsZ->IsVRational();
599     Standard_Boolean IsR = (myRational && (URat || VRat));
600     if( UDeg <= myMaxDegree &&  VDeg <= myMaxDegree && NbSeg <=  myNbMaxSeg && !IsR ) 
601       return Standard_False;
602
603   }
604   GeomAbs_Shape Cont = myContinuity3d;
605   if(aSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) Cont = GeomAbs_C0;
606   /*    Standard_Boolean IsR = (myRational && (URat || VRat));
607   if( UDeg <= myMaxDegree &&  VDeg <= myMaxDegree && NbSeg <=  myNbMaxSeg && !IsR ) {
608   return Standard_False;
609
610   }*/
611
612   Standard_Real aTol3d;
613   Standard_Integer nbOfSpan,imax=10;
614   Standard_Integer MaxSeg = myNbMaxSeg;
615   Standard_Integer MaxDeg = myMaxDegree;
616   Standard_Real u1,u2,v1,v2;
617   aSurf->Bounds(u1,u2,v1,v2);
618   Standard_Real ShiftU = 0, ShiftV = 0;
619   if( Abs(u1-UF) > Precision::PConfusion() || Abs(u2- UL) > Precision::PConfusion() || 
620     Abs(v1-VF) > Precision::PConfusion() || Abs(v2- VL) > Precision::PConfusion()) {
621       /*if(aSurf->IsUPeriodic() ) {
622       Standard_Real aDelta = (UL > UF ? UL - UF : UF - UL );
623       u1 = (aDelta > 2.*M_PI ? 0. : UF + ShapeAnalysis::AdjustByPeriod(UF,0.5*(UL+UF),2*M_PI)); 
624       u2 = (aDelta > 2.*M_PI ? 2.*M_PI : u1 + aDelta); 
625       }*/
626       Standard_Boolean isTrim = Standard_False;
627       if(!aSurf->IsUPeriodic() ) { //else {
628         u1 = Max(u1,UF); u2 = Min(u2,UL);
629         isTrim = Standard_True;
630       }
631       /*if(aSurf->IsVPeriodic()) {
632
633       Standard_Real aDelta = (VL > VF ? VL - VF : VF - VL );
634       v1 = (aDelta > 2.*M_PI ? 0. : VF + ShapeAnalysis::AdjustByPeriod(VF,0.5*(UL+UF),2*M_PI));
635       v2 = (aDelta > 2.*M_PI ? 2.* M_PI : v1 + aDelta); 
636       }*/
637       if(!aSurf->IsVPeriodic()) {//else 
638         v1 = Max(v1,VF); v2 = Min(v2,VL);
639         isTrim = Standard_True;
640       }
641
642       if(isTrim && (u1 != u2) && (v1 != v2)) {
643         Handle(Geom_RectangularTrimmedSurface) trSurface = new Geom_RectangularTrimmedSurface(aSurf,u1,u2,v1,v2);
644         Standard_Real ur1,ur2,vr1,vr2;
645         trSurface->Bounds(ur1,ur2,vr1,vr2);
646         ShiftU = u1-ur1;
647         ShiftV = v1-vr1;
648         aSurf = trSurface;
649       }
650   }
651   Standard_Integer aCU= Min(ContToInteger(Cont),ContToInteger(aSurf->Continuity()));
652   Standard_Integer aCV = Min(ContToInteger(Cont),ContToInteger( aSurf->Continuity()));
653   if(!aCU)
654     aCU = ContToInteger(Cont);
655   if(!aCV)
656     aCV = ContToInteger(Cont);
657
658   for(; ;) {
659     Standard_Real prevTol = RealLast(),newTol =0;
660     for (Standard_Integer i=1; i <= imax; i++) {
661       aTol3d = myTol3d*i/2;
662       while (aCU >= 0 || aCV >= 0) {
663         try {
664           OCC_CATCH_SIGNALS
665             GeomAbs_Shape aContV = IntegerToGeomAbsShape(aCV);
666           GeomAbs_Shape aContU = IntegerToGeomAbsShape(aCU);
667
668           GeomConvert_ApproxSurface anApprox(aSurf,aTol3d,aContU,aContV,MaxDeg,MaxDeg,MaxSeg,0);
669           Standard_Boolean Done = anApprox.IsDone();
670           newTol = anApprox.MaxError();
671           if (anApprox.MaxError() <= myTol3d && Done) {
672
673             nbOfSpan = (anApprox.Surface()->NbUKnots()-1)*(anApprox.Surface()->NbVKnots()-1);
674 #ifdef OCCT_DEBUG
675             if((imax-i+1)!=1) {
676               std::cout << " iteration = " << i
677                 <<    "\terror = " << anApprox.MaxError()
678                 <<    "\tspans = " << nbOfSpan << std::endl;
679               std::cout<< " Surface is approximated with continuity " << IntegerToGeomAbsShape(Min(aCU,aCV)) <<std::endl;
680             }
681 #endif
682             S = anApprox.Surface();
683             Handle(Geom_BSplineSurface) Bsc = Handle(Geom_BSplineSurface)::DownCast(S);
684             if(aSurface->IsUPeriodic() )
685               Bsc->SetUPeriodic();
686             if(aSurface->IsVPeriodic() )
687               Bsc->SetVPeriodic();
688             //Standard_Integer DegU = Bsc->UDegree(); // DegU not used (skl)
689             //Standard_Integer DegV = Bsc->VDegree(); // DegV not used (skl)
690             //Standard_Integer nbVK = Bsc->NbVKnots(); // nbVK not used (skl)
691             //Standard_Integer nbUK = Bsc->NbUKnots(); // nbUK not used (skl)
692             myConvert = Standard_True;
693             myNbOfSpan = myNbOfSpan + nbOfSpan;
694             mySurfaceError = Max(mySurfaceError,anApprox.MaxError());
695             if(Abs(ShiftU) > Precision::PConfusion()) {
696               Standard_Integer nb = Bsc->NbUKnots();
697               TColStd_Array1OfReal uknots(1,nb);
698               Bsc->UKnots(uknots);
699               for(Standard_Integer j = 1; j <= nb; j++)
700                 uknots(j)+=ShiftU;
701               Bsc->SetUKnots(uknots);
702             }
703             if(Abs(ShiftV) > Precision::PConfusion()) {
704               Standard_Integer nb = Bsc->NbVKnots();
705               TColStd_Array1OfReal vknots(1,nb);
706               Bsc->VKnots(vknots);
707               for(Standard_Integer j = 1; j <= nb; j++)
708                 vknots(j)+=ShiftV;
709               Bsc->SetVKnots(vknots);
710             }
711
712             return Standard_True;
713           }
714           else {
715             break;
716           }
717
718         }
719
720         catch (Standard_Failure const& anException) {
721 #ifdef OCCT_DEBUG
722           std::cout << "Warning: GeomConvert_ApproxSurface Exception: try to decrease continuity ";
723           anException.Print(std::cout); std::cout << std::endl;
724 #endif
725           (void)anException;
726           //szv: protection against loop
727           if(aCU == 0 && aCV == 0) break;
728           if(aCU > 0) aCU--;
729           if(aCV > 0) aCV--;
730         }
731       }
732       if(prevTol <= newTol) break;
733       else prevTol = newTol;
734     }
735     //Standard_Integer GMaxDegree = 15;//Geom_BSplineSurface::MaxDegree();
736
737     if(myDeg) {
738       if(MaxSeg < myParameters->GMaxSeg()){ 
739         if(aCV != 0 || aCU != 0) {
740           if(aCV > 0) aCV--;
741           if(aCU > 0) aCU--;
742         }
743         else MaxSeg = 2*MaxSeg; //myGMaxSeg; 
744         if(MaxSeg > myParameters->GMaxSeg()) 
745           MaxSeg = myParameters->GMaxSeg();
746         else continue;
747       }
748       else { 
749 #ifdef OCCT_DEBUG
750         std::cout<<" Approximation iteration out. Surface is not approximated." << std::endl;
751 #endif
752         return Standard_False;
753       }
754     }
755     else {
756       if(MaxDeg < myParameters->GMaxDegree())
757       { MaxDeg = myParameters->GMaxDegree(); continue;}
758       else {
759 #ifdef OCCT_DEBUG       
760         std::cout<<" Approximation iteration out. Surface is not approximated." << std::endl;
761 #endif
762         return Standard_False;
763       }
764     }
765   }
766   //}
767   //else 
768   //Surface is not BSpline or Bezier
769   //  return Standard_False;
770 }
771
772 //=======================================================================
773 //function : NewCurve
774 //purpose  : 
775 //=======================================================================
776
777 Standard_Boolean ShapeCustom_BSplineRestriction::NewCurve(const TopoDS_Edge& E,
778                                                           Handle(Geom_Curve)& C,
779                                                           TopLoc_Location& L,
780                                                           Standard_Real& Tol) 
781 {
782   if ( ! myApproxCurve3dFlag )
783     return Standard_False;
784   Standard_Real First, Last;
785   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(E,L,First, Last);
786   Standard_Real TolCur = BRep_Tool::Tolerance(E);
787   //if(aCurve.IsNull()) return Standard_False;
788   Standard_Boolean IsConvert = Standard_False;
789   Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
790   // iterate on pcurves
791   BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
792   for ( ; itcr.More(); itcr.Next() ) {
793     Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
794     if ( GC.IsNull() || ! GC->IsCurveOnSurface() ) continue;
795     Handle(Geom_Surface) aSurface = GC->Surface();
796     Handle(Geom2d_Curve) aCurve2d = GC->PCurve();
797     if((myApproxSurfaceFlag && 
798       IsConvertSurface(aSurface,myMaxDegree,myNbMaxSeg,myRational,myParameters)) || 
799       (myApproxCurve2dFlag && IsConvertCurve2d(aCurve2d,myMaxDegree,myNbMaxSeg,myRational,myParameters))) {
800         IsConvert = Standard_True;
801         break;
802     }
803   }
804   if(aCurve.IsNull()) {
805     if(IsConvert) {
806       C = aCurve;
807       Tol = TolCur;
808       return Standard_True;
809     }
810     else return Standard_False;
811   }
812   Standard_Boolean IsOf = Standard_True;
813   if(myParameters->ConvertOffsetCurv3d())  IsOf = Standard_False;
814   Standard_Boolean IsConv = ConvertCurve(aCurve,C,IsConvert,First,Last,TolCur,IsOf);
815   Tol= BRep_Tool::Tolerance(E);//TolCur;
816
817   if ( IsConv )
818   {
819     Standard_Boolean wasBSpline = aCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve));
820     Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
821     if ( !tc.IsNull() )
822       wasBSpline = tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom_BSplineCurve));
823
824     if ( wasBSpline )
825       SendMsg( E, Message_Msg("BSplineRestriction.NewCurve.MSG1"));
826     else
827       SendMsg( E, Message_Msg("BSplineRestriction.NewCurve.MSG0"));
828   }
829   return IsConv;
830 }
831
832 //=======================================================================
833 //function : ConvertCurve
834 //purpose  : 
835 //=======================================================================
836
837 Standard_Boolean ShapeCustom_BSplineRestriction::ConvertCurve(const Handle(Geom_Curve)& aCurve,
838                                                               Handle(Geom_Curve)& C,
839                                                               const Standard_Boolean IsConvert,
840                                                               const Standard_Real First,
841                                                               const Standard_Real Last,
842                                                               Standard_Real& TolCur,
843                                                               const Standard_Boolean IsOf) 
844 {
845   //  TolCur =  Precision::Confusion();
846   if (aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
847     Handle(Geom_TrimmedCurve) tmp = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
848     //Standard_Real pf =tmp->FirstParameter(), pl =  tmp->LastParameter(); // pf,pl not used - see below (skl)
849     Handle(Geom_Curve) BasCurve = tmp->BasisCurve();
850     Handle(Geom_Curve) ResCurve;
851     if(ConvertCurve(BasCurve,ResCurve,IsConvert,First,Last,TolCur,IsOf)) {
852       //      Stanadrd_Real F = Max(pf,First), L = Min(pl,Last);
853       //      if(First != Last)
854       //        C = new Geom_TrimmedCurve(ResCurve,Max(First,ResCurve->FirstParameter()),Min(Last,ResCurve->LastParameter()));
855       //else 
856       C = ResCurve;
857       return Standard_True;
858     }
859     else {
860       if(IsConvert) {
861         C = Handle(Geom_Curve)::DownCast(aCurve->Copy());
862         TolCur =  Precision::Confusion();
863         return Standard_True;
864       }
865
866       return Standard_False;
867     }
868   }
869
870   if (aCurve->IsKind(STANDARD_TYPE(Geom_Line)) && myParameters->ConvertCurve3d()) {
871     Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(aCurve);
872     TColgp_Array1OfPnt poles(1,2);
873     poles(1) = aLine->Value(First);
874     poles(2) = aLine->Value(Last);
875     TColStd_Array1OfReal knots(1,2);
876     knots(1) = First; knots(2) = Last;
877     TColStd_Array1OfInteger mults(1,2);
878     mults.Init(2);
879     Handle(Geom_BSplineCurve) res = new Geom_BSplineCurve(poles,knots,mults,1);
880     C = res;
881     return Standard_True;
882   }
883
884   if (aCurve->IsKind(STANDARD_TYPE(Geom_Conic)) && myParameters->ConvertCurve3d()) {
885     Handle(Geom_BSplineCurve) aBSpline;
886     Handle(Geom_Curve) tcurve = new Geom_TrimmedCurve(aCurve,First,Last); //protection against parabols ets
887     GeomConvert_ApproxCurve approx (tcurve, myTol3d/*Precision::Approximation()*/, myContinuity2d, myNbMaxSeg, 6 );
888     if ( approx.HasResult() )
889       aBSpline = approx.Curve();
890     else 
891       aBSpline = GeomConvert::CurveToBSplineCurve(tcurve,Convert_QuasiAngular);
892
893     Standard_Real Shift = First - aBSpline->FirstParameter();
894     if(Abs(Shift) > Precision::PConfusion()) {
895       Standard_Integer nbKnots = aBSpline->NbKnots();
896       TColStd_Array1OfReal newKnots(1,nbKnots);
897       aBSpline->Knots(newKnots);
898       for (Standard_Integer i = 1; i <= nbKnots; i++)
899         newKnots(i)+=Shift;
900       aBSpline->SetKnots(newKnots);
901     }
902     Handle(Geom_Curve) ResCurve;
903     if(ConvertCurve(aBSpline,ResCurve,IsConvert,First,Last,TolCur,Standard_False)) {
904       C = ResCurve;
905       return Standard_True;
906     }
907     else {
908       C = aBSpline;
909       TolCur = Precision::PConfusion();
910       return Standard_True;
911     } 
912   }
913
914   if (aCurve->IsKind(STANDARD_TYPE(Geom_BezierCurve)) && myParameters->ConvertCurve3d()) {
915     Handle(Geom_Curve) aBSpline 
916       = GeomConvert::CurveToBSplineCurve(aCurve,Convert_QuasiAngular);
917     Handle(Geom_Curve) ResCurve;
918     if(ConvertCurve(aBSpline,ResCurve,IsConvert,First,Last,TolCur,Standard_False)) {
919       C = ResCurve;
920       return Standard_True;
921     }
922     else {
923       C = aBSpline;
924       TolCur = Precision::PConfusion();
925       return Standard_True;
926     } 
927   }
928
929   if (aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)) && IsOf) {
930     Handle(Geom_OffsetCurve) tmp = Handle(Geom_OffsetCurve)::DownCast (aCurve);
931     Handle(Geom_Curve) BasCurve = tmp->BasisCurve();
932     Handle(Geom_Curve) ResCurve;
933     if(ConvertCurve(BasCurve,ResCurve,IsConvert,First,Last,TolCur)) {
934       if(ResCurve->Continuity() != GeomAbs_C0) {
935         C = new Geom_OffsetCurve(ResCurve,tmp->Offset(),tmp->Direction());
936         return Standard_True;
937       }
938       else if(ConvertCurve(aCurve,C,IsConvert,First,Last,TolCur,Standard_False))
939         return Standard_True;
940       else {
941         if(IsConvert) {
942           C = Handle(Geom_Curve)::DownCast(aCurve->Copy());
943           TolCur =  Precision::Confusion();
944           return Standard_True;
945         }
946         return Standard_False;
947       }
948     } 
949     else {
950       if(IsConvert) {
951         C = Handle(Geom_Curve)::DownCast(aCurve->Copy());
952         TolCur =  Precision::Confusion();
953         return Standard_True;
954       }
955       return Standard_False;
956     }
957   }
958   if (aCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) || 
959     aCurve->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ||
960     (aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)) && !IsOf))  {
961       Standard_Integer Deg=1;
962
963       if (aCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
964         Handle(Geom_BSplineCurve) BsC = Handle(Geom_BSplineCurve)::DownCast (aCurve);
965         Deg =BsC->Degree();
966         Standard_Boolean IsR = (myRational && BsC->IsRational());
967         if(!IsR && Deg <= myMaxDegree && (BsC->NbKnots() - 1) <= myNbMaxSeg) {
968           if(IsConvert) {
969             C = Handle(Geom_Curve)::DownCast(aCurve->Copy());
970             TolCur =  Precision::Confusion();
971             return Standard_True;
972           }
973           else return Standard_False;
974         }
975       }
976       if (aCurve->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
977         Handle(Geom_BezierCurve) BzC =  Handle(Geom_BezierCurve)::DownCast (aCurve);
978         Deg =BzC->Degree();
979         Standard_Boolean IsR = (myRational && BzC->IsRational());
980         if(!IsR && Deg <= myMaxDegree ) {
981           if(IsConvert) {
982             C = Handle(Geom_Curve)::DownCast(aCurve->Copy());
983             TolCur =  Precision::Confusion();
984             return Standard_True;
985           }
986           else return Standard_False;
987         }
988       }
989       Handle(Geom_Curve) aCurve1;
990       Standard_Real pf =aCurve->FirstParameter(), pl =  aCurve->LastParameter();
991       // 15.11.2002 PTV OCC966
992       if(ShapeAnalysis_Curve::IsPeriodic(aCurve) && (First != Last))  aCurve1 = new Geom_TrimmedCurve(aCurve,First,Last);
993       else if(pf < (First - Precision::PConfusion()) || 
994         pl > (Last + Precision::PConfusion())) {
995           Standard_Real F = Max(First,pf),
996             L = Min(Last,pl);
997           if(F != L)
998             aCurve1 = new Geom_TrimmedCurve(aCurve,F,L);
999           else aCurve1 = aCurve; 
1000       }
1001       else aCurve1 = aCurve; 
1002       Standard_Integer  aC = Min(ContToInteger(myContinuity3d),ContToInteger(aCurve->Continuity()));
1003       if(!aC)
1004         aC = ContToInteger(myContinuity3d);
1005       //aC = Min(aC,(Deg -1));
1006       Standard_Integer MaxSeg = myNbMaxSeg;
1007       Standard_Integer MaxDeg = myMaxDegree;
1008       //GeomAbs_Shape aCont = IntegerToGeomAbsShape(aC);
1009       Standard_Integer aC1 = aC;
1010       //Standard_Integer GMaxDegree = 15; //Geom_BSplineCurve::MaxDegree();
1011       for(; aC >= 0; aC--) {
1012         try {
1013           OCC_CATCH_SIGNALS
1014             for(Standard_Integer j = 1; j <=2 ; j++) {
1015               GeomAbs_Shape aCont = IntegerToGeomAbsShape(aC);
1016               GeomConvert_ApproxCurve anApprox(aCurve1,myTol3d,aCont,MaxSeg,MaxDeg);
1017               Standard_Boolean Done = anApprox.IsDone();
1018               C=anApprox.Curve();
1019               Standard_Integer Nbseg = Handle(Geom_BSplineCurve)::DownCast(C)->NbKnots() - 1;
1020               Standard_Integer DegC = Handle(Geom_BSplineCurve)::DownCast(C)->Degree();
1021               if( myDeg && ((DegC > MaxDeg) || !Done || 
1022                 (anApprox.MaxError() >= Max(TolCur,myTol3d)))) {
1023                   if(MaxSeg < myParameters->GMaxSeg()) { MaxSeg = myParameters->GMaxSeg(); aC =aC1; continue;}
1024                   else {
1025 #ifdef OCCT_DEBUG
1026                     std::cout << "Curve is not aproxed with continuity  "<< aCont<<std::endl;
1027 #endif        
1028                     if(IsConvert) {
1029                       C = Handle(Geom_Curve)::DownCast(aCurve->Copy());
1030                       TolCur =  Precision::Confusion();
1031                       return Standard_True;
1032                     } 
1033                   }
1034               }
1035               if(!myDeg && ((Nbseg > myParameters->GMaxSeg()) || !Done || 
1036                 (anApprox.MaxError() >= Max(TolCur,myTol3d)))) {
1037                   if(MaxDeg < myParameters->GMaxDegree()) { 
1038                     MaxDeg = myParameters->GMaxDegree(); aC = aC1; continue;
1039                   }
1040                   else {
1041 #ifdef OCCT_DEBUG
1042                     std::cout << "Curve is not aproxed with continuity  "<< aCont<<std::endl;
1043 #endif
1044                     if(IsConvert) {
1045                       C = Handle(Geom_Curve)::DownCast(aCurve->Copy());
1046                       TolCur =  Precision::Confusion();
1047                       return Standard_True;
1048                     } 
1049                   }
1050               }
1051               myConvert = Standard_True;
1052               TolCur =  anApprox.MaxError();
1053               myCurve3dError = Max(myCurve3dError,anApprox.MaxError());
1054               return Standard_True;
1055             }
1056         }
1057         catch (Standard_Failure const& anException) {
1058 #ifdef OCCT_DEBUG
1059           std::cout << "Warning: GeomConvert_ApproxCurve Exception: Wrong Coefficient : Decrease continuity    ";
1060           anException.Print(std::cout); std::cout << std::endl;
1061 #endif
1062           (void)anException;
1063           continue;
1064         } 
1065       }
1066       return Standard_False;
1067   }  
1068   else {
1069     if(IsConvert) {
1070       C = Handle(Geom_Curve)::DownCast(aCurve->Copy());
1071       TolCur =  Precision::Confusion();
1072       return Standard_True;
1073     }
1074     return Standard_False;
1075   }
1076 }
1077
1078 //=======================================================================
1079 //function : NewCurve2d
1080 //purpose  : 
1081 //=======================================================================
1082
1083 Standard_Boolean ShapeCustom_BSplineRestriction::NewCurve2d(const TopoDS_Edge& E,
1084                                                             const TopoDS_Face& F,
1085                                                             const TopoDS_Edge& NewE,
1086                                                             const TopoDS_Face& /*NewF*/,
1087                                                             Handle(Geom2d_Curve)& C,
1088                                                             Standard_Real& Tol)
1089 {
1090   if ( ! myApproxCurve2dFlag && !myApproxSurfaceFlag)
1091     return Standard_False;
1092   Standard_Real First, Last,F1,L1;
1093   TopLoc_Location L,Loc1;
1094   Handle(Geom_Surface) aSurface = BRep_Tool::Surface(F,L);
1095   GeomAdaptor_Surface AdS(aSurface);
1096   Standard_Real TolCur = Min(AdS.UResolution(BRep_Tool::Tolerance(E)),AdS.VResolution(BRep_Tool::Tolerance(E)));
1097   Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(E,F,First, Last);
1098   if(aCurve.IsNull()) return Standard_False;
1099   Handle(Geom_Curve) aCur3d = BRep_Tool::Curve(E,Loc1,F1, L1);
1100   //  Standard_Boolean IsConvert = (IsConvertSurface(aSurface,myMaxDegree,myNbMaxSeg) || !E.IsSame(NewE));
1101
1102   Standard_Boolean IsConvert = 
1103     ((myApproxSurfaceFlag && IsConvertSurface(aSurface,myMaxDegree,myNbMaxSeg,myRational,myParameters)) || 
1104     (myApproxCurve3dFlag && IsConvertCurve3d(aCur3d,myMaxDegree,myNbMaxSeg,myRational,myParameters)));
1105
1106   if(!IsConvert) {
1107     Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&E.TShape());
1108     // iterate on pcurves
1109     BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
1110     for ( ; itcr.More(); itcr.Next() ) {
1111       Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
1112       if ( GC.IsNull() || ! GC->IsCurveOnSurface() ) continue;
1113       Handle(Geom_Surface) aSurf = GC->Surface();
1114       Handle(Geom2d_Curve) aCur2d = GC->PCurve();
1115       if((myApproxSurfaceFlag && IsConvertSurface(aSurf,myMaxDegree,myNbMaxSeg,myRational,myParameters)) || 
1116         (myApproxCurve2dFlag && IsConvertCurve2d(aCur2d,myMaxDegree,myNbMaxSeg,myRational,myParameters))) {
1117           IsConvert = Standard_True;
1118           break;
1119       }
1120     }
1121   }
1122   if(! myApproxCurve2dFlag){
1123     if(IsConvert) {
1124       C = Handle(Geom2d_Curve)::DownCast(aCurve->Copy());
1125       return Standard_True;
1126     }
1127     else
1128       return Standard_False;
1129   }
1130   Standard_Boolean IsOf = Standard_True;
1131   if(myParameters->ConvertOffsetCurv2d())  IsOf = Standard_False;
1132   Standard_Boolean IsConv = ConvertCurve2d(aCurve,C,IsConvert,First,Last,TolCur,IsOf);
1133
1134   Tol= BRep_Tool::Tolerance(E);//TolCur;
1135   BRep_Builder B;
1136   if(!IsConv && !NewE.IsSame( E)) 
1137     B.Range(NewE,First,Last);
1138   return IsConv;
1139 }
1140
1141 //=======================================================================
1142 //function : ConvertCurve2d
1143 //purpose  : 
1144 //=======================================================================
1145
1146 Standard_Boolean ShapeCustom_BSplineRestriction::ConvertCurve2d(const Handle(Geom2d_Curve)& aCurve,
1147                                                                 Handle(Geom2d_Curve)& C, 
1148                                                                 const Standard_Boolean IsConvert,
1149                                                                 const Standard_Real First, 
1150                                                                 const Standard_Real Last,
1151                                                                 Standard_Real& TolCur,
1152                                                                 const Standard_Boolean IsOf) 
1153 {  
1154   //TolCur = Precision::PConfusion();
1155   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
1156     Handle(Geom2d_TrimmedCurve) tmp = Handle(Geom2d_TrimmedCurve)::DownCast (aCurve);
1157     // Standard_Real pf =tmp->FirstParameter(), pl =  tmp->LastParameter();
1158     Handle(Geom2d_Curve) BasCurve = tmp->BasisCurve();
1159     Handle(Geom2d_Curve) ResCurve;
1160     if(ConvertCurve2d(BasCurve,ResCurve,IsConvert,First,Last,TolCur,IsOf)) {
1161       //      Standard_Real F = Max(ResCurve->FirstParameter(),First), L = Min(ResCurve->LastParameter(),Last);
1162       //      if(F != Last)
1163       //C = new Geom2d_TrimmedCurve(ResCurve,Max(First,ResCurve->FirstParameter()),Min(Last,ResCurve->LastParameter()));
1164       //else 
1165       C = ResCurve;
1166       return Standard_True;
1167     }
1168     else {
1169       if(IsConvert) {
1170         C = Handle(Geom2d_Curve)::DownCast(aCurve->Copy());
1171         TolCur = Precision::PConfusion();
1172         return Standard_True;
1173       }
1174       else return Standard_False;
1175     }
1176   }
1177
1178   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_Line)) && myParameters->ConvertCurve2d()) {
1179     Handle(Geom2d_Line) aLine2d = Handle(Geom2d_Line)::DownCast(aCurve);
1180     TColgp_Array1OfPnt2d poles(1,2);
1181     poles(1) = aLine2d->Value(First);
1182     poles(2) = aLine2d->Value(Last);
1183     TColStd_Array1OfReal knots(1,2);
1184     knots(1) = First; knots(2) = Last;
1185     TColStd_Array1OfInteger mults(1,2);
1186     mults.Init(2);
1187     Handle(Geom2d_BSplineCurve) res = new Geom2d_BSplineCurve(poles,knots,mults,1);
1188     C = res;
1189     return Standard_True;
1190   }
1191
1192   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_Conic)) && myParameters->ConvertCurve2d()) {
1193     Handle(Geom2d_BSplineCurve) aBSpline2d;
1194     Handle(Geom2d_Curve) tcurve = new Geom2d_TrimmedCurve(aCurve,First,Last); //protection against parabols ets
1195     Geom2dConvert_ApproxCurve approx (tcurve, myTol2d,myContinuity2d,myNbMaxSeg , 6 );
1196     if ( approx.HasResult() )
1197       aBSpline2d = approx.Curve();
1198     else 
1199       aBSpline2d = Geom2dConvert::CurveToBSplineCurve(tcurve,Convert_QuasiAngular);
1200
1201     Standard_Real Shift = First - aBSpline2d->FirstParameter();
1202     if(Abs(Shift) > Precision::PConfusion()) {
1203       Standard_Integer nbKnots = aBSpline2d->NbKnots();
1204       TColStd_Array1OfReal newKnots(1,nbKnots);
1205       aBSpline2d->Knots(newKnots);
1206       for (Standard_Integer i = 1; i <= nbKnots; i++)
1207         newKnots(i)+=Shift;
1208       aBSpline2d->SetKnots(newKnots);
1209     }
1210     Handle(Geom2d_Curve) ResCurve;
1211     if(ConvertCurve2d(aBSpline2d,ResCurve,IsConvert,First,Last,TolCur,Standard_False)) {
1212       C = ResCurve;
1213       return Standard_True;
1214     }
1215     else {
1216       C = aBSpline2d;
1217       TolCur = Precision::PConfusion();
1218       return Standard_True;
1219     } 
1220   }
1221
1222   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve)) && myParameters->ConvertCurve2d()) {
1223     Handle(Geom2d_Curve) aBSpline2d 
1224       = Geom2dConvert::CurveToBSplineCurve(aCurve,Convert_QuasiAngular);
1225     Handle(Geom2d_Curve) ResCurve;
1226     if(ConvertCurve2d(aBSpline2d,ResCurve,IsConvert,First,Last,TolCur,Standard_False)) {
1227       C = ResCurve;
1228       return Standard_True;
1229     }
1230     else {
1231       C = aBSpline2d;
1232       TolCur = Precision::PConfusion();
1233       return Standard_True;
1234     } 
1235   }
1236
1237   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)) && IsOf) {
1238     Handle(Geom2d_OffsetCurve) tmp = Handle(Geom2d_OffsetCurve)::DownCast (aCurve);
1239     Handle(Geom2d_Curve) BasCurve = tmp->BasisCurve();
1240     Handle(Geom2d_Curve) ResCurve;
1241     if(ConvertCurve2d(BasCurve,ResCurve,IsConvert,First,Last,TolCur)) {
1242       if(ResCurve->Continuity() != GeomAbs_C0) {
1243         C = new Geom2d_OffsetCurve(ResCurve,tmp->Offset());
1244         return Standard_True;
1245       }
1246       else if (ConvertCurve2d(aCurve,ResCurve,IsConvert,First,Last,TolCur,Standard_False))
1247         return Standard_True;
1248       else {
1249         if(IsConvert) {
1250           C = Handle(Geom2d_Curve)::DownCast(aCurve->Copy());
1251           TolCur = Precision::PConfusion();
1252           return Standard_True;
1253         }
1254         else return Standard_False;
1255
1256       }
1257     } 
1258     else {
1259       if(IsConvert) {
1260         C = Handle(Geom2d_Curve)::DownCast(aCurve->Copy());
1261         TolCur = Precision::PConfusion();
1262         return Standard_True;
1263       }
1264       else return Standard_False;
1265     }
1266   }
1267   if (aCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) || 
1268       aCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))  ||
1269       ((aCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) && !IsOf ))  {
1270       Standard_Integer Deg=1;
1271
1272       if (aCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
1273         Handle(Geom2d_BSplineCurve) BsC = Handle(Geom2d_BSplineCurve)::DownCast (aCurve);
1274         Deg =BsC->Degree();
1275         Standard_Boolean IsR = (myRational && BsC->IsRational());
1276         if(!IsR && Deg <= myMaxDegree && (BsC->NbKnots() -1) <= myNbMaxSeg) {
1277           if(IsConvert) {
1278             C = Handle(Geom2d_Curve)::DownCast(aCurve->Copy());
1279             TolCur = Precision::PConfusion();
1280             return Standard_True;
1281           }
1282           else return Standard_False;
1283         }
1284       }
1285       if (aCurve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) {
1286         Handle(Geom2d_BezierCurve)BzC =  Handle(Geom2d_BezierCurve)::DownCast (aCurve);
1287         Deg =BzC->Degree();
1288         Standard_Boolean IsR = (myRational && BzC->IsRational());
1289         if(!IsR && Deg <= myMaxDegree) {
1290           if(IsConvert) {
1291             C = Handle(Geom2d_Curve)::DownCast(aCurve->Copy());
1292             TolCur = Precision::PConfusion();
1293             return Standard_True;
1294           }
1295           else return Standard_False;
1296         }
1297       }
1298       Handle(Geom2d_Curve) aCurve1;
1299       Standard_Real pf =aCurve->FirstParameter(), pl =  aCurve->LastParameter();
1300       // 15.11.2002 PTV OCC966
1301       if(ShapeAnalysis_Curve::IsPeriodic(aCurve) && (First != Last)) aCurve1 = new Geom2d_TrimmedCurve(aCurve,First,Last);
1302       else if(aCurve->FirstParameter() < (First - Precision::PConfusion())  || 
1303         aCurve->LastParameter() > (Last + Precision::PConfusion())) {
1304           Standard_Real F = Max(First,pf),
1305             L = Min(Last,pl);
1306           if(F != L)
1307             aCurve1 = new Geom2d_TrimmedCurve(aCurve,F,L);
1308           else aCurve1 = aCurve;
1309       }
1310       else aCurve1 = aCurve;
1311       Standard_Integer aC = Min(ContToInteger(myContinuity2d),ContToInteger( aCurve->Continuity()));
1312       if(!aC)
1313         aC = ContToInteger(myContinuity2d);
1314       //aC = Min(aC,(Deg -1));
1315       Standard_Integer aC1 = aC;
1316       //GeomAbs_Shape aCont =IntegerToGeomAbsShape(aC);
1317       Standard_Integer MaxSeg = myNbMaxSeg;
1318       Standard_Integer MaxDeg = myMaxDegree;
1319       //Standard_Integer GMaxDegree = 15;//Geom2d_BSplineCurve::MaxDegree();
1320       for(; aC >= 0; aC--) {
1321         try {
1322           OCC_CATCH_SIGNALS
1323             GeomAbs_Shape aCont = IntegerToGeomAbsShape(aC);
1324           for(Standard_Integer j =1;j<=2 ;j++) {
1325             Geom2dConvert_ApproxCurve anApprox(aCurve1,myTol2d,aCont,MaxSeg,MaxDeg);
1326             Standard_Boolean Done = anApprox.IsDone();
1327             C=anApprox.Curve();
1328             Standard_Integer Nbseg = Handle(Geom2d_BSplineCurve)::DownCast(C)->NbKnots() -1;
1329             Standard_Integer DegC = Handle(Geom2d_BSplineCurve)::DownCast(C)->Degree();
1330
1331             if(myDeg && ((DegC > MaxDeg)  || !Done || ( anApprox.MaxError() >= Max(myTol2d,TolCur)))) {
1332               if(MaxSeg < myParameters->GMaxSeg()) { MaxSeg = myParameters->GMaxSeg(); aC =aC1; continue;}
1333               else {
1334 #ifdef OCCT_DEBUG
1335                 std::cout << "Curve is not aproxed with continuity  "<< aCont<<std::endl;
1336 #endif
1337                 if(IsConvert) {
1338                   C = Handle(Geom2d_Curve)::DownCast(aCurve->Copy());
1339                   TolCur = Precision::PConfusion();
1340                   return Standard_True;
1341                 } 
1342               }
1343             }
1344
1345             if(!myDeg && (( Nbseg >= MaxSeg)|| !Done || ( anApprox.MaxError() >= Max(myTol2d,TolCur)))) {
1346               if(MaxDeg < myParameters->GMaxDegree()) { 
1347                 MaxDeg = myParameters->GMaxDegree(); aC =aC1; continue;
1348               }
1349               else {
1350 #ifdef OCCT_DEBUG
1351                 std::cout << "Curve is not aproxed with continuity  "<< aCont<<std::endl;
1352 #endif
1353                 if(IsConvert) {
1354                   C = Handle(Geom2d_Curve)::DownCast(aCurve->Copy());
1355                   TolCur = Precision::PConfusion();
1356                   return Standard_True;
1357                 } 
1358               }
1359             }
1360             myConvert= Standard_True; 
1361             TolCur = anApprox.MaxError();
1362             myCurve2dError = Max(myCurve2dError,anApprox.MaxError());
1363             return Standard_True;
1364           }
1365         }
1366         catch (Standard_Failure const& anException) {
1367 #ifdef OCCT_DEBUG
1368           std::cout << "Warning: Geom2dConvert_ApproxCurve Exception: Wrong Cofficient :Decrease Continuity    ";
1369           anException.Print(std::cout); std::cout << std::endl;
1370 #endif
1371           (void)anException;
1372           continue;
1373         }
1374       }
1375       return Standard_False;
1376   }  
1377   else {
1378     if(IsConvert) {
1379       C = Handle(Geom2d_Curve)::DownCast(aCurve->Copy());
1380       TolCur = Precision::PConfusion();
1381       return Standard_True;
1382     }
1383     else return Standard_False;
1384   }
1385 }
1386
1387 //=======================================================================
1388 //function : NewPoint
1389 //purpose  : 
1390 //=======================================================================
1391
1392 Standard_Boolean ShapeCustom_BSplineRestriction::NewPoint(const TopoDS_Vertex& V,
1393                                                           gp_Pnt& P,
1394                                                           Standard_Real& Tol)
1395 {
1396   Tol = BRep_Tool::Tolerance(V);
1397   if(myConvert) {
1398     gp_Pnt p1(BRep_Tool::Pnt(V).XYZ());
1399     P = p1; 
1400     return Standard_True;
1401   }
1402   else 
1403     return Standard_False;
1404 }
1405
1406 //=======================================================================
1407 //function : NewParameter
1408 //purpose  : 
1409 //=======================================================================
1410
1411 Standard_Boolean ShapeCustom_BSplineRestriction::NewParameter(const TopoDS_Vertex& /*V*/,
1412                                                               const TopoDS_Edge& /*E*/,
1413                                                               Standard_Real& /*P*/,
1414                                                               Standard_Real& /*Tol*/)
1415 {
1416   return Standard_False;
1417 }
1418
1419 //=======================================================================
1420 //function : Continuity
1421 //purpose  : 
1422 //=======================================================================
1423
1424 GeomAbs_Shape ShapeCustom_BSplineRestriction::Continuity(const TopoDS_Edge& E,
1425                                                          const TopoDS_Face& F1,
1426                                                          const TopoDS_Face& F2,
1427                                                          const TopoDS_Edge& /*NewE*/,
1428                                                          const TopoDS_Face& /*NewF1*/,
1429                                                          const TopoDS_Face& /*NewF2*/)
1430 {
1431   return BRep_Tool::Continuity(E,F1,F2);
1432 }
1433
1434 //=======================================================================
1435 //function : MaxErrors
1436 //purpose  : 
1437 //=======================================================================
1438
1439 Standard_Real ShapeCustom_BSplineRestriction::MaxErrors(Standard_Real& aCurve3dErr,Standard_Real& aCurve2dErr) const
1440 {
1441   aCurve3dErr = myCurve3dError;
1442   aCurve2dErr = myCurve2dError;
1443   return mySurfaceError;
1444 }
1445
1446 //=======================================================================
1447 //function : NbOfSpan
1448 //purpose  : 
1449 //======================================================================
1450
1451 Standard_Integer ShapeCustom_BSplineRestriction::NbOfSpan() const
1452 {
1453   return myNbOfSpan;
1454 }
1455