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