0031939: Coding - correction of spelling errors in comments [part 4]
[occt.git] / src / IGESToBRep / IGESToBRep_BasicSurface.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 //=======================================================================
15 //modified: 
16 //:k0 abv 16.12.98: eliminating existing code
17 // 21.12.98 rln, gka S4054
18 //:k5 abv 25 Dec 98: PRO8803 1901: extending method of fixing Multi > Degree
19 // 28.12.98 dce S3767 New messaging system
20 //#61 rln 05.01.99
21 //:l1 abv 06.01.99: USA60022.igs 243: fixing missing seam on closed surface 
22 //:p6 abv 26.02.99: improve messages after call to ConvertToPeriodic
23 //#75 rln 11.03.99: using message mechanism for periodic B-Spline
24 //S4181 pdn 15.04.99 implementing of reading IGES elementary surfaces.
25 //sln 29.12.2001 OCC90 : Method checkBSplineSurfaceStatus and varification of creation of bspline surfaces were added
26 //=======================================================================
27
28 #include <Geom_BSplineSurface.hxx>
29 #include <Geom_ConicalSurface.hxx>
30 #include <Geom_CylindricalSurface.hxx>
31 #include <Geom_Plane.hxx>
32 #include <Geom_SphericalSurface.hxx>
33 #include <Geom_Surface.hxx>
34 #include <Geom_ToroidalSurface.hxx>
35 #include <gp_Ax3.hxx>
36 #include <gp_Cylinder.hxx>
37 #include <gp_GTrsf.hxx>
38 #include <gp_Pln.hxx>
39 #include <gp_Trsf.hxx>
40 #include <IGESConvGeom.hxx>
41 #include <IGESData_IGESEntity.hxx>
42 #include <IGESData_IGESModel.hxx>
43 #include <IGESData_ToolLocation.hxx>
44 #include <IGESGeom_BSplineSurface.hxx>
45 #include <IGESGeom_Direction.hxx>
46 #include <IGESGeom_Point.hxx>
47 #include <IGESGeom_SplineSurface.hxx>
48 #include <IGESSolid_ConicalSurface.hxx>
49 #include <IGESSolid_CylindricalSurface.hxx>
50 #include <IGESSolid_PlaneSurface.hxx>
51 #include <IGESSolid_SphericalSurface.hxx>
52 #include <IGESSolid_ToroidalSurface.hxx>
53 #include <IGESToBRep.hxx>
54 #include <IGESToBRep_BasicSurface.hxx>
55 #include <IGESToBRep_CurveAndSurface.hxx>
56 #include <Interface_Macros.hxx>
57 #include <Message_Msg.hxx>
58 #include <Precision.hxx>
59 #include <ShapeAlgo.hxx>
60 #include <ShapeAlgo_AlgoContainer.hxx>
61 #include <ShapeConstruct_Curve.hxx>
62 #include <Standard_ErrorHandler.hxx>
63 #include <Standard_Failure.hxx>
64 #include <TColgp_Array2OfPnt.hxx>
65 #include <TColgp_HArray2OfPnt.hxx>
66 #include <TColStd_Array1OfInteger.hxx>
67 #include <TColStd_Array1OfReal.hxx>
68 #include <TColStd_Array2OfReal.hxx>
69 #include <TColStd_HArray1OfReal.hxx>
70 #include <TColStd_SequenceOfInteger.hxx>
71
72 //:36
73 //S3767
74 //S4181
75 //=======================================================================
76 //function : CheckBSplineSurface
77 //purpose  : Check coincidede knots. Check whether knots are in ascending 
78 //           order and difference between vaues of weights more than 1000. 
79 //           Send corresponding messages. The function returns Standard_False 
80 //           if surface can not be created, Standard_True otherwise.
81 //=======================================================================
82 static Standard_Boolean checkBSplineSurface(IGESToBRep_BasicSurface*             theSurface,
83                                           const Handle(IGESGeom_BSplineSurface)& theBSplineSurface,
84                                           TColStd_Array1OfReal&                  SUKnots,
85                                           TColStd_Array1OfReal&                  SVKnots,
86                                           const TColStd_Array2OfReal&            SWeights)
87 {
88   // check whether difference between vaues of weights more than 1000.
89   if(!theBSplineSurface->IsPolynomial()) {
90     Standard_Real aMinValue = SWeights.Value(SWeights.LowerRow(), SWeights.LowerCol());
91     Standard_Real aMaxValue = SWeights.Value(SWeights.LowerRow(), SWeights.LowerCol());
92     for(Standard_Integer i = SWeights.LowerRow(); i<= SWeights.UpperRow(); i++)
93     for(Standard_Integer j = SWeights.LowerCol(); j<= SWeights.UpperCol(); j++) {
94       if(SWeights.Value(i,j) < aMinValue) aMinValue = SWeights.Value(i,j);
95       if(SWeights.Value(i,j) > aMaxValue) aMaxValue = SWeights.Value(i,j);    
96
97       if(aMaxValue - aMinValue > 1000) {
98         Message_Msg msg1374("IGES_1374"); // WARNING - Difference between weights is too big.
99         theSurface->SendWarning(theBSplineSurface, msg1374);
100       }
101     }
102   }
103  
104   Standard_Boolean aResult = Standard_True;
105   
106   //check whether knots are in ascending order.
107   Standard_Boolean aWrongOrder = Standard_False;
108   Standard_Integer i;
109   for (i = SUKnots.Lower(); (i < SUKnots.Upper()) && (!aWrongOrder); i++) 
110     if(SUKnots.Value (i+1) < SUKnots.Value (i)) aWrongOrder = Standard_True;
111   for (i = SVKnots.Lower(); (i < SVKnots.Upper()) && (!aWrongOrder); i++) 
112     if(SVKnots.Value (i+1) < SVKnots.Value (i)) aWrongOrder = Standard_True;
113   
114   if(aWrongOrder) { 
115     Message_Msg msg1373("IGES_1373"); // FAIL - Knots are not in ascending order 
116     theSurface->SendFail(theBSplineSurface, msg1373);
117     aResult = Standard_False;
118   }
119
120   //Fix coincided knots
121   if(aResult) {
122     ShapeConstruct_Curve::FixKnots(SUKnots);
123     ShapeConstruct_Curve::FixKnots(SVKnots);
124   }
125   
126   return aResult;
127
128 }
129
130
131 //=======================================================================
132 //function : IGESToBRep_BasicSurface
133 //purpose  : 
134 //=======================================================================
135
136 IGESToBRep_BasicSurface::IGESToBRep_BasicSurface()
137      :IGESToBRep_CurveAndSurface()
138 {  
139   SetModeTransfer(Standard_False);
140 }
141
142 //=======================================================================
143 //function : IGESToBRep_BasicSurface
144 //purpose  : 
145 //=======================================================================
146
147 IGESToBRep_BasicSurface::IGESToBRep_BasicSurface
148   (const IGESToBRep_CurveAndSurface& CS)
149      :IGESToBRep_CurveAndSurface(CS)
150 {  
151 }
152
153 //=======================================================================
154 //function : IGESToBRep_BasicSurface
155 //purpose  : 
156 //=======================================================================
157
158 IGESToBRep_BasicSurface::IGESToBRep_BasicSurface
159   (const Standard_Real    eps,
160    const Standard_Real    epsCoeff,
161    const Standard_Real    epsGeom,
162    const Standard_Boolean mode,
163    const Standard_Boolean modeapprox,
164    const Standard_Boolean optimized)
165      :IGESToBRep_CurveAndSurface(eps, epsCoeff, epsGeom, mode, modeapprox,
166                                  optimized)
167 {  
168 }
169
170
171 //=============================================
172 //Function : TransferBasicSurface
173 //Purpose : Choice of the right transfer method
174 //=============================================
175
176 Handle(Geom_Surface) IGESToBRep_BasicSurface::TransferBasicSurface
177        (const Handle(IGESData_IGESEntity)& start)
178
179   Handle(Geom_Surface) resurf;
180   if (start.IsNull()) {
181     Message_Msg msg1005("IGES_1005");
182     SendFail(start, msg1005);
183     return resurf;
184   }
185
186   try { //:36 by abv 11.12.97: Geom_BSplineSurface raiss if some weights <0
187     OCC_CATCH_SIGNALS
188     
189     //S4054
190     if (start->IsKind(STANDARD_TYPE(IGESGeom_BSplineSurface))) {
191       DeclareAndCast(IGESGeom_BSplineSurface, st128, start);
192       resurf = TransferBSplineSurface(st128);
193     }
194     else if (start->IsKind(STANDARD_TYPE(IGESGeom_SplineSurface))) {
195       DeclareAndCast(IGESGeom_SplineSurface, st114, start);
196       resurf = TransferSplineSurface(st114);
197     } //S4181 pdn 15.04.99  implementing of reading IGES elementary surfaces.
198     else if (start->IsKind(STANDARD_TYPE(IGESSolid_PlaneSurface))) {
199       DeclareAndCast(IGESSolid_PlaneSurface, st190, start);
200       resurf = TransferPlaneSurface(st190);
201     }
202     else if (start->IsKind(STANDARD_TYPE(IGESSolid_CylindricalSurface))) {
203       DeclareAndCast(IGESSolid_CylindricalSurface, st192, start);
204       resurf = TransferRigthCylindricalSurface(st192);
205     }
206     else if (start->IsKind(STANDARD_TYPE(IGESSolid_ConicalSurface))) {
207       DeclareAndCast(IGESSolid_ConicalSurface, st194, start);
208       resurf = TransferRigthConicalSurface(st194);
209     }
210     else if (start->IsKind(STANDARD_TYPE(IGESSolid_SphericalSurface))) {
211       DeclareAndCast(IGESSolid_SphericalSurface, st196, start);
212       resurf = TransferSphericalSurface(st196);
213     }
214     else if (start->IsKind(STANDARD_TYPE(IGESSolid_ToroidalSurface))) {
215       DeclareAndCast(IGESSolid_ToroidalSurface, st198, start);
216       resurf = TransferToroidalSurface(st198);
217     }
218     else {
219      // AddFail(start, "Spline or BSpline surface expected for TransferBasicSurface");
220       return resurf;
221     }
222
223   } //:36
224   catch(Standard_Failure const& anException) {
225 #ifdef OCCT_DEBUG
226     std::cout << "\n** Exception in IGESToBRep_BasicSurface::TransferBasicSurface : "; 
227     anException.Print(std::cout);
228 #endif
229     (void)anException;
230   }
231
232   if (resurf.IsNull()) {
233     // AddFail(start,"The IGESEntity cannot be transferred");
234   }
235   else
236     resurf->Scale(gp_Pnt(0,0,0),GetUnitFactor());
237
238   return resurf;
239 }
240
241
242 //=======================================================================
243 //function : TransferPlaneSurface
244 //purpose  : 
245 //=======================================================================
246
247 Handle(Geom_Plane) IGESToBRep_BasicSurface::TransferPlaneSurface(const Handle(IGESSolid_PlaneSurface)& start)
248 {
249   Handle(Geom_Plane) res;
250   if (start.IsNull()) {
251     Message_Msg msg1005("IGES_1005");
252     SendFail(start, msg1005);
253     return res;
254   }
255   
256   gp_Pln pln;
257   Standard_Boolean Param = start->IsParametrised();
258   Handle(IGESGeom_Point) Point = start->LocationPoint();
259   Handle(IGESGeom_Direction) Dir = start->Normal();
260
261   if (Point.IsNull()) {
262     Message_Msg msg174("XSTEP_174");   
263     SendFail(start, msg174);
264     // Point Reading Error : Null IGESEntity
265     return res;
266   }
267   if (Dir.IsNull()) {
268     Message_Msg msg1280("IGES_1280");
269     SendFail(start, msg1280);
270     // Direction Reading Error : Null IGESEntity
271     return res;
272   } 
273
274   gp_Pnt Pt = Point->Value();
275   gp_Dir Normale = gp_Dir(Dir->Value());
276   if (!Param) {
277     pln = gp_Pln(Pt,Normale);
278   }
279   else {
280     Handle(IGESGeom_Direction) refdir = start->ReferenceDir();
281     gp_Dir Dirgp = gp_Dir(refdir->Value());
282     pln = gp_Pln( gp_Ax3(Pt, Normale, Dirgp));  
283   }
284   
285   return new Geom_Plane(pln); 
286 }
287
288 //=======================================================================
289 //function : TransferRigthCylindricalSurface
290 //purpose  : 
291 //=======================================================================
292
293 Handle(Geom_CylindricalSurface) IGESToBRep_BasicSurface::TransferRigthCylindricalSurface
294        (const Handle(IGESSolid_CylindricalSurface)& start)
295 {
296   Handle(Geom_CylindricalSurface) res;
297   if (start.IsNull()) {
298     Message_Msg msg1005("IGES_1005");
299     SendFail(start, msg1005);
300     return res;
301   }
302   
303   Standard_Boolean Param = start->IsParametrised();
304   Handle(IGESGeom_Point) Point = start->LocationPoint();
305   Handle(IGESGeom_Direction) Axis = start->Axis();
306   Standard_Real radius = start->Radius();
307   
308   if (Point.IsNull()) {
309     Message_Msg msg174("XSTEP_174");   
310     SendFail(start, msg174);
311     // Point Reading Error : Null IGESEntity
312     return res;
313   }
314   if (Axis.IsNull()) {
315     Message_Msg msg1280("IGES_1280");
316     SendFail(start, msg1280);
317     // Direction Reading Error : Null IGESEntity
318     return res;
319   }
320   if (radius < Precision::Confusion()) {
321     return res;
322   }
323     
324   gp_Pnt Pt = Point->Value();
325   gp_Dir ax = gp_Dir(Axis->Value());
326   gp_Ax3 ax3;
327   if (!Param) 
328     ax3 = gp_Ax3(Pt,ax);
329   else {
330     Handle(IGESGeom_Direction) refdir = start->ReferenceDir();
331     gp_Dir Dir = gp_Dir(refdir->Value());
332     gp_Dir vc = Dir^ax;
333     if(vc.XYZ().Modulus() < Precision::Confusion()) {
334       
335       return res;
336     }
337     ax3 = gp_Ax3(Pt,ax,Dir);
338   }
339   gp_Cylinder cyl(ax3,radius);
340   return new Geom_CylindricalSurface(cyl);
341 }
342
343 //=======================================================================
344 //function : TransferRigthConicalSurface
345 //purpose  : 
346 //=======================================================================
347
348 Handle(Geom_ConicalSurface) IGESToBRep_BasicSurface::TransferRigthConicalSurface
349        (const Handle(IGESSolid_ConicalSurface)& start)
350 {
351   Handle(Geom_ConicalSurface) res;
352   if (start.IsNull()) {
353     Message_Msg msg1005("IGES_1005");
354     SendFail(start, msg1005);
355     return res;
356   } 
357   
358   Standard_Boolean Param = start->IsParametrised();
359   Handle(IGESGeom_Point) Point = start->LocationPoint();
360   Handle(IGESGeom_Direction) Axis = start->Axis();
361   Standard_Real radius = start->Radius();
362   Standard_Real angle  = start->SemiAngle()/180.*M_PI;
363   
364   if (Point.IsNull()) {
365     Message_Msg msg174("XSTEP_174");   
366     SendFail(start, msg174);
367     // Point Reading Error : Null IGESEntity
368     return res;
369   }
370   if (Axis.IsNull()) {
371     Message_Msg msg1280("IGES_1280");
372     SendFail(start, msg1280);
373     // Direction Reading Error : Null IGESEntity
374     return res;
375   }
376   if (angle < Precision::Confusion()||angle > M_PI/2.) {
377     return res;
378   }
379   if (radius < 0) {
380     return res;
381   }
382   if (radius < Precision::Confusion())
383     radius = 0.;
384   
385   gp_Pnt Pt = Point->Value();
386   gp_Dir ax = gp_Dir(Axis->Value());
387   gp_Ax3 ax3;
388   if (!Param) 
389     ax3 = gp_Ax3(Pt,ax);
390   else {
391     Handle(IGESGeom_Direction) refdir = start->ReferenceDir();
392     gp_Dir Dir = gp_Dir(refdir->Value());
393     gp_Dir vc = Dir^ax;
394     if(vc.XYZ().Modulus() < Precision::Confusion()) {
395       
396       return res;
397     }
398     ax3 = gp_Ax3(Pt,ax,Dir);
399   }
400   return new Geom_ConicalSurface(ax3,angle,radius);
401 }
402
403 //=======================================================================
404 //function : TransferSphericalSurface
405 //purpose  : 
406 //=======================================================================
407
408 Handle(Geom_SphericalSurface) IGESToBRep_BasicSurface::TransferSphericalSurface
409        (const Handle(IGESSolid_SphericalSurface)& start)
410 {
411   Handle(Geom_SphericalSurface) res;
412   if (start.IsNull()) {
413     Message_Msg msg1005("IGES_1005");
414     SendFail(start, msg1005);
415     return res;
416   } 
417   
418   Standard_Boolean Param = start->IsParametrised();
419   Handle(IGESGeom_Point) Point = start->Center();
420   Handle(IGESGeom_Direction) Axis = start->Axis();
421   Standard_Real radius = start->Radius();
422   
423   if (Point.IsNull()) {
424     Message_Msg msg174("XSTEP_174");   
425     SendFail(start, msg174);
426     // Point Reading Error : Null IGESEntity
427     return res;
428   }
429   if (Axis.IsNull()) {
430     Message_Msg msg1280("IGES_1280");
431     SendFail(start, msg1280);
432     // Direction Reading Error : Null IGESEntity
433     return res;
434   }
435   if (radius < Precision::Confusion()){
436    
437     return res;
438   }
439
440   gp_Pnt Pt = Point->Value();
441   gp_Dir ax = gp_Dir(Axis->Value());
442   gp_Ax3 ax3;
443   if (!Param) 
444     ax3 = gp_Ax3(Pt,ax);
445   else {
446     Handle(IGESGeom_Direction) refdir = start->ReferenceDir();
447     gp_Dir Dir = gp_Dir(refdir->Value());
448     gp_Dir vc = Dir^ax;
449     if(vc.XYZ().Modulus() < Precision::Confusion()) {
450       
451       return res;
452     }
453     ax3 = gp_Ax3(Pt,ax,Dir);
454   }
455   return new Geom_SphericalSurface(ax3,radius); 
456 }
457
458 //=======================================================================
459 //function : TransferToroidalSurface
460 //purpose  : 
461 //=======================================================================
462
463 Handle(Geom_ToroidalSurface) IGESToBRep_BasicSurface::TransferToroidalSurface
464        (const Handle(IGESSolid_ToroidalSurface)& start)
465 {
466   Handle(Geom_ToroidalSurface) res;
467   if (start.IsNull()) {
468     Message_Msg msg1005("IGES_1005");
469     SendFail(start, msg1005);
470     return res;
471   } 
472   
473   Standard_Boolean Param = start->IsParametrised();
474   Handle(IGESGeom_Point) Point = start->Center();
475   Handle(IGESGeom_Direction) Axis = start->Axis();
476   Standard_Real major = start->MajorRadius();
477   Standard_Real minor = start->MinorRadius();
478   
479   if (Point.IsNull()) {
480     Message_Msg msg174("XSTEP_174");   
481     SendFail(start, msg174);
482     // Point Reading Error : Null IGESEntity
483     return res;
484   }
485   if (Axis.IsNull()) {
486     Message_Msg msg1280("IGES_1280");
487     SendFail(start, msg1280);
488     // Direction Reading Error : Null IGESEntity
489     return res;
490   }
491   if (major < Precision::Confusion()||minor < Precision::Confusion()){
492    
493     return res;
494   }
495
496   gp_Pnt Pt = Point->Value();
497   gp_Dir ax = gp_Dir(Axis->Value());
498   gp_Ax3 ax3;
499   if (!Param) 
500     ax3 = gp_Ax3(Pt,ax);
501   else {
502     Handle(IGESGeom_Direction) refdir = start->ReferenceDir();
503     gp_Dir Dir = gp_Dir(refdir->Value());
504     gp_Dir vc = Dir^ax;
505     if(vc.XYZ().Modulus() < Precision::Confusion()) {
506       
507       return res;
508     }
509     ax3 = gp_Ax3(Pt,ax,Dir);
510   }
511   return new Geom_ToroidalSurface(ax3,major,minor);
512 }
513 //==================================
514 //Function : TransferSplineSurface :
515 //Purpose :
516 //==================================
517
518 Handle(Geom_BSplineSurface) IGESToBRep_BasicSurface::TransferSplineSurface
519        (const Handle(IGESGeom_SplineSurface)& start)
520
521   Handle(Geom_BSplineSurface) resconv;
522   if (start.IsNull()) {
523     Message_Msg msg1005("IGES_1005");
524     SendFail(start, msg1005);
525     return resconv;
526   }
527
528   Standard_Real epscoef = GetEpsCoeff();
529   Standard_Real epsgeom = GetEpsGeom();
530
531   Standard_Integer result = IGESConvGeom::SplineSurfaceFromIGES
532     (start, epscoef, epsgeom, resconv);
533
534   switch (result) {
535   case 5 : {
536     Message_Msg msg1305("IGES_1305");
537     SendFail (start, msg1305); // less than on segment in U or V (no result produced)
538     return resconv;
539   }
540   case 4 : {
541     Message_Msg msg1190("IGES_1190");
542     SendFail (start, msg1190);
543     return resconv;
544   }
545     // case 3 :
546     // AddWarning ( start, "Degree is not compatible with code boundary type , C0 is not guaranteed)");
547     //case 2 :
548     // AddWarning ( start, "Degree is not compatible with code boundary type , C0 is guaranteed)");
549   default :
550       break;
551   }
552   
553   
554   //  Checking C2 and C1 continuity :  case 1 :
555   //  AddWarning ( start, "The result is not guaranteed to be C0");
556   //  ===============================
557
558   IGESConvGeom::IncreaseSurfaceContinuity (resconv, epsgeom, GetContinuity());
559   return resconv;
560 }
561
562 //===================================
563 //Function : TransferBSplineSurface :
564 //Purpose : 
565 //===================================
566
567 Handle(Geom_BSplineSurface)  IGESToBRep_BasicSurface::TransferBSplineSurface
568        (const Handle(IGESGeom_BSplineSurface)& start)
569
570   Handle(Geom_BSplineSurface)  res;
571   if (start.IsNull()) {
572     Message_Msg msg1005("IGES_1005");
573     SendFail(start, msg1005);
574     return res;
575   }
576
577   Standard_Integer  DegreeU = start->DegreeU();
578   Standard_Integer  DegreeV = start->DegreeV();
579   if ((DegreeU <= 0)  ||  (DegreeU > Geom_BSplineSurface::MaxDegree()) ||
580       (DegreeV <= 0)  ||  (DegreeV > Geom_BSplineSurface::MaxDegree())) {
581     Message_Msg msg1310("IGES_1310");
582     SendFail ( start, msg1310);
583     // Improper Input BSpline Degree
584     return res;
585   }
586   
587   //  Filling poles array :
588   //  =====================
589   
590   Standard_Integer  NbPolesU = start->NbPolesU();
591   Standard_Integer  newNbPolesU = NbPolesU;
592   if (NbPolesU<2) {
593     Message_Msg msg1195("IGES_1195");
594     SendFail(start, msg1195);
595     // Number of poles lower than 2 following U
596     return res;
597   }
598   
599   Standard_Integer  NbPolesV = start->NbPolesV();
600   Standard_Integer  newNbPolesV = NbPolesV;
601   if (NbPolesV<2) {
602     Message_Msg msg1195("IGES_1195");
603     SendFail(start, msg1195);
604     return res;
605   }
606   
607   TColgp_Array2OfPnt  Pole(1, NbPolesU, 1, NbPolesV);
608   Standard_Integer             UIndex = Pole.LowerRow();
609   Standard_Integer             VIndex = Pole.LowerCol();
610   Standard_Integer             i, j; //szv#4:S4163:12Mar99 k unused
611   
612   if (!GetModeTransfer() && start->HasTransf()) 
613     for (i=0; i <= start->UpperIndexU(); i++) {
614       for (j=0; j <= start->UpperIndexV(); j++) 
615         Pole.SetValue(UIndex, VIndex++, start->TransformedPole(i,j));
616       UIndex++;
617       VIndex = Pole.LowerCol();
618     }
619   else
620     for (i=0; i <= start->UpperIndexU(); i++) {
621       for (j=0; j <= start->UpperIndexV(); j++) 
622         Pole.SetValue(UIndex, VIndex++, start->Pole(i,j));
623       UIndex++;
624       VIndex = Pole.LowerCol();
625     }
626   
627   
628   //  KNOTS & MULTIPLICITIES for U :
629   //  ==============================
630   
631   Standard_Integer           NbUKnots = start->NbKnotsU();
632   TColStd_Array1OfReal       TempUKnot(1, NbUKnots);
633   TColStd_Array1OfInteger    TempUMult(1, NbUKnots);
634   TempUMult.Init(1);
635
636   UIndex = TempUKnot.Lower();
637   
638   
639   //  If several identical IGES knots are encountered, corresponding 
640   //  multiplicity is increased
641   //  ==============================================================
642   
643   TempUKnot.SetValue(UIndex, start->KnotU(-DegreeU));
644   
645   for (i = 1-DegreeU; i < NbUKnots-DegreeU; i++) {
646
647     Standard_Real  UKnot1 = start->KnotU(i);
648     Standard_Real  UKnot2 = start->KnotU(i-1);
649
650     if (Abs(UKnot1 - UKnot2) <= Epsilon(UKnot2))
651       TempUMult.SetValue(UIndex, TempUMult.Value(UIndex) + 1);
652     else 
653       TempUKnot.SetValue(++UIndex, UKnot1);
654   }
655   
656   //  Final knots & multiplicities arraies are dimensionned so as to be fully 
657   //  filled :
658   //  =======================================================================
659   
660   TColStd_Array1OfReal     UKnot(1,UIndex);
661   TColStd_Array1OfInteger  UMult(1,UIndex);
662   
663   Standard_Integer SumOfUMult = 0;
664
665   TColStd_SequenceOfInteger SeqIndexU;
666   Standard_Integer DelIndexU;
667   Standard_Integer OldSumOfUMult = 0;
668   for (i=1 ; i <= UIndex; i++) { //:k5 abv 25 Dec 98: cycle modified
669     Standard_Integer aMult = TempUMult.Value(i);
670     Standard_Integer maxMult = ( i==1 || i == UIndex ? DegreeU + 1 : DegreeU );
671     if (aMult > maxMult) {
672       Message_Msg msg1200("IGES_1200");
673       msg1200.Arg("U");
674       msg1200.Arg("U");
675       msg1200.Arg("U");//#61 rln 05.01.99
676       SendWarning(start, msg1200); //U Multiplicity > DegreeU (or Degree+1 at end); corrected
677       for ( DelIndexU = OldSumOfUMult + 1; aMult > maxMult; DelIndexU++, aMult-- ) {
678         newNbPolesU--;
679         SeqIndexU.Append(DelIndexU);
680       }
681     }
682     OldSumOfUMult += TempUMult.Value(i); 
683     UKnot.SetValue(i, TempUKnot.Value(i));
684     UMult.SetValue(i, aMult);
685     SumOfUMult += aMult;
686   }
687
688   if (SumOfUMult != newNbPolesU + DegreeU + 1) {
689     Message_Msg msg1210("IGES_1210");
690     msg1210.Arg("U");
691     msg1210.Arg("U");
692     SendWarning(start, msg1210);
693     // Sum of multiplicities following U is not equal to the sum : Count of poles + DegreeU + 1
694   }
695   
696   //  KNOTS & MULTIPLICITIES for V :
697   //  ==============================
698   
699   Standard_Integer         NbVKnots = start->NbKnotsV();
700   TColStd_Array1OfReal     TempVKnot(1, NbVKnots);
701   TColStd_Array1OfInteger  TempVMult(1, NbVKnots);
702   TempVMult.Init(1);
703   
704   VIndex = TempVKnot.Lower();
705   
706
707   //  If several identical IGES knots are encountered, corresponding 
708   //  multiplicity is increased
709   //  ==============================================================  
710   
711   TempVKnot.SetValue(VIndex, start->KnotV(-DegreeV));
712   
713   for (i = 1-DegreeV; i < NbVKnots-DegreeV; i++) {
714
715     Standard_Real  VKnot1 = start->KnotV(i);
716     Standard_Real  VKnot2 = start->KnotV(i-1);
717
718     if (Abs(VKnot1 - VKnot2) <= Epsilon(VKnot2))
719       TempVMult.SetValue(VIndex, TempVMult.Value(VIndex) + 1);
720     else 
721       TempVKnot.SetValue(++VIndex, VKnot1);
722   }
723   
724   //  Final knots & multiplicities arraies are dimensionned so as to be fully 
725   //  filled :
726   //  =======================================================================
727   
728   TColStd_Array1OfReal     VKnot(1,VIndex);
729   TColStd_Array1OfInteger  VMult(1,VIndex);
730   
731   Standard_Integer SumOfVMult = 0;
732    
733   TColStd_SequenceOfInteger SeqIndexV;
734   Standard_Integer DelIndexV;
735   Standard_Integer OldSumOfVMult = 0;
736   for (i=1; i <= VIndex; i++) { //:k5 abv 25 Dec 98: cycle modified
737     Standard_Integer aMult = TempVMult.Value(i);
738     Standard_Integer maxMult = ( i==1 || i == VIndex ? DegreeV + 1 : DegreeV );
739     if (aMult > maxMult) {
740       Message_Msg msg1200("IGES_1200");//#61 rln 05.01.99
741       msg1200.Arg("V");
742       msg1200.Arg("V");
743       msg1200.Arg("V");
744       SendWarning(start, msg1200);
745       //V Multiplicity > DegreeV (or Degree+1 at end); corrected
746       for ( DelIndexV = OldSumOfVMult + 1; aMult > maxMult; DelIndexV++, aMult-- ) {
747         newNbPolesV--;
748         SeqIndexV.Append(DelIndexV);
749       }
750     }
751     OldSumOfVMult += TempVMult.Value(i); 
752     VKnot.SetValue(i, TempVKnot.Value(i));
753     VMult.SetValue(i, aMult);
754     SumOfVMult += aMult;
755   }  
756
757   if (SumOfVMult != newNbPolesV + DegreeV + 1)  {
758     Message_Msg msg1210("IGES_1210");
759     msg1210.Arg("V");
760     msg1210.Arg("V");
761     SendWarning(start, msg1210); 
762     // Sum of multiplicities following V is not equal to the sum : Count of poles + Degree V + 1
763   }
764   
765   // Mise a jour du tableau des poles
766   TColgp_Array2OfPnt  Poles(1, newNbPolesU, 1, newNbPolesV);
767   TColStd_SequenceOfInteger PoleUInd;
768   TColStd_SequenceOfInteger PoleVInd;
769   for (i=1; i<=NbPolesU; i++) PoleUInd.Append(i);
770   for (i=1; i<=NbPolesV; i++) PoleVInd.Append(i);
771   UIndex = Poles.LowerRow();
772   VIndex = Poles.LowerCol();
773
774   if (( newNbPolesU < NbPolesU) || (newNbPolesV < NbPolesV)) {
775     if ( newNbPolesU < NbPolesU) {
776       Standard_Integer Offset = 0;
777       for (Standard_Integer itab = 1; itab <= SeqIndexU.Length(); itab++) {
778         DelIndexU = SeqIndexU.Value(itab) - Offset;
779         PoleUInd.Remove(DelIndexU);
780         Offset++;
781       }
782     }
783     if ( newNbPolesV < NbPolesV) {
784       Standard_Integer Offset = 0;
785       for (Standard_Integer itab = 1; itab <= SeqIndexV.Length(); itab++) {
786         DelIndexV = SeqIndexV.Value(itab) - Offset;
787         PoleVInd.Remove(DelIndexV);
788         Offset++;
789       }
790     }
791     Standard_Integer nbUseq = PoleUInd.Length();
792     Standard_Integer nbVseq = PoleVInd.Length();
793     if (( nbUseq == newNbPolesU)&&(nbVseq == newNbPolesV)) {
794       for ( i=1; i<= newNbPolesU; i++) {
795         for (j=1; j<= newNbPolesV; j++) 
796           Poles.SetValue(UIndex,VIndex++ , Pole.Value(PoleUInd.Value(i),
797                                                       PoleVInd.Value(j)));
798         UIndex++;
799         VIndex = Poles.LowerCol();
800       }
801     }
802     else {
803        Message_Msg msg1175("IGES_1175");
804        SendWarning(start, msg1175);
805     }
806   }
807
808   else {
809     for ( i=1; i<= newNbPolesU; i++) {
810       for (j=1; j<= newNbPolesV; j++) 
811         Poles.SetValue (UIndex, VIndex++,Pole.Value(i,j));
812       UIndex++;
813       VIndex = Poles.LowerCol();
814     }
815   }
816     
817
818   //  Building result taking into account transformation if any :
819   //  ===========================================================
820
821   if (!GetModeTransfer() && start->HasTransf()) {
822     gp_GTrsf GBSplTrsf(start->CompoundLocation());
823     gp_Trsf  BSplTrsf;
824     if (IGESData_ToolLocation::ConvertLocation(GetEpsilon(),GBSplTrsf,BSplTrsf)) 
825       for (i=Poles.LowerRow(); i<=Poles.UpperRow(); i++) 
826         for (j=Poles.LowerCol(); j<=Poles.UpperCol(); j++) 
827           Poles.SetValue(i, j, Poles.Value(i,j).Transformed(BSplTrsf));
828     else {   
829       Message_Msg msg1035("IGES_1035");
830       SendWarning(start, msg1035);
831     }
832   }
833   
834   
835   //  CREATION with the ARRAY of POLES WEIGHTS if any :
836   //  =================================================
837   
838     if (start->IsPolynomial()) 
839     {
840       //sln 29.12.2001 OCC90 : If surface can not be created do nothing
841       TColStd_Array2OfReal  Weight(1, 1, 1, 1);
842       if(!checkBSplineSurface(this, start, UKnot, VKnot, Weight)) return res;
843       res = new Geom_BSplineSurface(Poles, UKnot, VKnot, UMult, VMult, 
844                                     DegreeU, DegreeV);
845     }
846
847     else {
848       TColStd_Array2OfReal  PoleWeight(1, NbPolesU, 1, NbPolesV);
849       Standard_Boolean      polynomial          =  Standard_True;
850       Standard_Real         WeightReference     =  start->Weight(0,0);
851       Standard_Integer      WeightRow           =  PoleWeight.LowerRow();
852       Standard_Integer      WeightCol           =  PoleWeight.LowerCol();
853       
854       for (i=0; i <= start->UpperIndexU(); i++) {
855         for (j=0; j <= start->UpperIndexV(); j++) {
856           polynomial = (Abs(start->Weight(i,j) - WeightReference) 
857                         <= Epsilon(WeightReference)) && polynomial;
858           //:39 by abv 15.12.97
859           Standard_Real weight = start->Weight(i,j);
860           if ( weight < Precision::PConfusion() ) {
861             Message_Msg msg1215("IGES_1215");
862             SendFail (start, msg1215); // Some weights are not positive.
863             return res;
864           }
865           PoleWeight.SetValue(WeightRow, WeightCol++, weight);
866 //:39     PoleWeight.SetValue(WeightRow, WeightCol++, start->Weight(i,j));
867         }
868         WeightRow++;
869         WeightCol = PoleWeight.LowerCol();
870       }
871       if (polynomial) {
872         Message_Msg msg1220("IGES_1220");
873         const Standard_CString surface ("surface");      
874         msg1220.Arg(surface);
875         SendWarning(start, msg1220);
876      }
877       // Mise a jour du tableau des Weight lors de la correction de la multiplicite
878       TColStd_Array2OfReal Weight(1, newNbPolesU, 1, newNbPolesV);
879       UIndex = Weight.LowerRow();
880       VIndex = Weight.LowerCol();
881       if (( newNbPolesU < NbPolesU) || (newNbPolesV < NbPolesV)) {
882         //Standard_Integer indj = 1; //szv#4:S4163:12Mar99 unused
883         for ( i=1; i<= newNbPolesU; i++) {
884           for (j=1; j<= newNbPolesV; j++) 
885             Weight.SetValue(UIndex, VIndex++ , 
886                             PoleWeight.Value(PoleUInd.Value(i),PoleVInd.Value(j)));
887           UIndex++;
888           VIndex = Poles.LowerCol();
889         }
890       }
891       else {
892         for ( i=1; i<= newNbPolesU; i++) {
893           for (j=1; j<= newNbPolesV; j++) 
894             Weight.SetValue(UIndex, VIndex++ ,PoleWeight.Value(i,j));
895           UIndex++;
896           VIndex = Poles.LowerCol();
897         }
898       }
899
900       //sln 29.12.2001 OCC90 : If surface can not be created do nothing
901       if(!checkBSplineSurface(this, start, UKnot, VKnot, Weight)) return res;
902       res = new Geom_BSplineSurface
903         (Poles, Weight, UKnot, VKnot, UMult, VMult, DegreeU, DegreeV);
904     }
905   
906
907   //  Checking C2 and C1 continuity :
908   //  ===============================
909   
910   Standard_Integer icont = GetContinuity();
911   //Standard_Boolean isC1 = Standard_True, isC2 = Standard_True; //szv#4:S4163:12Mar99 not needed
912
913   i = res->LastUKnotIndex();
914   Standard_Integer FirstIndex = res->FirstUKnotIndex();
915   while (--i >= FirstIndex+1) {
916     if (icont >=2) {
917       if(!res->RemoveUKnot(i, DegreeU-2, GetEpsGeom())) {
918         //isC2 = Standard_False; //szv#4:S4163:12Mar99 not needed
919         res->RemoveUKnot(i, DegreeU-1, GetEpsGeom()); //szv#4:S4163:12Mar99 `isC1=` not needed
920       }
921       else
922         res->RemoveUKnot(i, DegreeU-1, GetEpsGeom()); //szv#4:S4163:12Mar99 `isC1=` not needed
923     }
924   }
925
926   i = res->LastVKnotIndex();
927   FirstIndex = res->FirstVKnotIndex();
928   while (--i >= FirstIndex+1) {
929     if (icont >=2) {
930       if(!res->RemoveVKnot(i, DegreeV-2, GetEpsGeom())) {
931         //isC2 = Standard_False; //szv#4:S4163:12Mar99 not needed
932         res->RemoveVKnot(i, DegreeV-1, GetEpsGeom()); //szv#4:S4163:12Mar99 `isC1=` not needed
933       }
934       else
935         res->RemoveVKnot(i, DegreeV-1, GetEpsGeom()); //szv#4:S4163:12Mar99 `isC1=` not needed
936     }
937   }
938
939   //:h7 abv 14 Jul 98: ims010.igs 2519: closed periodic surface should be forced
940   // else some wires which can lie over the seam will be incorrect
941   //:l1 abv 6 Jan 99: USA60022 243: force periodicity on any closed surface
942   Standard_Boolean isUPeriodic = ( start->IsClosedU() && ( start->IsPeriodicU() ||
943                                                            res->IsUClosed() ) );
944   Standard_Boolean isVPeriodic = ( start->IsClosedV() && ( start->IsPeriodicV() ||
945                                                            res->IsVClosed() ) );
946   //:k0 abv 16 Dec 98: use ShapeCustom 
947   if ( isUPeriodic || isVPeriodic ) {
948     Handle(Geom_BSplineSurface) periodicSurf =
949       Handle(Geom_BSplineSurface)::DownCast ( ShapeAlgo::AlgoContainer()->ConvertToPeriodic (res) );
950     if ( ! periodicSurf.IsNull() ) { //:p6 abv 26 Feb 99: && periodicSurf != res ) {
951       //#75 rln 11.03.99: using message mechanism
952       Message_Msg msg1221("IGES_1221");
953       SendWarning(start, msg1221);//SendWarning(start,"Surface forced to be periodic");
954       res = periodicSurf;
955     }
956   }
957   return res;
958 }
959
960
961
962
963 //=======================================================================
964 //function : DeletePoleRow
965 //purpose  : 
966 //=======================================================================
967 //szv#4:S4163:12Mar99 function never referenced
968 /*
969 static void DeletePoleRow
970   (const TColgp_Array2OfPnt& Poles,
971    const Standard_Integer    Index,
972          TColgp_Array2OfPnt& NewPoles)
973 {
974   Standard_Integer Offset = 0;
975   Standard_Integer ColIndex;
976   Standard_Integer RowIndex = NewPoles.LowerRow();
977   while (RowIndex <= NewPoles.UpperRow()) {
978     ColIndex = NewPoles.LowerCol();
979     if (RowIndex == Index)  Offset = 1;
980     while (ColIndex <= NewPoles.UpperCol()){
981       NewPoles (RowIndex, ColIndex) = Poles (RowIndex + Offset, ColIndex);
982       ColIndex++;
983     }
984     RowIndex++;
985   }
986 }
987 */
988
989 //=======================================================================
990 //function : DeletePoleCol
991 //purpose  : 
992 //=======================================================================
993 //szv#4:S4163:12Mar99 function never referenced
994 /*
995 static void DeletePoleCol
996   (const TColgp_Array2OfPnt& Poles,
997    const Standard_Integer    Index,
998          TColgp_Array2OfPnt& NewPoles)
999 {
1000   Standard_Integer Offset = 0;
1001   Standard_Integer RowIndex;
1002   Standard_Integer ColIndex = NewPoles.LowerCol();
1003   while (ColIndex <= NewPoles.UpperCol()) {
1004     RowIndex = NewPoles.LowerRow();
1005     if (ColIndex == Index)  Offset = 1;
1006     while (RowIndex <= NewPoles.UpperRow()){
1007       NewPoles (RowIndex, ColIndex) = Poles (RowIndex, ColIndex + Offset);
1008       RowIndex++;
1009     }
1010     ColIndex++;
1011   }
1012 }
1013 */
1014