0029915: Porting to VC 2017 : Regressions in Modeling Algorithms on VC 2017
[occt.git] / src / GeomConvert / GeomConvert.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 // Jean-Claude Vauthier Novembre 1991
16 // Passage sur C1 Aout 1992 et ajout transformation Bezier->BSpline + Debug
17 // Modif JCV correction bug le 2/08/1993
18
19 #include <BSplCLib.hxx>
20 #include <Convert_CircleToBSplineCurve.hxx>
21 #include <Convert_ConicToBSplineCurve.hxx>
22 #include <Convert_EllipseToBSplineCurve.hxx>
23 #include <Convert_HyperbolaToBSplineCurve.hxx>
24 #include <Convert_ParabolaToBSplineCurve.hxx>
25 #include <ElCLib.hxx>
26 #include <Geom2d_BSplineCurve.hxx>
27 #include <Geom_BezierCurve.hxx>
28 #include <Geom_BSplineCurve.hxx>
29 #include <Geom_BSplineSurface.hxx>
30 #include <Geom_Circle.hxx>
31 #include <Geom_Conic.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_Ellipse.hxx>
34 #include <Geom_Geometry.hxx>
35 #include <Geom_Hyperbola.hxx>
36 #include <Geom_Line.hxx>
37 #include <Geom_OffsetCurve.hxx>
38 #include <Geom_Parabola.hxx>
39 #include <Geom_Surface.hxx>
40 #include <Geom_TrimmedCurve.hxx>
41 #include <GeomConvert.hxx>
42 #include <GeomConvert_ApproxCurve.hxx>
43 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
44 #include <GeomLProp.hxx>
45 #include <gp.hxx>
46 #include <gp_Ax3.hxx>
47 #include <gp_Circ2d.hxx>
48 #include <gp_Elips2d.hxx>
49 #include <gp_Hypr2d.hxx>
50 #include <gp_Lin.hxx>
51 #include <gp_Parab2d.hxx>
52 #include <gp_Pnt.hxx>
53 #include <gp_Pnt2d.hxx>
54 #include <gp_Trsf.hxx>
55 #include <gp_Vec.hxx>
56 #include <Hermit.hxx>
57 #include <PLib.hxx>
58 #include <Precision.hxx>
59 #include <Standard_ConstructionError.hxx>
60 #include <Standard_DomainError.hxx>
61 #include <TColGeom_Array1OfCurve.hxx>
62 #include <TColgp_Array1OfPnt.hxx>
63 #include <TColgp_Array1OfPnt2d.hxx>
64 #include <TColStd_Array1OfBoolean.hxx>
65 #include <TColStd_Array1OfInteger.hxx>
66 #include <TColStd_Array1OfReal.hxx>
67 #include <TColStd_HArray1OfInteger.hxx>
68 #include <TColStd_HArray1OfReal.hxx>
69
70 //=======================================================================
71 //function : BSplineCurveBuilder
72 //purpose  : 
73 //=======================================================================
74 static Handle(Geom_BSplineCurve) BSplineCurveBuilder 
75        (const Handle(Geom_Conic)&          TheConic,
76         const Convert_ConicToBSplineCurve& Convert) 
77
78 {
79   Handle(Geom_BSplineCurve) TheCurve;
80   Standard_Integer NbPoles = Convert.NbPoles();
81   Standard_Integer NbKnots = Convert.NbKnots();
82   TColgp_Array1OfPnt      Poles   (1, NbPoles);
83   TColStd_Array1OfReal    Weights (1, NbPoles);
84   TColStd_Array1OfReal    Knots   (1, NbKnots);
85   TColStd_Array1OfInteger Mults   (1, NbKnots);
86   Standard_Integer i;
87   gp_Pnt2d P2d;
88   gp_Pnt   P3d;
89   for (i = 1; i <= NbPoles; i++) {
90     P2d = Convert.Pole (i);
91     P3d.SetCoord (P2d.X(), P2d.Y(), 0.0);
92     Poles (i) = P3d;
93     Weights (i) = Convert.Weight (i);         
94   }
95   for (i = 1; i <= NbKnots; i++) {
96     Knots (i) = Convert.Knot (i);
97     Mults (i) = Convert.Multiplicity (i);
98   }
99   TheCurve = 
100     new Geom_BSplineCurve (Poles, Weights, Knots, Mults, 
101                            Convert.Degree(), Convert.IsPeriodic());
102   gp_Trsf T;
103   T.SetTransformation (TheConic->Position(), gp::XOY());
104   Handle(Geom_BSplineCurve) Cres;
105   Cres = Handle(Geom_BSplineCurve)::DownCast(TheCurve->Transformed (T));
106   return Cres;
107 }
108
109
110
111 //=======================================================================
112 //function : SplitBSplineCurve
113 //purpose  : 
114 //=======================================================================
115
116 Handle(Geom_BSplineCurve) GeomConvert::SplitBSplineCurve 
117   (const Handle(Geom_BSplineCurve)& C,
118    const Standard_Integer               FromK1, 
119    const Standard_Integer               ToK2,
120    const Standard_Boolean               SameOrientation) 
121 {
122   Standard_Integer TheFirst = C->FirstUKnotIndex ();
123   Standard_Integer TheLast  = C->LastUKnotIndex ();
124   if (FromK1 == ToK2)  throw Standard_DomainError();
125   Standard_Integer FirstK = Min (FromK1, ToK2);
126   Standard_Integer LastK  = Max (FromK1, ToK2);
127   if (FirstK < TheFirst || LastK > TheLast) throw Standard_DomainError();
128
129   Handle(Geom_BSplineCurve) C1
130     = Handle(Geom_BSplineCurve)::DownCast(C->Copy ());
131
132   C1->Segment( C->Knot(FirstK),C->Knot(LastK));
133
134   if (C->IsPeriodic()) {
135     if (!SameOrientation) C1->Reverse();
136   }
137   else {
138     if (FromK1 > ToK2)    C1->Reverse();
139   }
140   return C1;
141 }
142
143
144 //=======================================================================
145 //function : SplitBSplineCurve
146 //purpose  : 
147 //=======================================================================
148
149 Handle(Geom_BSplineCurve) GeomConvert::SplitBSplineCurve 
150   (const Handle(Geom_BSplineCurve)& C, 
151    const Standard_Real              FromU1, 
152    const Standard_Real              ToU2,
153    const Standard_Real              , //ParametricTolerance,
154    const Standard_Boolean            SameOrientation    ) 
155 {
156   Standard_Real FirstU = Min( FromU1, ToU2);
157   Standard_Real LastU  = Max( FromU1, ToU2);
158
159   Handle (Geom_BSplineCurve) C1 
160     = Handle(Geom_BSplineCurve)::DownCast(C->Copy());
161
162   C1->Segment(FirstU, LastU);
163
164   if (C->IsPeriodic()) {
165      if (!SameOrientation) C1->Reverse();
166    }
167   else {
168     if (FromU1 > ToU2)    C1->Reverse();
169   }
170
171   return C1;
172 }
173
174
175
176
177 //=======================================================================
178 //function : CurveToBSplineCurve
179 //purpose  : 
180 //=======================================================================
181
182 Handle(Geom_BSplineCurve)  GeomConvert::CurveToBSplineCurve 
183   (const Handle(Geom_Curve)&          C,
184    const Convert_ParameterisationType Parameterisation) 
185 {
186   Handle (Geom_BSplineCurve) TheCurve;
187
188   if (C->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
189     Handle(Geom_Curve) Curv;
190     Handle(Geom_TrimmedCurve) Ctrim = Handle(Geom_TrimmedCurve)::DownCast(C);
191     Curv = Ctrim->BasisCurve();
192     Standard_Real U1 = Ctrim->FirstParameter();
193     Standard_Real U2 = Ctrim->LastParameter();
194
195     // Si la courbe n'est pas vraiment restreinte, on ne risque pas 
196     // le Raise dans le BS->Segment.
197     if (!Curv->IsPeriodic()) {
198       if (U1 < Curv->FirstParameter())
199         U1 =  Curv->FirstParameter();
200       if (U2 > Curv->LastParameter())
201         U2 = Curv->LastParameter();
202     }
203
204     if (Curv->IsKind(STANDARD_TYPE(Geom_Line))) {
205        gp_Pnt Pdeb = Ctrim->StartPoint();
206        gp_Pnt Pfin = Ctrim->EndPoint();
207        TColgp_Array1OfPnt Poles (1, 2);
208        Poles (1) = Pdeb;
209        Poles (2) = Pfin;
210        TColStd_Array1OfReal Knots (1, 2);
211        Knots (1) = Ctrim->FirstParameter ();
212        Knots (2) = Ctrim->LastParameter  ();
213        TColStd_Array1OfInteger Mults (1, 2);
214        Mults (1) = 2;
215        Mults (2) = 2;
216        Standard_Integer Degree = 1;
217        TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
218     }
219
220     else if (Curv->IsKind(STANDARD_TYPE(Geom_Circle))) {
221       Handle(Geom_Circle) TheConic = Handle(Geom_Circle)::DownCast(Curv);
222       gp_Circ2d C2d (gp::OX2d(), TheConic->Radius());
223       if(Parameterisation != Convert_RationalC1) {
224         Convert_CircleToBSplineCurve Convert (C2d,
225                                               U1, 
226                                               U2, 
227                                               Parameterisation);
228         TheCurve = BSplineCurveBuilder (TheConic, Convert);
229       }
230       else {
231         if(U2 - U1 < 6.) {
232           Convert_CircleToBSplineCurve Convert (C2d,
233                                                 U1, 
234                                                 U2, 
235                                                 Parameterisation);
236           TheCurve = BSplineCurveBuilder (TheConic, Convert);
237         }
238         else { // split circle to avoide numerical 
239                // overflow when U2 - U1 =~ 2*PI
240
241           Standard_Real Umed = (U1 + U2) * .5;
242           Convert_CircleToBSplineCurve Convert1 (C2d, 
243                                                  U1, 
244                                                  Umed, 
245                                                  Parameterisation);
246
247           Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
248
249           Convert_CircleToBSplineCurve Convert2 (C2d, 
250                                                  Umed, 
251                                                  U2, 
252                                                  Parameterisation);
253
254           Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
255
256           GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
257                                                       Parameterisation);
258
259           CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
260
261           
262           TheCurve = CCTBSpl.BSplineCurve();
263         }
264       }
265
266     }
267
268     else if (Curv->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
269       Handle(Geom_Ellipse) TheConic = Handle(Geom_Ellipse)::DownCast(Curv);
270       gp_Elips2d E2d (gp::OX2d(),
271                       TheConic->MajorRadius(),
272                       TheConic->MinorRadius());
273       if(Parameterisation != Convert_RationalC1) {
274         Convert_EllipseToBSplineCurve Convert (E2d, 
275                                                U1, 
276                                                U2,
277                                                Parameterisation);
278         TheCurve = BSplineCurveBuilder (TheConic, Convert);
279       }
280       else {
281         if(U2 - U1 < 6.) {
282           Convert_EllipseToBSplineCurve Convert (E2d, 
283                                                  U1, 
284                                                  U2,
285                                                  Parameterisation);
286           TheCurve = BSplineCurveBuilder (TheConic, Convert);
287         }       
288         else { // split ellipse to avoide numerical 
289                // overflow when U2 - U1 =~ 2*PI
290
291           Standard_Real Umed = (U1 + U2) * .5;
292           Convert_EllipseToBSplineCurve Convert1 (E2d, 
293                                                   U1, 
294                                                   Umed, 
295                                                   Parameterisation);
296
297           Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
298
299           Convert_EllipseToBSplineCurve Convert2 (E2d, 
300                                                 Umed, 
301                                                 U2, 
302                                                 Parameterisation);
303
304           Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
305
306           GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
307                                                       Parameterisation);
308
309           CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
310
311           
312           TheCurve = CCTBSpl.BSplineCurve();
313         }
314       }
315     }
316
317     else if (Curv->IsKind(STANDARD_TYPE(Geom_Hyperbola))) {
318       Handle(Geom_Hyperbola) TheConic = Handle(Geom_Hyperbola)::DownCast(Curv);
319       gp_Hypr2d H2d (gp::OX2d(), 
320                      TheConic->MajorRadius(), TheConic->MinorRadius());
321       Convert_HyperbolaToBSplineCurve Convert (H2d, U1, U2);
322       TheCurve = BSplineCurveBuilder (TheConic, Convert);
323     }
324
325     else if (Curv->IsKind(STANDARD_TYPE(Geom_Parabola))) {
326       Handle(Geom_Parabola) TheConic = Handle(Geom_Parabola)::DownCast(Curv);
327       gp_Parab2d Prb2d (gp::OX2d(), TheConic->Focal());
328       Convert_ParabolaToBSplineCurve Convert (Prb2d, U1, U2);
329       TheCurve = BSplineCurveBuilder (TheConic, Convert);
330     }
331
332     else if (Curv->IsKind (STANDARD_TYPE(Geom_BezierCurve))) {
333  
334       Handle(Geom_BezierCurve) CBez 
335         = Handle(Geom_BezierCurve)::DownCast(Curv->Copy());
336       CBez->Segment (U1, U2);
337       Standard_Integer NbPoles = CBez->NbPoles();
338       Standard_Integer Degree  = CBez->Degree();
339       TColgp_Array1OfPnt     Poles   (1, NbPoles);
340       TColStd_Array1OfReal    Knots   (1, 2);
341       TColStd_Array1OfInteger Mults   (1, 2);
342       Knots (1) = 0.0;
343       Knots (2) = 1.0;
344       Mults (1) = Degree + 1;
345       Mults (2) = Degree + 1;
346       CBez->Poles (Poles);
347       if (CBez->IsRational()) {    
348         TColStd_Array1OfReal    Weights (1, NbPoles);
349         CBez->Weights (Weights);
350         TheCurve = 
351           new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree);
352       }
353       else {
354         TheCurve = 
355           new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
356       }
357     }
358     else if (Curv->IsKind (STANDARD_TYPE(Geom_BSplineCurve))) {
359       TheCurve = Handle(Geom_BSplineCurve)::DownCast(Curv->Copy());
360       //// modified by jgv, 14.01.05 for OCC7355 ////
361       if (TheCurve->IsPeriodic())
362         {
363           Standard_Real Uf = TheCurve->FirstParameter();
364           Standard_Real Ul = TheCurve->LastParameter();
365           ElCLib::AdjustPeriodic( Uf, Ul, Precision::Confusion(), U1, U2 );
366           if (Abs(U1 - Uf) <= Precision::Confusion() &&
367               Abs(U2 - Ul) <= Precision::Confusion())
368             TheCurve->SetNotPeriodic();
369         }
370       ///////////////////////////////////////////////
371       TheCurve->Segment(U1,U2);
372     }
373     else if (Curv->IsKind (STANDARD_TYPE(Geom_OffsetCurve))) {
374      Standard_Real Tol3d = 1.e-4;
375      GeomAbs_Shape Order = GeomAbs_C2;
376      Standard_Integer MaxSegments = 16, MaxDegree = 14; 
377      GeomConvert_ApproxCurve ApprCOffs(C, Tol3d, Order, 
378                                          MaxSegments, MaxDegree);
379      if (ApprCOffs.HasResult())
380        TheCurve = ApprCOffs.Curve();
381      else  throw Standard_ConstructionError();
382     }
383     else { throw Standard_DomainError("No such curve"); }
384   }
385
386   else { 
387     if (C->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
388       Handle(Geom_Ellipse) TheConic= Handle(Geom_Ellipse)::DownCast(C);
389       gp_Elips2d E2d (gp::OX2d(), 
390                       TheConic->MajorRadius(), TheConic->MinorRadius());
391 /*      if (Parameterisation == Convert_TgtThetaOver2_1 ||
392           Parameterisation == Convert_TgtThetaOver2_2) {
393         throw Standard_DomainError(); }
394  
395       else if ( Parameterisation == Convert_QuasiAngular) {
396         Convert_EllipseToBSplineCurve Convert (E2d,
397                                                0.0e0,
398                                                2.0e0 * M_PI,
399                                                Parameterisation);
400
401         TheCurve = BSplineCurveBuilder (TheConic, Convert);
402         TheCurve->SetPeriodic();
403       }
404       else {*/
405         Convert_EllipseToBSplineCurve Convert (E2d,
406                                               Parameterisation);
407         TheCurve = BSplineCurveBuilder (TheConic, Convert);
408         TheCurve->SetPeriodic(); // pour polynomial et quasi angular
409 //      }
410     }
411     
412     else if (C->IsKind(STANDARD_TYPE(Geom_Circle))) {
413       Handle(Geom_Circle) TheConic = Handle(Geom_Circle)::DownCast(C);
414       gp_Circ2d C2d (gp::OX2d(), TheConic->Radius());
415 /*      if (Parameterisation == Convert_TgtThetaOver2_1 ||
416           Parameterisation == Convert_TgtThetaOver2_2) {
417         throw Standard_DomainError(); }
418  
419       else if ( Parameterisation == Convert_QuasiAngular) {
420         Convert_CircleToBSplineCurve Convert (C2d,
421                                               0.0e0,
422                                               2.0e0 * M_PI,
423                                               Parameterisation);
424         
425         TheCurve = BSplineCurveBuilder (TheConic, Convert);                                  
426       }
427       else {*/
428         Convert_CircleToBSplineCurve Convert (C2d,
429                                               Parameterisation);
430         TheCurve = BSplineCurveBuilder (TheConic, Convert);
431         TheCurve->SetPeriodic();
432 //      }
433     }
434     
435     else if (C->IsKind (STANDARD_TYPE(Geom_BezierCurve))) {
436       Handle(Geom_BezierCurve) CBez= Handle(Geom_BezierCurve)::DownCast(C);
437       Standard_Integer NbPoles = CBez->NbPoles();
438       Standard_Integer Degree  = CBez->Degree();
439       TColgp_Array1OfPnt     Poles   (1, NbPoles);
440       TColStd_Array1OfReal    Knots   (1, 2);
441       TColStd_Array1OfInteger Mults   (1, 2);
442       Knots (1) = 0.0;
443       Knots (2) = 1.0;
444       Mults (1) = Degree + 1;
445       Mults (2) = Degree + 1;
446       CBez->Poles (Poles);
447       if (CBez->IsRational()) {    
448         TColStd_Array1OfReal    Weights (1, NbPoles);
449         CBez->Weights (Weights);
450         TheCurve = 
451           new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree);
452       }
453       else {
454         TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
455       }
456     }
457     
458     else if (C->IsKind (STANDARD_TYPE(Geom_BSplineCurve))) {
459       TheCurve = Handle(Geom_BSplineCurve)::DownCast(C->Copy());
460     }
461
462     else if (C->IsKind (STANDARD_TYPE(Geom_OffsetCurve))) {
463      Standard_Real Tol3d = 1.e-4;
464      GeomAbs_Shape Order = GeomAbs_C2;
465      Standard_Integer MaxSegments = 16, MaxDegree = 14; 
466      GeomConvert_ApproxCurve ApprCOffs(C, Tol3d, Order, 
467                                          MaxSegments, MaxDegree);
468      if (ApprCOffs.HasResult())
469        TheCurve = ApprCOffs.Curve();
470      else  throw Standard_ConstructionError();
471    }
472     else { throw Standard_DomainError("No such curve"); }
473   }
474   
475   return TheCurve;
476 }
477
478
479 //=======================================================================
480 //class : law_evaluator
481 //purpose  : usefull to estimate the value of a function
482 //=======================================================================
483
484 class GeomConvert_law_evaluator : public BSplCLib_EvaluatorFunction
485 {
486
487 public:
488
489   GeomConvert_law_evaluator (const Handle(Geom2d_BSplineCurve)& theAncore)
490   : myAncore (theAncore) {}
491
492   virtual void Evaluate (const Standard_Integer theDerivativeRequest,
493                          const Standard_Real*   theStartEnd,
494                          const Standard_Real    theParameter,
495                          Standard_Real&         theResult,
496                          Standard_Integer&      theErrorCode) const
497   {
498     theErrorCode = 0;
499     if (!myAncore.IsNull() &&
500         theParameter >= theStartEnd[0] &&
501         theParameter <= theStartEnd[1] && 
502         theDerivativeRequest == 0)
503     {
504       gp_Pnt2d aPoint;
505       myAncore->D0 (theParameter, aPoint);
506       theResult = aPoint.Coord(2);
507     }    
508     else 
509       theErrorCode = 1;
510   }
511
512 private:
513
514   Handle(Geom2d_BSplineCurve) myAncore;
515
516 };
517
518 //=======================================================================
519 //function : MultNumandDenom
520 //purpose  : Multiply two BSpline curves to make one
521 //=======================================================================
522
523
524 static Handle(Geom_BSplineCurve) MultNumandDenom(const Handle(Geom2d_BSplineCurve)& a ,
525                                                  const Handle(Geom_BSplineCurve)&   BS )
526      
527 { TColStd_Array1OfReal               aKnots(1,a->NbKnots());
528   TColStd_Array1OfReal               BSKnots(1,BS->NbKnots());
529   TColStd_Array1OfReal               BSFlatKnots(1,BS->NbPoles()+BS->Degree()+1);
530   TColStd_Array1OfReal               BSWeights(1,BS->NbPoles()); 
531   TColStd_Array1OfInteger            aMults(1,a->NbKnots());
532   TColStd_Array1OfInteger            BSMults(1,BS->NbKnots());
533   TColgp_Array1OfPnt2d               aPoles(1,a->NbPoles());
534   TColgp_Array1OfPnt                 BSPoles(1,BS->NbPoles());
535   Handle(Geom_BSplineCurve)          res;
536   Handle(TColStd_HArray1OfReal)      resKnots;
537   Handle(TColStd_HArray1OfInteger)   resMults; 
538   Standard_Real                      start_value,end_value;
539   Standard_Real                      tolerance=Precision::PConfusion();
540   Standard_Integer                   resNbPoles,degree,
541                                      ii,jj,
542                                      aStatus;
543   
544   BS->Knots(BSKnots);            //storage of the two BSpline 
545   BS->Multiplicities(BSMults);   //features
546   BS->Poles(BSPoles);
547   BS->Weights(BSWeights);
548   BS->KnotSequence(BSFlatKnots);
549   start_value = BSKnots(1);
550   end_value = BSKnots(BS->NbKnots());
551   if ((end_value - start_value)/5 < tolerance) 
552     tolerance = (end_value - start_value)/5;
553
554   a->Knots(aKnots);
555   a->Poles(aPoles);
556   a->Multiplicities(aMults);
557   BSplCLib::Reparametrize(BS->FirstParameter(),BS->LastParameter(),aKnots);
558   Handle(Geom2d_BSplineCurve) anAncore = new Geom2d_BSplineCurve (aPoles, aKnots, aMults, a->Degree());
559
560   BSplCLib::MergeBSplineKnots(tolerance,start_value,end_value, //merge of the knots
561                               a->Degree(),aKnots,aMults,
562                               BS->Degree(),BSKnots,BSMults,
563                               resNbPoles,resKnots,resMults);
564   degree=BS->Degree()+a->Degree();
565   TColgp_Array1OfPnt resNumPoles(1,resNbPoles);
566   TColStd_Array1OfReal resDenPoles(1,resNbPoles);
567   TColgp_Array1OfPnt resPoles(1,resNbPoles);
568   TColStd_Array1OfReal resFlatKnots(1,resNbPoles+degree+1);
569   BSplCLib::KnotSequence(resKnots->Array1(),resMults->Array1(),resFlatKnots);
570   for (ii=1;ii<=BS->NbPoles();ii++)
571     for (jj=1;jj<=3;jj++)
572       BSPoles(ii).SetCoord(jj,BSPoles(ii).Coord(jj)*BSWeights(ii));
573 //POP pour WNT
574   GeomConvert_law_evaluator ev (anAncore);
575
576   BSplCLib::FunctionMultiply(ev,                             
577                              BS->Degree(),
578                              BSFlatKnots,
579                              BSPoles,
580                              resFlatKnots,
581                              degree,
582                              resNumPoles,
583                              aStatus);
584
585   BSplCLib::FunctionMultiply(ev,
586                              BS->Degree(),
587                              BSFlatKnots,
588                              BSWeights,
589                              resFlatKnots,
590                              degree,
591                              resDenPoles,
592                              aStatus);
593   for (ii=1;ii<=resNbPoles;ii++)
594     for(jj=1;jj<=3;jj++) 
595       resPoles(ii).SetCoord(jj,resNumPoles(ii).Coord(jj)/resDenPoles(ii));
596   res = new Geom_BSplineCurve(resPoles,resDenPoles,resKnots->Array1(),resMults->Array1(),degree);
597   return res;
598 }
599
600 //=======================================================================
601 //function : Pretreatment 
602 //purpose  : Put the two first and two last weigths at one if they are 
603 //           equal
604 //=======================================================================
605
606 static void Pretreatment(TColGeom_Array1OfBSplineCurve& tab)
607
608 {Standard_Integer i,j;
609  Standard_Real a;
610
611  for (i=0;i<=(tab.Length()-1);i++){
612    if (tab(i)->IsRational()) {
613      a=tab(i)->Weight(1);                                 
614      if ((tab(i)->Weight(2)==a)&&
615          (tab(i)->Weight(tab(i)->NbPoles()-1)==a)&&
616          (tab(i)->Weight(tab(i)->NbPoles())==a))
617        
618        for (j=1;j<=tab(i)->NbPoles();j++)
619          tab(i)->SetWeight(j,tab(i)->Weight(j)/a);
620    }
621  }
622 }
623          
624 //=======================================================================
625 //function : NeedToBeTreated
626 //purpose  : Say if the BSpline is rationnal and if the two first and two
627 //           last weigths are different
628 //=======================================================================    
629
630 static Standard_Boolean NeedToBeTreated(const Handle(Geom_BSplineCurve)& BS)
631
632 {
633   TColStd_Array1OfReal  tabWeights(1,BS->NbPoles());
634   if (BS->IsRational()) {
635     BS->Weights(tabWeights);
636     if ((BSplCLib::IsRational(tabWeights,1,BS->NbPoles()))&&
637         ((BS->Weight(1)<(1-Precision::Confusion()))||
638          (BS->Weight(1)>(1+Precision::Confusion()))||
639          (BS->Weight(2)<(1-Precision::Confusion()))||
640          (BS->Weight(2)>(1+Precision::Confusion()))||
641          (BS->Weight(BS->NbPoles()-1)<(1-Precision::Confusion()))||
642          (BS->Weight(BS->NbPoles()-1)>(1+Precision::Confusion()))||
643          (BS->Weight(BS->NbPoles())<(1-Precision::Confusion()))||
644          (BS->Weight(BS->NbPoles())>(1+Precision::Confusion()))))
645       return Standard_True;
646     else
647       return Standard_False;
648   }
649   else 
650     return Standard_False ;
651  
652 }
653
654 //=======================================================================
655 //function : Need2DegRepara
656 //purpose  : in the case of wire closed G1 it says if you will to use a 
657 //           two degree reparametrisation to close it C1
658 //=======================================================================
659
660 static Standard_Boolean Need2DegRepara(const TColGeom_Array1OfBSplineCurve& tab)
661
662 {Standard_Integer        i;
663  gp_Vec                  Vec1,Vec2;
664  gp_Pnt                  Pint;
665  Standard_Real           Rapport=1.0e0;
666
667  for (i=0;i<=tab.Length()-2;i++){
668    tab(i+1)->D1(tab(i+1)->FirstParameter(),Pint,Vec1);
669    tab(i)->D1(tab(i)->LastParameter(),Pint,Vec2);
670    Rapport=Rapport*Vec2.Magnitude()/Vec1.Magnitude();
671  }
672  if ((Rapport<=(1.0e0+Precision::Confusion()))&&(Rapport>=(1.0e0-Precision::Confusion())))
673    return Standard_False;
674  else
675    return Standard_True;
676 }
677
678 //=======================================================================
679 //function : Indexmin
680 //purpose  : Give the index of the curve which has the lowest degree
681 //=======================================================================
682
683 static Standard_Integer Indexmin(const TColGeom_Array1OfBSplineCurve& tab)
684 {
685   Standard_Integer i = 0, index = 0, degree = 0;
686   
687   degree=tab(0)->Degree();
688   for (i=0;i<=tab.Length()-1;i++)
689     if (tab(i)->Degree()<=degree){
690       degree=tab(i)->Degree();
691       index=i;
692     }
693   return index;
694 }
695
696 //=======================================================================
697 //function : NewTabClosedG1
698 //purpose  : Sort the array of BSplines to start at the nb_vertex_group0 index
699 //=======================================================================
700
701 static void ReorderArrayOfG1Curves(TColGeom_Array1OfBSplineCurve&    ArrayOfCurves, 
702                            TColStd_Array1OfReal&             ArrayOfToler,
703                            TColStd_Array1OfBoolean&          tabG1,
704                            const Standard_Integer            StartIndex,
705                            const Standard_Real               ClosedTolerance)
706
707 {Standard_Integer i;
708  TColGeom_Array1OfBSplineCurve  ArraybisOfCurves(0,ArrayOfCurves.Length()-1);  //temporary
709  TColStd_Array1OfReal           ArraybisOfToler(0,ArrayOfToler.Length()-1);    //arrays
710  TColStd_Array1OfBoolean        tabbisG1(0,tabG1.Length()-1);
711
712  for (i=0;i<=ArrayOfCurves.Length()-1;i++){
713    if (i!=ArrayOfCurves.Length()-1){
714      ArraybisOfCurves(i)=ArrayOfCurves(i);
715      ArraybisOfToler(i)=ArrayOfToler(i);
716      tabbisG1(i)=tabG1(i);
717    }
718    else
719      ArraybisOfCurves(i)=ArrayOfCurves(i);
720  }
721
722  for (i=0;i<=(ArrayOfCurves.Length()-(StartIndex+2));i++){
723    ArrayOfCurves(i)=ArraybisOfCurves(i+StartIndex+1);
724    if (i!=(ArrayOfCurves.Length()-(StartIndex+2))){
725      ArrayOfToler(i)=ArraybisOfToler(i+StartIndex+1);
726      tabG1(i)=tabbisG1(i+StartIndex+1);
727    }
728  }
729
730  ArrayOfToler(ArrayOfCurves.Length()-(StartIndex+2))=ClosedTolerance;
731  tabG1(ArrayOfCurves.Length()-(StartIndex+2))=Standard_True;
732
733  for (i=(ArrayOfCurves.Length()-(StartIndex+1));i<=(ArrayOfCurves.Length()-1);i++){
734    if (i!=ArrayOfCurves.Length()-1){
735      ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
736      ArrayOfToler(i)=ArraybisOfToler(i-(ArrayOfCurves.Length()-(StartIndex+1)));
737      tabG1(i)=tabbisG1(i-(ArrayOfCurves.Length()-(StartIndex+1)));
738    }
739    else
740      ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
741  }
742 }
743
744 //=======================================================================
745 //class   : reparameterise_evaluator
746 //purpose :
747 //=======================================================================
748
749 class GeomConvert_reparameterise_evaluator : public BSplCLib_EvaluatorFunction
750 {
751
752 public:
753
754   GeomConvert_reparameterise_evaluator (const Standard_Real thePolynomialCoefficient[3])
755   {
756     memcpy (myPolynomialCoefficient, thePolynomialCoefficient, sizeof(myPolynomialCoefficient));
757   }
758
759   virtual void Evaluate (const Standard_Integer theDerivativeRequest,
760                          const Standard_Real*   /*theStartEnd*/,
761                          const Standard_Real    theParameter,
762                          Standard_Real&         theResult,
763                          Standard_Integer&      theErrorCode) const
764   {
765     theErrorCode = 0;
766     PLib::EvalPolynomial (theParameter,
767                           theDerivativeRequest,
768                           2,
769                           1,
770                           *((Standard_Real* )myPolynomialCoefficient), // function really only read values from this array
771                           theResult);
772   }
773
774 private:
775
776   Standard_Real myPolynomialCoefficient[3];
777
778 };
779
780 //=======================================================================
781 //function : ConcatG1
782 //purpose  : 
783 //=======================================================================
784
785  void  GeomConvert::ConcatG1(TColGeom_Array1OfBSplineCurve&           ArrayOfCurves, 
786                              const TColStd_Array1OfReal&              ArrayOfToler,
787                              Handle(TColGeom_HArray1OfBSplineCurve) & ArrayOfConcatenated,
788                              Standard_Boolean&                        ClosedG1Flag,
789                              const Standard_Real                      ClosedTolerance) 
790
791 {Standard_Integer             nb_curve=ArrayOfCurves.Length(),
792                               nb_vertexG1=0,
793                               nb_group=0,
794                               index=0,i,ii,j,jj,
795                               indexmin,
796                               nb_vertex_group0=0;
797  Standard_Real                lambda,                      //G1 coefficient
798                               First;
799  Standard_Real PreLast = 0.;
800  GeomAbs_Shape                Cont;
801  gp_Vec                       Vec1,Vec2;                   //concecutive tangential vectors 
802  gp_Pnt                       Pint;
803  Handle(Geom_BSplineCurve)    Curve1,Curve2;                       
804  TColStd_Array1OfBoolean      tabG1(0,nb_curve-2);         //array of the G1 continuity at the intersections
805  TColStd_Array1OfReal         local_tolerance(0,
806                                               ArrayOfToler.Length()-1) ;
807  
808  for (i=0 ; i < ArrayOfToler.Length() ; i++) {
809    local_tolerance(i) = ArrayOfToler(i) ;
810  }
811  for (i=0 ;i<nb_curve; i++){
812    if (i >= 1){
813      First=ArrayOfCurves(i)->FirstParameter();
814      Cont = GeomLProp::Continuity(ArrayOfCurves(i-1),
815                                   ArrayOfCurves(i),
816                                   PreLast,First,
817                                   Standard_True,Standard_True);
818      if (Cont<GeomAbs_C0)
819        throw Standard_ConstructionError("GeomConvert curves not C0") ;                
820      else{
821        if (Cont>=GeomAbs_G1)
822          tabG1(i-1)=Standard_True;                   //True=G1 continuity
823        else 
824          tabG1(i-1)=Standard_False;
825      }
826    }
827    PreLast=ArrayOfCurves(i)->LastParameter();     
828  }
829  
830
831  while (index<=nb_curve-1){ //determination of the Wire features
832    nb_vertexG1=0;
833    while(((index+nb_vertexG1)<=nb_curve-2)&&
834          (tabG1(index+nb_vertexG1)==Standard_True))
835      nb_vertexG1++;
836    nb_group++;
837    if (index==0)
838      nb_vertex_group0=nb_vertexG1;
839    index=index+1+nb_vertexG1;
840  }
841
842  if ((ClosedG1Flag)&&(nb_group!=1)){                            //sort of the array
843    nb_group--;
844    ReorderArrayOfG1Curves(ArrayOfCurves,
845                   local_tolerance,
846                   tabG1,
847                   nb_vertex_group0,
848                   ClosedTolerance);
849  }
850
851  ArrayOfConcatenated = new TColGeom_HArray1OfBSplineCurve(0,nb_group-1);
852  Standard_Boolean       fusion;
853
854  index=0;
855  Pretreatment(ArrayOfCurves);
856  Standard_Real aPolynomialCoefficient[3];
857
858  Standard_Boolean NeedDoubleDegRepara = Need2DegRepara(ArrayOfCurves);
859  if (nb_group==1 && ClosedG1Flag && NeedDoubleDegRepara)
860  {
861    Curve1 = ArrayOfCurves(nb_curve-1);
862    if (Curve1->Degree() > Geom2d_BSplineCurve::MaxDegree()/2)
863      ClosedG1Flag = Standard_False;
864  }
865
866  if ((nb_group==1) && (ClosedG1Flag)){ //treatment of a particular case
867    indexmin=Indexmin(ArrayOfCurves);
868    if (indexmin!=(ArrayOfCurves.Length()-1))
869      ReorderArrayOfG1Curves(ArrayOfCurves,
870                     local_tolerance,
871                     tabG1,
872                     indexmin,
873                     ClosedTolerance);
874    Curve2=ArrayOfCurves(0);
875    for (j=1;j<=nb_curve-1;j++){                          //secondary loop inside each group
876      Curve1=ArrayOfCurves(j);
877      if ( (j==(nb_curve-1)) && (NeedDoubleDegRepara)){ 
878        Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
879        Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
880        lambda=Vec2.Magnitude()/Vec1.Magnitude();
881        TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
882        Curve1->Knots(KnotC1);
883        Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
884        ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
885        Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
886        Standard_Real tmax,a,b,c,
887        umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
888        tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
889        a=(lambda*lambda2-1)/(2*lambda*tmax);
890        aPolynomialCoefficient[2] = a;
891        b=(1/lambda); 
892        aPolynomialCoefficient[1] = b;
893        c=umin;
894        aPolynomialCoefficient[0] = c;
895        TColStd_Array1OfReal  Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
896        TColStd_Array1OfInteger  KnotC1Mults(1,Curve1->NbKnots());
897        Curve1->Multiplicities(KnotC1Mults);
898        BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
899        KnotC1(1)=0.0;
900        for (ii=2;ii<=KnotC1.Length();ii++) {
901 //       KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
902          KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); // ifv 17.05.00 buc60667
903        }
904        TColgp_Array1OfPnt  Curve1Poles(1,Curve1->NbPoles());
905        Curve1->Poles(Curve1Poles);
906        
907        for (ii=1;ii<=Curve1->NbKnots();ii++)
908          KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
909        
910        TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
911        
912        BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
913        TColgp_Array1OfPnt  NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
914        Standard_Integer      aStatus;
915        TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
916        Curve1->Weights(Curve1Weights);
917        for (ii=1;ii<=Curve1->NbPoles();ii++)
918          for (jj=1;jj<=3;jj++)
919            Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
920 //POP pour WNT
921        GeomConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
922 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
923        BSplCLib::FunctionReparameterise(ev,
924                                         Curve1->Degree(),
925                                         Curve1FlatKnots,
926                                         Curve1Poles,
927                                         FlatKnots,
928                                         2*Curve1->Degree(),
929                                         NewPoles,
930                                         aStatus
931                                         );
932        TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
933 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
934        BSplCLib::FunctionReparameterise(ev,
935                                         Curve1->Degree(),
936                                         Curve1FlatKnots,
937                                         Curve1Weights,
938                                         FlatKnots,
939                                         2*Curve1->Degree(),
940                                         NewWeights,
941                                         aStatus
942                                         );
943        for (ii=1;ii<=NewPoles.Length();ii++)
944          for (jj=1;jj<=3;jj++)
945            NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
946        Curve1= new Geom_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
947      }
948      GeomConvert_CompCurveToBSplineCurve C (Curve2);
949      fusion=C.Add(Curve1,
950                   local_tolerance(j-1));                //merge of two consecutive curves               
951      if (fusion==Standard_False)
952        throw Standard_ConstructionError("GeomConvert Concatenation Error") ;
953      Curve2=C.BSplineCurve();
954    }
955    Curve2->SetPeriodic();      
956    Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
957                          Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
958                          Precision::Confusion());
959    ArrayOfConcatenated->SetValue(0,Curve2);
960  }
961  
962  else
963    for (i=0;i<=nb_group-1;i++){                             //principal loop on each G1 continuity 
964      nb_vertexG1=0;                                         //group
965      
966      while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
967        nb_vertexG1++;
968       
969      for (j=index;j<=index+nb_vertexG1;j++){                //secondary loop inside each group
970        Curve1=ArrayOfCurves(j);
971        
972        if (index==j)                                        //initialisation at the begining of the loop
973          ArrayOfConcatenated->SetValue(i,Curve1);
974        else{
975          GeomConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(i));
976          fusion=C.Add(Curve1,ArrayOfToler(j-1));            //merge of two consecutive curves               
977          if (fusion==Standard_False)
978            throw Standard_ConstructionError("GeomConvert Concatenation Error") ;
979          ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
980        }
981      }
982      index=index+1+nb_vertexG1;
983    }
984 }  
985 //=======================================================================
986 //function : ConcatC1
987 //purpose  : 
988 //=======================================================================
989
990 void  GeomConvert::ConcatC1(TColGeom_Array1OfBSplineCurve&           ArrayOfCurves, 
991                             const TColStd_Array1OfReal&              ArrayOfToler,
992                             Handle(TColStd_HArray1OfInteger)&        ArrayOfIndices,
993                             Handle(TColGeom_HArray1OfBSplineCurve)&  ArrayOfConcatenated,
994                             Standard_Boolean&                        ClosedG1Flag,
995                             const Standard_Real                      ClosedTolerance) 
996 {
997   ConcatC1(ArrayOfCurves,
998            ArrayOfToler,
999            ArrayOfIndices,
1000            ArrayOfConcatenated,
1001            ClosedG1Flag,
1002            ClosedTolerance,
1003            Precision::Angular()) ;
1004 }
1005 //=======================================================================
1006 //function : ConcatC1
1007 //purpose  : 
1008 //=======================================================================
1009
1010 void  GeomConvert::ConcatC1(TColGeom_Array1OfBSplineCurve&           ArrayOfCurves, 
1011                             const TColStd_Array1OfReal&              ArrayOfToler,
1012                             Handle(TColStd_HArray1OfInteger)&        ArrayOfIndices,
1013                             Handle(TColGeom_HArray1OfBSplineCurve)&  ArrayOfConcatenated,
1014                             Standard_Boolean&                        ClosedG1Flag,
1015                             const Standard_Real                      ClosedTolerance,
1016                             const Standard_Real                      AngularTolerance)
1017
1018 {Standard_Integer             nb_curve=ArrayOfCurves.Length(),
1019                               nb_vertexG1,
1020                               nb_group=0,
1021                               index=0,i,ii,j,jj,
1022                               indexmin,
1023                               nb_vertex_group0=0;
1024  Standard_Real                lambda,                      //G1 coefficient
1025                               First;
1026  Standard_Real PreLast = 0.;
1027
1028  GeomAbs_Shape                Cont;
1029  gp_Vec                       Vec1,Vec2;                   //concecutive tangential vectors
1030  gp_Pnt                       Pint;
1031  Handle(Geom_BSplineCurve)    Curve1,Curve2;                       
1032  TColStd_Array1OfBoolean      tabG1(0,nb_curve-2);         //array of the G1 continuity at the intersections
1033  TColStd_Array1OfReal         local_tolerance(0,
1034                                               ArrayOfToler.Length()-1) ;
1035  
1036  for (i=0 ; i < ArrayOfToler.Length() ; i++) {
1037    local_tolerance(i) = ArrayOfToler(i) ;
1038  }
1039  for (i=0 ;i<nb_curve; i++){
1040    if (i >= 1){
1041      First=ArrayOfCurves(i)->FirstParameter();
1042      Cont = GeomLProp::Continuity(ArrayOfCurves(i-1),
1043                                ArrayOfCurves(i),
1044                                PreLast,
1045                                First,
1046                                Standard_True,
1047                                Standard_True,
1048                                local_tolerance(i-1),
1049                                AngularTolerance);
1050      if (Cont<GeomAbs_C0)
1051        throw Standard_ConstructionError("GeomConvert curves not C0");
1052      else{
1053        if (Cont>=GeomAbs_G1)
1054          tabG1(i-1)=Standard_True;                   //True=G1 continuity
1055        else 
1056          tabG1(i-1)=Standard_False;
1057      }
1058    }
1059    PreLast=ArrayOfCurves(i)->LastParameter();     
1060  }
1061  
1062
1063  while (index<=nb_curve-1){                                 //determination of the Wire features
1064    nb_vertexG1=0;
1065    while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1066      nb_vertexG1++;
1067    nb_group++;
1068    if (index==0)
1069      nb_vertex_group0=nb_vertexG1;
1070    index=index+1+nb_vertexG1;
1071  }
1072
1073  if ((ClosedG1Flag)&&(nb_group!=1)){                            //sort of the array
1074    nb_group--;
1075    ReorderArrayOfG1Curves(ArrayOfCurves,
1076                           local_tolerance,
1077                           tabG1,
1078                           nb_vertex_group0,
1079                           ClosedTolerance);
1080  }
1081
1082  ArrayOfIndices = 
1083    new TColStd_HArray1OfInteger(0,nb_group);
1084  ArrayOfConcatenated = 
1085    new TColGeom_HArray1OfBSplineCurve(0,nb_group-1);
1086
1087  Standard_Boolean       fusion;
1088  Standard_Integer       k=0;
1089  index=0;
1090  Pretreatment(ArrayOfCurves);
1091  Standard_Real aPolynomialCoefficient[3];
1092
1093  Standard_Boolean NeedDoubleDegRepara = Need2DegRepara(ArrayOfCurves);
1094  if (nb_group==1 && ClosedG1Flag && NeedDoubleDegRepara)
1095  {
1096    Curve1 = ArrayOfCurves(nb_curve-1);
1097    if (Curve1->Degree() > Geom2d_BSplineCurve::MaxDegree()/2)
1098      ClosedG1Flag = Standard_False;
1099  }
1100
1101  if ((nb_group==1) && (ClosedG1Flag)){                       //treatment of a particular case
1102    ArrayOfIndices->SetValue(0,0);
1103    ArrayOfIndices->SetValue(1,0);
1104    indexmin=Indexmin(ArrayOfCurves);
1105    if (indexmin!=(ArrayOfCurves.Length()-1))
1106      ReorderArrayOfG1Curves(ArrayOfCurves,
1107                             local_tolerance,
1108                             tabG1,
1109                             indexmin,
1110                             ClosedTolerance);
1111    for (j=0;j<=nb_curve-1;j++){                          //secondary loop inside each group
1112      if (NeedToBeTreated(ArrayOfCurves(j)))
1113        Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1114      else
1115        Curve1=ArrayOfCurves(j);
1116      
1117      if (j==0)                                           //initialisation at the begining of the loop
1118        Curve2=Curve1;
1119      else{
1120        if ( (j==(nb_curve-1)) && (NeedDoubleDegRepara)){ 
1121          Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1122          Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1123          lambda=Vec2.Magnitude()/Vec1.Magnitude();
1124          TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1125          Curve1->Knots(KnotC1);
1126          Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1127          ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1128          Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1129          Standard_Real tmax,a,b,c,
1130          umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1131          tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1132          a=(lambda*lambda2-1)/(2*lambda*tmax);
1133          aPolynomialCoefficient[2] = a;
1134          b=(1/lambda); 
1135          aPolynomialCoefficient[1] = b;
1136          c=umin;
1137          aPolynomialCoefficient[0] = c;
1138          TColStd_Array1OfReal  Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1139          TColStd_Array1OfInteger  KnotC1Mults(1,Curve1->NbKnots());
1140          Curve1->Multiplicities(KnotC1Mults);
1141          BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1142          KnotC1(1)=0.0;
1143          for (ii=2;ii<=KnotC1.Length();ii++) {
1144 //         KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1145            KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); // ifv 17.05.00 buc60667
1146          }
1147          TColgp_Array1OfPnt  Curve1Poles(1,Curve1->NbPoles());
1148          Curve1->Poles(Curve1Poles);
1149          
1150          for (ii=1;ii<=Curve1->NbKnots();ii++)
1151            KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1152          
1153          TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1154          
1155          BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1156          TColgp_Array1OfPnt  NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1157          Standard_Integer      aStatus;
1158          TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1159          Curve1->Weights(Curve1Weights);
1160          for (ii=1;ii<=Curve1->NbPoles();ii++)
1161            for (jj=1;jj<=3;jj++)
1162              Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1163 //POP pour WNT
1164          GeomConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1165
1166          BSplCLib::FunctionReparameterise(ev,
1167                                           Curve1->Degree(),
1168                                           Curve1FlatKnots,
1169                                           Curve1Poles,
1170                                           FlatKnots,
1171                                           2*Curve1->Degree(),
1172                                           NewPoles,
1173                                           aStatus
1174                                           );
1175          TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1176
1177          BSplCLib::FunctionReparameterise(ev,
1178                                           Curve1->Degree(),
1179                                           Curve1FlatKnots,
1180                                           Curve1Weights,
1181                                           FlatKnots,
1182                                           2*Curve1->Degree(),
1183                                           NewWeights,
1184                                           aStatus
1185                                           );
1186          for (ii=1;ii<=NewPoles.Length();ii++)
1187            for (jj=1;jj<=3;jj++)
1188              NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1189          Curve1= new Geom_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
1190        }
1191        GeomConvert_CompCurveToBSplineCurve C (Curve2);
1192        fusion=C.Add(Curve1,
1193                     local_tolerance(j-1));          //merge of two consecutive curves               
1194        if (fusion==Standard_False)
1195          throw Standard_ConstructionError("GeomConvert Concatenation Error") ;
1196        Curve2=C.BSplineCurve();
1197      }
1198    }
1199    Curve2->SetPeriodic();                               //only one C1 curve
1200    Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
1201                          Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1202                          Precision::Confusion());
1203    ArrayOfConcatenated->SetValue(0,Curve2);
1204  }
1205  
1206  else
1207    for (i=0;i<=nb_group-1;i++){                             //principal loop on each G1 continuity 
1208      nb_vertexG1=0;                                         //group
1209       
1210      while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1211        nb_vertexG1++;
1212       
1213      if ((!ClosedG1Flag)||(nb_group==1)){                        //filling of the array of index which are kept
1214        k++;
1215        ArrayOfIndices->SetValue(k-1,index);
1216        if (k==nb_group)
1217          ArrayOfIndices->SetValue(k,0);
1218      }
1219      else{
1220        k++;
1221        ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1);
1222        if (k==nb_group)
1223          ArrayOfIndices->SetValue(k,nb_vertex_group0+1);
1224      }
1225       
1226      for (j=index;j<=index+nb_vertexG1;j++){                //secondary loop inside each group
1227        if (NeedToBeTreated(ArrayOfCurves(j)))
1228          Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1229        else
1230          Curve1=ArrayOfCurves(j);
1231        
1232        if (index==j)                                      //initialisation at the begining of the loop
1233          ArrayOfConcatenated->SetValue(i,Curve1);
1234        else
1235        {
1236          // Merge of two consecutive curves.
1237          GeomConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(i));
1238          fusion=C.Add(Curve1, local_tolerance(j-1), Standard_True);
1239          if (fusion==Standard_False)
1240            throw Standard_ConstructionError("GeomConvert Concatenation Error");
1241          ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1242        }
1243      }
1244      index=index+1+nb_vertexG1;
1245    }
1246 }
1247            
1248 //=======================================================================
1249 //function : C0BSplineToC1BSplineCurve
1250 //purpose  : 
1251 //=======================================================================
1252
1253 void GeomConvert::C0BSplineToC1BSplineCurve(Handle(Geom_BSplineCurve)& BS,
1254                                             const Standard_Real tolerance, 
1255                                             const Standard_Real AngularTol)
1256
1257 {
1258   Standard_Boolean fusion;
1259   Handle(TColGeom_HArray1OfBSplineCurve) ArrayOfConcatenated; 
1260   //the array with the resulting curves
1261     
1262   GeomConvert::C0BSplineToArrayOfC1BSplineCurve(BS, ArrayOfConcatenated, 
1263                                                 AngularTol, tolerance);
1264     
1265   GeomConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(0));
1266   if (ArrayOfConcatenated->Length()>=2){
1267     Standard_Integer i;
1268     for (i=1;i<ArrayOfConcatenated->Length();i++){
1269       fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance);
1270       if (fusion==Standard_False)
1271         throw Standard_ConstructionError("GeomConvert Concatenation Error") ;
1272     }
1273   }
1274   BS=C.BSplineCurve();
1275 }
1276
1277 //=======================================================================
1278 //function : C0BSplineToArrayOfC1BSplineCurve
1279 //purpose  : 
1280 //=======================================================================
1281
1282 void GeomConvert::C0BSplineToArrayOfC1BSplineCurve(
1283                                 const Handle(Geom_BSplineCurve) &        BS,
1284                                 Handle(TColGeom_HArray1OfBSplineCurve) & tabBS,
1285                                 const Standard_Real                      tolerance)
1286 {
1287    C0BSplineToArrayOfC1BSplineCurve(BS,
1288                                     tabBS,
1289                                     Precision::Angular(),
1290                                     tolerance) ;
1291 }
1292
1293 //=======================================================================
1294 //function : C0BSplineToArrayOfC1BSplineCurve
1295 //purpose  : 
1296 //=======================================================================
1297
1298 void GeomConvert::C0BSplineToArrayOfC1BSplineCurve(
1299                                 const Handle(Geom_BSplineCurve) &        BS,
1300                                 Handle(TColGeom_HArray1OfBSplineCurve) & tabBS,
1301                                 const Standard_Real                      AngularTolerance,
1302                                 const Standard_Real                      tolerance)
1303
1304 {TColStd_Array1OfInteger          BSMults(1,BS->NbKnots());
1305  TColStd_Array1OfReal             BSKnots(1,BS->NbKnots());
1306  Standard_Integer                 i,j,nbcurveC1=1;
1307  Standard_Real                    U1,U2;
1308  Standard_Boolean                 closed_flag= Standard_False ;
1309  gp_Pnt                           point;
1310  gp_Vec                           V1,V2;
1311 // Standard_Boolean                 fusion;
1312
1313  BS->Knots(BSKnots);
1314  BS->Multiplicities(BSMults);
1315  for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){                                 //give the number of C1 curves
1316    if (BSMults(i)==BS->Degree())
1317      nbcurveC1++;   
1318  }
1319
1320  if (nbcurveC1>1){
1321    TColGeom_Array1OfBSplineCurve    ArrayOfCurves(0,nbcurveC1-1);
1322    TColStd_Array1OfReal             ArrayOfToler(0,nbcurveC1-2);
1323    
1324    for (i=0;i<=nbcurveC1-2;i++)                                      
1325      //filling of the array of tolerances  
1326      ArrayOfToler(i)=tolerance;                                      
1327    //with the variable tolerance
1328    U2=BS->FirstParameter() ;
1329    j=BS->FirstUKnotIndex() + 1;
1330    for (i=0;i<nbcurveC1;i++){                                        
1331      //filling of the array of curves
1332      U1=U2;                                                          
1333      //with the curves C1 segmented
1334      while (BSMults(j)<BS->Degree() && j < BS->LastUKnotIndex())
1335        j++;
1336      U2=BSKnots(j);
1337      j++;
1338      Handle(Geom_BSplineCurve) 
1339        BSbis=Handle(Geom_BSplineCurve)::DownCast(BS->Copy());
1340      BSbis->Segment(U1,U2);
1341      ArrayOfCurves(i)=BSbis;
1342    }
1343     
1344    Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1345      
1346    BS->D1(BS->FirstParameter(),point,V1);  
1347    BS->D1(BS->LastParameter(),point,V2);
1348     
1349    if ((BS->IsClosed())&&(V1.IsParallel(V2,AngularTolerance))){
1350      //check if the BSpline is closed G1
1351      closed_flag = Standard_True ;
1352    }
1353     
1354    GeomConvert::ConcatC1(ArrayOfCurves,
1355                          ArrayOfToler,
1356                          ArrayOfIndices,
1357                          tabBS,
1358                          closed_flag,
1359                          tolerance,
1360                          AngularTolerance);
1361  }
1362  else{
1363    tabBS = new TColGeom_HArray1OfBSplineCurve(0,0);
1364    tabBS->SetValue(0,BS);
1365  }
1366 }  
1367
1368
1369
1370
1371