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