5acd4e5ea2a246273c38c273cf5cf014bdf9b9bf
[occt.git] / src / IGESConvGeom / IGESConvGeom.cxx
1 // Created on: 1994-09-01
2 // Created by: Christian CAILLET
3 // Copyright (c) 1994-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 // modif du 31/01/97 : mjm
18 // on commence par les SplineCurves.
19 // modif du 17/03/97 : mjm
20 // SplineSurfaces.
21 //%13 pdn 12.02.99: USA60293 avoid applying transformation twice
22
23 #include <BSplCLib.hxx>
24 #include <BSplSLib.hxx>
25 #include <Geom2d_BSplineCurve.hxx>
26 #include <Geom_BSplineCurve.hxx>
27 #include <Geom_BSplineSurface.hxx>
28 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
29 #include <gp_GTrsf.hxx>
30 #include <gp_Trsf.hxx>
31 #include <IGESConvGeom.hxx>
32 #include <IGESData_ToolLocation.hxx>
33 #include <IGESGeom_SplineCurve.hxx>
34 #include <IGESGeom_SplineSurface.hxx>
35 #include <PLib.hxx>
36 #include <TColgp_HArray1OfPnt.hxx>
37 #include <TColgp_HArray2OfPnt.hxx>
38 #include <TColStd_Array1OfInteger.hxx>
39 #include <TColStd_Array1OfReal.hxx>
40 #include <TColStd_HArray1OfReal.hxx>
41
42 //=======================================================================
43 //function : IGESConvGeom::SplineCurveFromIGES
44 //purpose  : 
45 //=======================================================================
46 Standard_Integer  IGESConvGeom::SplineCurveFromIGES
47   (const Handle(IGESGeom_SplineCurve)& st,
48    const Standard_Real /*epscoef*/,  const Standard_Real epsgeom,
49    Handle(Geom_BSplineCurve)& res)
50 {
51   Standard_Integer returned = 0;
52
53   // on recupere le degre
54   Standard_Integer degree = st->SplineType();
55   if (degree > 3) degree = 3;
56
57   // on recupere le nombre de segments.
58   Standard_Integer nbSegs  = st->NbSegments();  
59   if (nbSegs < 1) return 5;            // FAIL : no segment
60
61   Standard_Integer nbKnots = nbSegs+1;          
62
63   // Array of multiplicities.  
64   TColStd_Array1OfInteger multi(1, nbKnots); 
65   multi.Init(degree);
66   multi.SetValue(multi.Lower(), degree+1);
67   multi.SetValue(multi.Upper(), degree+1);
68
69   // Array of knots.  
70   TColStd_Array1OfReal knots(1, nbKnots);                 
71   TColStd_Array1OfReal delta(1, nbSegs);
72   Standard_Integer i; // svv Jan 10 2000 : porting on DEC
73   for (i = 1; i<= nbKnots; i++)
74     knots.SetValue(i, st->BreakPoint(i));
75
76   for (i = 1; i <= nbSegs; i++) 
77     delta.SetValue(i, st->BreakPoint(i+1) - st->BreakPoint(i));
78
79   TColgp_Array1OfPnt bspoles(1, nbSegs*degree+1);
80   Standard_Integer ibspole = bspoles.Lower()-1;              // Bspole Index.
81   // il faut reparametrer avant de passer dans PLib.
82   // on est entre[0, T(i+1)-T(i)] et on veut [0,1]
83
84   for (i = 1; i <= nbSegs; i++) {
85     Standard_Real AX,BX,CX,DX,AY,BY,CY,DY,AZ,BZ,CZ,DZ;
86     st->XCoordPolynomial(i, AX, BX, CX, DX);
87     st->YCoordPolynomial(i, AY, BY, CY, DY);
88     st->ZCoordPolynomial(i, AZ, BZ, CZ, DZ);
89     if (st->NbDimensions() == 2 ) BZ=0.,CZ=0.,DZ=0.; 
90     Standard_Real Di  = delta(i);
91     Standard_Real Di2 = delta(i)*delta(i);
92     Standard_Real Di3 = delta(i)*delta(i)*delta(i);
93
94     TColgp_Array1OfPnt coeff(0, degree);
95     switch (degree) {
96     case 3 :
97       coeff.SetValue(coeff.Lower()+3, gp_Pnt(DX*Di3, DY*Di3, DZ*Di3));
98     case 2 :
99       coeff.SetValue(coeff.Lower()+2, gp_Pnt(CX*Di2, CY*Di2, CZ*Di2));
100     case 1 :
101       coeff.SetValue(coeff.Lower()+1, gp_Pnt(BX*Di, BY*Di, BZ*Di));
102       coeff.SetValue(coeff.Lower()+0, gp_Pnt(AX, AY, AZ));
103       break;
104     default:
105       break;
106     }
107
108
109     TColgp_Array1OfPnt bzpoles(0, degree);
110     PLib::CoefficientsPoles(coeff,PLib::NoWeights(),bzpoles,PLib::NoWeights());
111
112     // C0 test.
113     // Not to check the first pole of the first segment.
114     if (ibspole > bspoles.Lower()) {  
115       Standard_Integer bzlow = bzpoles.Lower();
116       if (!(bspoles.Value(ibspole).IsEqual(bzpoles.Value(bzlow), epsgeom))) {
117         returned = 1;
118         // Medium point computing.
119         bspoles.SetValue (ibspole, 
120            gp_Pnt((bspoles.Value(ibspole).X() + bzpoles.Value(bzlow).X())/2.,
121                   (bspoles.Value(ibspole).Y() + bzpoles.Value(bzlow).Y())/2.,
122                   (bspoles.Value(ibspole).Z() + bzpoles.Value(bzlow).Z())/2.));
123       }
124     }
125     if (i == 1) bspoles.SetValue(++ibspole, bzpoles.Value(bzpoles.Lower()));
126
127     for (Standard_Integer j = bzpoles.Lower()+1; j <= bzpoles.Upper(); j++) 
128       bspoles.SetValue(++ibspole, bzpoles.Value(j));
129   }
130   if (ibspole != bspoles.Upper()) {   
131     // Just to be sure.
132     return 3;           // FAIL : Error during creation of control points
133   }
134
135   //  Building result taking into account transformation if any :
136   //  ===========================================================
137   
138   //%13 pdn 12.02.99 USA60293
139 //  if (st->HasTransf()) {
140 //    gp_Trsf trsf;
141 //    Standard_Real epsilon = 1.E-04;
142 //    if (IGESData_ToolLocation::ConvertLocation
143 //      (epsilon,st->CompoundLocation(),trsf)) { 
144 //      for (Standard_Integer i = bspoles.Lower(); i <= bspoles.Upper(); i++) 
145 //      bspoles.SetValue(i, bspoles.Value(i).Transformed(trsf));
146 //    }
147 //    else
148 //      AddFail(st, "Transformation : not a similarity");
149 //  }
150   res = new Geom_BSplineCurve (bspoles, knots, multi, degree);
151 //  GeomConvert_CompCurveToBSplineCurve CompCurve = 
152 //    GeomConvert_CompCurveToBSplineCurve(res);
153 //  res = CompCurve.BSplineCurve();
154   return returned;
155 }
156
157
158
159 //=======================================================================
160 //function : IGESConvGeom::IncreaseCurveContinuity
161 //purpose  : 
162 //=======================================================================
163 Standard_Integer IGESConvGeom::IncreaseCurveContinuity (const Handle(Geom_BSplineCurve)& res,
164                                                         const Standard_Real epsgeom,
165                                                         const Standard_Integer continuity)
166 {
167   if (continuity < 1) return continuity;
168   Standard_Boolean isC1 = Standard_True, isC2 = Standard_True;
169   Standard_Integer degree = res->Degree();
170
171   
172   Standard_Boolean isModified;
173   do {
174     isModified = Standard_False;
175     for (Standard_Integer i = res->FirstUKnotIndex()+1; i < res->LastUKnotIndex(); i++) 
176       if(degree - res->Multiplicity(i) < continuity) {
177         if (continuity >= 2) {
178           if (!res->RemoveKnot(i, degree-2, epsgeom)) {
179             isC2 = Standard_False;
180             Standard_Boolean locOK = res->RemoveKnot(i, degree-1, epsgeom);   // is C1 ?
181             isC1 &= locOK;
182             isModified |= locOK;
183           }
184           else
185             isModified = Standard_True;
186         }
187         else {
188           Standard_Boolean locOK = res->RemoveKnot(i, degree-1, epsgeom);   // is C1 ?
189           isC1 &= locOK;
190           isModified |= locOK;
191         }
192       }
193   }
194   while (isModified);
195     
196   if (!isC1) return 0;
197   if (continuity >= 2 && !isC2) return 1;
198   return continuity;
199 }
200
201 //=======================================================================
202 //function : IncreaseCurveContinuity
203 //purpose  : 
204 //=======================================================================
205
206 Standard_Integer IGESConvGeom::IncreaseCurveContinuity (const Handle(Geom2d_BSplineCurve)& res,
207                                                         const Standard_Real epsgeom,
208                                                         const Standard_Integer continuity)
209 {
210   if (continuity < 1) return continuity;
211   Standard_Boolean isC1 = Standard_True, isC2 = Standard_True;
212   Standard_Integer degree = res->Degree();
213
214   Standard_Boolean isModified;
215   do {
216     isModified = Standard_False;
217     for (Standard_Integer i = res->FirstUKnotIndex()+1; i < res->LastUKnotIndex(); i++) 
218       if(degree - res->Multiplicity(i) < continuity) {
219         if (continuity >= 2) {
220           if (!res->RemoveKnot(i, degree-2, epsgeom)) {
221             isC2 = Standard_False;
222             Standard_Boolean locOK = res->RemoveKnot(i, degree-1, epsgeom);   // is C1 ?
223             isC1 &= locOK;
224             isModified |= locOK;
225           }
226           else
227             isModified = Standard_True;
228         }
229         else {
230           Standard_Boolean locOK = res->RemoveKnot(i, degree-1, epsgeom);   // is C1 ?
231           isC1 &= locOK;
232           isModified |= locOK;
233         }
234       }
235   }
236   while (isModified);
237
238   if (!isC1) return 0;
239   if (continuity >= 2 && !isC2) return 1;
240   return continuity;
241 }
242
243
244 //=======================================================================
245 //function : IGESConvGeom::SplineSurfaceFromIGES
246 //purpose  : 
247 //=======================================================================
248 Standard_Integer  IGESConvGeom::SplineSurfaceFromIGES
249   (const Handle(IGESGeom_SplineSurface)& st,
250    const Standard_Real /*epscoef*/,  const Standard_Real epsgeom,
251    Handle(Geom_BSplineSurface)& res)
252 {
253   Standard_Integer returned = 0;
254   Standard_Integer degree = st->BoundaryType();
255   if (degree > 3) degree = 3;
256   Standard_Integer DegreeU = degree;
257   Standard_Integer DegreeV = degree;
258   
259   Standard_Integer  NbUSeg = st->NbUSegments();  
260   Standard_Integer  NbVSeg = st->NbVSegments();  
261   
262   if ((NbUSeg < 1) || (NbVSeg < 1)) return 5;
263   
264   //  Output BSpline knots & multiplicities arraies for U & V :
265   //  =========================================================
266
267   TColStd_Array1OfReal  UKnot(1,NbUSeg+1);
268   TColStd_Array1OfReal  VKnot(1,NbVSeg+1);
269   TColStd_Array1OfReal  deltaU(1,NbUSeg);
270   TColStd_Array1OfReal  deltaV(1,NbVSeg);
271
272   Standard_Integer i; // svv Jan 10 2000 : porting on DEC
273   for (i=1; i <= NbUSeg+1; i++)
274     UKnot.SetValue(i, st->UBreakPoint(i));
275
276   for (i=1; i <= NbUSeg; i++)
277     deltaU.SetValue(i, st->UBreakPoint(i+1)- st->UBreakPoint(i));
278
279   for (i=1; i <= NbVSeg+1; i++)
280     VKnot.SetValue(i, st->VBreakPoint(i));
281
282   for (i=1; i <= NbVSeg; i++) 
283     deltaV.SetValue(i, st->VBreakPoint(i+1)- st->VBreakPoint(i));
284
285   TColStd_Array1OfInteger  UMult(1,NbUSeg+1); UMult.Init(DegreeU);
286   UMult.SetValue(UMult.Lower(),DegreeU+1);
287   UMult.SetValue(UMult.Upper(),DegreeU+1);
288
289   TColStd_Array1OfInteger  VMult(1,NbVSeg+1); VMult.Init(DegreeV);
290   VMult.SetValue(VMult.Lower(),DegreeV+1);
291   VMult.SetValue(VMult.Upper(),DegreeV+1);
292       
293   
294   //  Poles computing
295   //  ===============
296   
297   Standard_Integer  NbUPoles  =  NbUSeg * DegreeU + 1;
298   Standard_Integer  NbVPoles  =  NbVSeg * DegreeV + 1;  
299   
300   TColgp_Array2OfPnt  BsPole(1, NbUPoles, 1, NbVPoles);
301
302   Standard_Integer  iBs, jBs, iBz, jBz;
303   Standard_Boolean  wasC0 = Standard_True;
304   
305   //  Patch (1,1)
306   //  ===========
307   Standard_Integer USeg, VSeg, j;
308   USeg = 1;
309   VSeg = 1;
310   
311   Handle(TColStd_HArray1OfReal) XPoly = st->XPolynomial(USeg, VSeg);
312   Handle(TColStd_HArray1OfReal) YPoly = st->YPolynomial(USeg, VSeg);
313   Handle(TColStd_HArray1OfReal) ZPoly = st->ZPolynomial(USeg, VSeg);
314   
315   TColgp_Array2OfPnt Coef(1, DegreeU+1, 1, DegreeV+1);
316   Standard_Real ParamU, ParamV;
317   ParamU = 1.;
318   for (i=1; i<=DegreeU+1; i++) {
319     ParamV = 1.;
320     for (j=1; j<=DegreeV+1; j++) {
321       Standard_Integer PolyIndex = i + 4*(j-1);
322       gp_Pnt aPoint(XPoly->Value(PolyIndex)*ParamU*ParamV, 
323                     YPoly->Value(PolyIndex)*ParamU*ParamV, 
324                     ZPoly->Value(PolyIndex)*ParamU*ParamV);
325       Coef.SetValue(i, j, aPoint);
326       ParamV = ParamV *deltaV(VSeg);
327     }
328     ParamU = ParamU * deltaU(USeg);
329   }  
330   TColgp_Array2OfPnt BzPole(1, DegreeU+1, 1, DegreeV+1);
331   PLib::CoefficientsPoles(Coef,PLib::NoWeights2(),BzPole,PLib::NoWeights2());
332   
333   iBs = BsPole.LowerRow();
334   jBs = BsPole.LowerCol();
335   
336   //  Making output BSpline poles array :
337   for (iBz=BzPole.LowerRow(); iBz<=BzPole.UpperRow(); iBz++) {
338     for (jBz=BzPole.LowerCol(); jBz<=BzPole.UpperCol(); jBz++)
339       BsPole.SetValue(iBs, jBs++, BzPole.Value(iBz,jBz));
340     jBs = BsPole.LowerCol();
341     iBs++;
342   }
343
344
345   //  Patches (1<USeg<NbUSeg, 1)
346   //  ==========================
347   
348   VSeg = 1;
349   for (USeg=2; USeg<=NbUSeg; USeg++) {
350     XPoly = st->XPolynomial(USeg, VSeg);
351     YPoly = st->YPolynomial(USeg, VSeg);
352     ZPoly = st->ZPolynomial(USeg, VSeg);
353     ParamU = 1.;
354     for (i=Coef.LowerRow(); i<=Coef.UpperRow(); i++) {
355       ParamV = 1.;
356       for (j=Coef.LowerCol(); j<=Coef.UpperCol(); j++) {
357         Standard_Integer PolyIndex = i + 4*(j-1);
358         gp_Pnt aPoint;
359         aPoint.SetCoord(XPoly->Value(PolyIndex)*ParamU*ParamV, 
360                         YPoly->Value(PolyIndex)*ParamU*ParamV, 
361                         ZPoly->Value(PolyIndex)*ParamU*ParamV);
362         Coef.SetValue(i, j, aPoint);
363         ParamV = ParamV *deltaV(VSeg);
364       }
365       ParamU = ParamU * deltaU(USeg);
366     }
367     PLib::CoefficientsPoles(Coef,PLib::NoWeights2(),BzPole,PLib::NoWeights2());
368
369     //  C0 check and correction for poles lying on isoparametrics U=0 & V=0
370     Standard_Integer  iBsPole = BsPole.LowerRow() + (USeg-1)*DegreeU;
371     Standard_Integer  jBsPole = BsPole.LowerCol();
372     iBz = BzPole.LowerRow();
373     for (jBz=BzPole.LowerCol(); jBz<=BzPole.UpperCol(); jBz++) {
374      if (!BzPole.Value(iBz,jBz).IsEqual(BsPole.Value(iBsPole,jBsPole), epsgeom)) {
375         wasC0=Standard_False;
376         gp_Pnt MidPoint;
377         Standard_Real  XCoord = 
378           0.5 * (BzPole.Value(iBz,jBz).X() + BsPole.Value(iBsPole,jBsPole).X());
379         Standard_Real  YCoord = 
380           0.5 * (BzPole.Value(iBz,jBz).Y() + BsPole.Value(iBsPole,jBsPole).Y());
381         Standard_Real  ZCoord = 
382           0.5 * (BzPole.Value(iBz,jBz).Z() + BsPole.Value(iBsPole,jBsPole).Z());
383         MidPoint.SetCoord(XCoord, YCoord, ZCoord);
384         BsPole.SetValue(iBsPole, jBsPole++, MidPoint);
385       }
386       else {
387         BsPole.SetValue(iBsPole, jBsPole++, BzPole.Value(iBz,jBz));
388       }
389     }
390     
391     //  Other poles (no check about C0) :
392     iBsPole++;
393     jBsPole = BsPole.LowerCol();
394     for (iBz=BzPole.LowerRow()+1; iBz<=BzPole.UpperRow(); iBz++) {
395       for (jBz=BzPole.LowerCol(); jBz<=BzPole.UpperCol(); jBz++)
396         BsPole.SetValue(iBsPole, jBsPole++, BzPole.Value(iBz,jBz));
397       iBsPole++;
398       jBsPole = BsPole.LowerCol();
399     }
400   }
401       
402       
403       
404   //  Patches (1, 1<VSeg<NbVSeg)
405   //  ==========================
406   
407   USeg = 1;
408   for (VSeg=2; VSeg <= NbVSeg; VSeg++) {
409     XPoly = st->XPolynomial(USeg, VSeg);
410     YPoly = st->YPolynomial(USeg, VSeg);
411     ZPoly = st->ZPolynomial(USeg, VSeg);
412     ParamU = 1.;
413     for (i=Coef.LowerRow(); i<=Coef.UpperRow(); i++) {
414       ParamV = 1.;
415       for (j=Coef.LowerCol(); j<=Coef.UpperCol(); j++) {
416         Standard_Integer PolyIndex = i + 4*(j-1);
417         gp_Pnt aPoint;
418         aPoint.SetCoord(XPoly->Value(PolyIndex)*ParamU*ParamV, 
419                         YPoly->Value(PolyIndex)*ParamU*ParamV, 
420                         ZPoly->Value(PolyIndex)*ParamU*ParamV);
421         Coef.SetValue(i, j, aPoint);
422         ParamV = ParamV *deltaV(VSeg);
423       }
424       ParamU = ParamU * deltaU(USeg);
425     }
426     PLib::CoefficientsPoles(Coef,PLib::NoWeights2(),BzPole,PLib::NoWeights2());
427
428     //  C0 check and correction for poles lying on isoparametrics U=0 & V=0
429     iBs = BsPole.LowerRow();
430     jBs = BsPole.LowerCol() + (VSeg-1)*DegreeV;
431     jBz = BzPole.LowerCol();
432     for (iBz=BzPole.LowerRow(); iBz<=BzPole.UpperRow(); iBz++) {
433       if (!BzPole.Value(iBz,jBz).IsEqual(BsPole.Value(iBs,jBs), epsgeom)) {
434         wasC0=Standard_False;
435         gp_Pnt MidPoint;
436         Standard_Real  XCoord = 0.5 * 
437           (BzPole.Value(iBz,jBz).X() + BsPole.Value(iBs,jBs).X());
438         Standard_Real  YCoord = 0.5 * 
439           (BzPole.Value(iBz,jBz).Y() + BsPole.Value(iBs,jBs).Y());
440         Standard_Real  ZCoord = 0.5 * 
441           (BzPole.Value(iBz,jBz).Z() + BsPole.Value(iBs,jBs).Z());
442         MidPoint.SetCoord(XCoord, YCoord, ZCoord);
443         BsPole.SetValue(iBs++, jBs, MidPoint);
444       }
445       else{
446         BsPole.SetValue(iBs++, jBs, BzPole.Value(iBz,jBz));
447       }
448     }
449
450     jBs++;
451     iBs = BsPole.LowerRow();
452     for (jBz=BzPole.LowerCol()+1; jBz<=BzPole.UpperCol(); jBz++) {
453       for (iBz=BzPole.LowerRow(); iBz<=BzPole.UpperRow(); iBz++) 
454         BsPole.SetValue(iBs++, jBs, BzPole.Value(iBz,jBz));
455       iBs = BsPole.LowerRow();
456       jBs++;
457     }
458   }
459   
460   
461   //  Patches (1<USeg<NbUSeg, 1<VSeg<NbVSeg)
462   //  ======================================  
463   
464   for (VSeg=2; VSeg <= NbVSeg; VSeg++) {
465     for (USeg=2; USeg <= NbUSeg; USeg++) {
466       XPoly = st->XPolynomial(USeg, VSeg);
467       YPoly = st->YPolynomial(USeg, VSeg);
468       ZPoly = st->ZPolynomial(USeg, VSeg);
469       ParamU = 1.;
470       for (i=Coef.LowerRow(); i<=Coef.UpperRow(); i++) {
471         ParamV = 1.;
472         for (j=Coef.LowerCol(); j<=Coef.UpperCol(); j++) {
473           Standard_Integer PolyIndex = i + 4*(j-1);
474           gp_Pnt aPoint;
475           aPoint.SetCoord(XPoly->Value(PolyIndex)*ParamU*ParamV, 
476                           YPoly->Value(PolyIndex)*ParamU*ParamV, 
477                           ZPoly->Value(PolyIndex)*ParamU*ParamV);
478           Coef.SetValue(i, j, aPoint);
479           ParamV = ParamV *deltaV(VSeg);          
480         }
481         ParamU = ParamU * deltaU(USeg);
482       }
483       PLib::CoefficientsPoles(Coef,PLib::NoWeights2(),BzPole,PLib::NoWeights2());
484
485       //  C0 check and correction for poles lying on isoparametrics U=0 & V=0
486       iBs = (USeg-1)*DegreeU + BsPole.LowerRow();
487       jBs = (VSeg-1)*DegreeV + BsPole.LowerCol();
488       jBz = BzPole.LowerCol();
489       for (iBz=BzPole.LowerRow(); iBz<=BzPole.UpperRow(); iBz++) {
490         if (!BzPole.Value(iBz,jBz).IsEqual(BsPole.Value(iBs,jBs), epsgeom)) {
491           wasC0=Standard_False;
492           gp_Pnt MidPoint;
493           Standard_Real  XCoord = 0.5 * 
494             (BzPole.Value(iBz,jBz).X() + BsPole.Value(iBs,jBs).X());
495           Standard_Real  YCoord = 0.5 * 
496             (BzPole.Value(iBz,jBz).Y() + BsPole.Value(iBs,jBs).Y());
497           Standard_Real  ZCoord = 0.5 * 
498             (BzPole.Value(iBz,jBz).Z() + BsPole.Value(iBs,jBs).Z());
499           MidPoint.SetCoord(XCoord, YCoord, ZCoord);
500           BsPole.SetValue(iBs++, jBs, MidPoint);
501         }
502         else
503           BsPole.SetValue(iBs++, jBs, BzPole.Value(iBz,jBz));
504       }
505       
506       iBs = (USeg-1)*DegreeU + BsPole.LowerRow();
507       iBz = BzPole.LowerRow();
508       for (jBz=BzPole.LowerCol(); jBz<=BzPole.UpperCol(); jBz++) {
509         //  C0 check and correction for poles lying on isoparametrics U=0 & V=0
510         if (!BzPole.Value(iBz,jBz).IsEqual(BsPole.Value(iBs,jBs), epsgeom)) {
511           wasC0=Standard_False;
512           gp_Pnt MidPoint;
513           Standard_Real  XCoord = 0.5 * 
514             (BzPole.Value(iBz,jBz).X() + BsPole.Value(iBs,jBs).X());
515           Standard_Real  YCoord = 0.5 * 
516             (BzPole.Value(iBz,jBz).Y() + BsPole.Value(iBs,jBs).Y());
517           Standard_Real  ZCoord = 0.5 * 
518             (BzPole.Value(iBz,jBz).Z() + BsPole.Value(iBs,jBs).Z());
519           MidPoint.SetCoord(XCoord, YCoord, ZCoord);
520           BsPole.SetValue(iBs, jBs++, MidPoint);
521         }
522         else 
523           BsPole.SetValue(iBs, jBs++, BzPole.Value(iBz,jBz));
524       }
525
526       iBs = BsPole.LowerRow() + (USeg-1)*DegreeU + 1;
527       jBs = BsPole.LowerCol() + (VSeg-1)*DegreeV + 1;
528       for (iBz=BzPole.LowerRow()+1; iBz<=BzPole.UpperRow(); iBz++) {
529         for (jBz=BzPole.LowerCol()+1; jBz<=BzPole.UpperCol(); jBz++)
530           BsPole.SetValue(iBs, jBs++, BzPole.Value(iBz,jBz));
531         jBs = BsPole.LowerCol() + (VSeg-1)*DegreeV + 1;
532         iBs++;
533       }
534     }
535   }
536
537   //  Building result taking into account transformation if any :
538   //  ===========================================================
539
540   if (st->HasTransf()) {
541     gp_GTrsf GSplTrsf(st->CompoundLocation());
542     gp_Trsf  SplTrsf;
543     Standard_Real epsilon = 1.E-04;
544     if (IGESData_ToolLocation::ConvertLocation(epsilon,GSplTrsf,SplTrsf)) 
545       for (iBs=BsPole.LowerRow(); iBs<=BsPole.UpperRow(); iBs++) 
546         for (jBs=BsPole.LowerCol(); jBs<=BsPole.UpperCol(); jBs++) 
547           BsPole.SetValue(iBs, jBs, BsPole.Value(iBs,jBs).Transformed(SplTrsf));
548 //    else
549 //      AddWarning(start, "Transformation skipped : Not a similarity");
550   }
551
552   res = new Geom_BSplineSurface
553     (BsPole, UKnot, VKnot, UMult, VMult, DegreeU, DegreeV);
554   if (wasC0) returned += 1;
555   return returned;
556 }
557
558
559 //=======================================================================
560 //function : IGESConvGeom::IncreaseSurfaceContinuity
561 //purpose  : 
562 //=======================================================================
563 Standard_Integer IGESConvGeom::IncreaseSurfaceContinuity  (const Handle(Geom_BSplineSurface)& res,
564                                                            const Standard_Real epsgeom,
565                                                            const Standard_Integer continuity)
566 {
567   if (continuity < 1) return continuity;
568   Standard_Boolean isC1 = Standard_True, isC2 = Standard_True;
569   Standard_Integer DegreeU = res->UDegree();
570   
571   Standard_Boolean isModified;
572   do {
573     isModified = Standard_False;
574     for (Standard_Integer i = res->FirstUKnotIndex()+1; i < res->LastUKnotIndex(); i++) 
575       if(DegreeU - res->UMultiplicity(i) < continuity) {
576         if (continuity >= 2) {
577           if (!res->RemoveUKnot(i, DegreeU-2, epsgeom)) {
578             isC2 = Standard_False;
579             Standard_Boolean locOK = res->RemoveUKnot(i, DegreeU-1, epsgeom);   // is C1 ?
580             isC1 &= locOK;
581             isModified |= locOK;
582           }
583           else
584             isModified = Standard_True;
585         }
586         else {
587           Standard_Boolean locOK = res->RemoveUKnot(i, DegreeU-1, epsgeom);   // is C1 ?
588           isC1 &= locOK;
589           isModified |= locOK;
590         }
591       }
592   }
593   while (isModified);
594   
595   Standard_Integer DegreeV = res->VDegree();
596   do {
597     isModified = Standard_False;
598     for (Standard_Integer i = res->FirstVKnotIndex()+1; i < res->LastVKnotIndex(); i++) 
599       if(DegreeV - res->VMultiplicity(i) < continuity) {
600         if (continuity >= 2) {
601           if (!res->RemoveVKnot(i, DegreeV-2, epsgeom)) {
602             isC2 = Standard_False;
603             Standard_Boolean locOK = res->RemoveVKnot(i, DegreeV-1, epsgeom);   // is C1 ?
604             isC1 &= locOK;
605             isModified |= locOK;
606           }
607           else
608             isModified = Standard_True;
609         }
610         else {
611           Standard_Boolean locOK = res->RemoveVKnot(i, DegreeV-1, epsgeom);   // is C1 ?
612           isC1 &= locOK;
613           isModified |= locOK;
614         }
615       }
616   }
617   while (isModified);
618     
619   /*
620   while (--i > j) {                                      // from 2 to NbKnots-1
621     if (continuity >= 2) {
622       if (!res->RemoveUKnot(i, DegreeU-2, epsgeom)) {    // is C2 ?
623         isC2 = Standard_False;
624         isC1 &= res->RemoveUKnot(i, DegreeU-1, epsgeom); // is C1 ?
625       }
626     }
627     else {
628       isC1 &= res->RemoveUKnot(i, DegreeU-1, epsgeom); // is C1 ?
629     }
630   }
631
632   i = res->LastVKnotIndex();   //knots.Upper();
633   j = res->FirstVKnotIndex();  //knots.Lower();
634   Standard_Integer DegreeV = res->VDegree();
635   while (--i > j) {                                      // from 2 to NbKnots-1
636     if (continuity >= 2) {
637       if (!res->RemoveVKnot(i, DegreeV-2, epsgeom)) {    // is C2 ?
638         isC2 = Standard_False;
639         isC1 &= res->RemoveVKnot(i, DegreeV-1, epsgeom); // is C1 ?
640       }
641     }
642     else {
643       isC1 &= res->RemoveVKnot(i, DegreeV-1, epsgeom); // is C1 ?
644     }
645   }*/
646   
647   
648   if (!isC1) return 0;
649   if (continuity >= 2 && !isC2) return 1;
650   return continuity;
651 }
652