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