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