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