0026377: Passing Handle objects as arguments to functions as non-const reference...
[occt.git] / src / Geom2dConvert / Geom2dConvert.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
17
18 #include <BSplCLib.hxx>
19 #include <Convert_CircleToBSplineCurve.hxx>
20 #include <Convert_ConicToBSplineCurve.hxx>
21 #include <Convert_EllipseToBSplineCurve.hxx>
22 #include <Convert_HyperbolaToBSplineCurve.hxx>
23 #include <Convert_ParabolaToBSplineCurve.hxx>
24 #include <Geom2d_BezierCurve.hxx>
25 #include <Geom2d_BSplineCurve.hxx>
26 #include <Geom2d_Circle.hxx>
27 #include <Geom2d_Conic.hxx>
28 #include <Geom2d_Curve.hxx>
29 #include <Geom2d_Ellipse.hxx>
30 #include <Geom2d_Geometry.hxx>
31 #include <Geom2d_Hyperbola.hxx>
32 #include <Geom2d_Line.hxx>
33 #include <Geom2d_OffsetCurve.hxx>
34 #include <Geom2d_Parabola.hxx>
35 #include <Geom2d_TrimmedCurve.hxx>
36 #include <Geom2dConvert.hxx>
37 #include <Geom2dConvert_ApproxCurve.hxx>
38 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
39 #include <GeomAbs_Shape.hxx>
40 #include <gp.hxx>
41 #include <gp_Circ2d.hxx>
42 #include <gp_Dir2d.hxx>
43 #include <gp_Elips2d.hxx>
44 #include <gp_Hypr2d.hxx>
45 #include <gp_Lin.hxx>
46 #include <gp_Parab2d.hxx>
47 #include <gp_Pnt2d.hxx>
48 #include <gp_Trsf2d.hxx>
49 #include <gp_Vec2d.hxx>
50 #include <Hermit.hxx>
51 #include <PLib.hxx>
52 #include <Precision.hxx>
53 #include <Standard_ConstructionError.hxx>
54 #include <Standard_DomainError.hxx>
55 #include <Standard_OutOfRange.hxx>
56 #include <TColgp_Array1OfPnt2d.hxx>
57 #include <TColStd_Array1OfBoolean.hxx>
58 #include <TColStd_Array1OfInteger.hxx>
59 #include <TColStd_Array1OfReal.hxx>
60 #include <TColStd_HArray1OfReal.hxx>
61
62 typedef gp_Circ2d  Circ2d;
63 typedef gp_Elips2d Elips2d;
64 typedef gp_Hypr2d  Hypr2d;
65 typedef gp_Parab2d Parab2d;
66 typedef gp_Pnt2d   Pnt2d;
67 typedef gp_Trsf2d  Trsf2d;
68 typedef Geom2d_Curve                Curve;
69 typedef Geom2d_BSplineCurve         BSplineCurve;
70 typedef TColStd_Array1OfReal                 Array1OfReal;
71 typedef TColStd_Array1OfInteger              Array1OfInteger;
72 typedef TColgp_Array1OfPnt2d                 Array1OfPnt2d;
73
74 //=======================================================================
75 //function : BSplineCurveBuilder
76 //purpose  : 
77 //=======================================================================
78
79 static Handle(Geom2d_BSplineCurve) BSplineCurveBuilder (
80
81 const Handle(Geom2d_Conic)&                TheConic,
82 const Convert_ConicToBSplineCurve&  Convert
83 ) {
84
85    Handle(Geom2d_BSplineCurve) TheCurve;
86    Standard_Integer NbPoles = Convert.NbPoles();
87    Standard_Integer NbKnots = Convert.NbKnots();
88    Array1OfPnt2d   Poles   (1, NbPoles);
89    Array1OfReal    Weights (1, NbPoles);
90    Array1OfReal    Knots   (1, NbKnots);
91    Array1OfInteger Mults   (1, NbKnots);
92    Standard_Integer i;
93    for (i = 1; i <= NbPoles; i++) {
94      Poles   (i) = Convert.Pole (i);
95      Weights (i) = Convert.Weight (i);         
96    }
97    for (i = 1; i <= NbKnots; i++) {
98      Knots (i) = Convert.Knot (i);
99      Mults (i) = Convert.Multiplicity (i);
100    }
101    TheCurve = new BSplineCurve (
102                   Poles, Weights, Knots, Mults, 
103                   Convert.Degree(), Convert.IsPeriodic());
104
105    gp_Ax22d Axis = TheConic->Position();
106    if ( ( Axis.XDirection() ^ Axis.YDirection()) < 0.) {
107      // Then the axis is left-handed, apply a symetry to the curve.
108      gp_Trsf2d Sym;
109      Sym.SetMirror(gp::OX2d());
110      TheCurve->Transform(Sym);
111    }
112
113    Trsf2d T;
114    T.SetTransformation (TheConic->XAxis(), gp::OX2d());
115    Handle(Geom2d_BSplineCurve) Cres = 
116      Handle(Geom2d_BSplineCurve)::DownCast(TheCurve->Transformed (T));
117    return Cres;
118 }
119
120
121 //=======================================================================
122 //function : SplitBSplineCurve
123 //purpose  : 
124 //=======================================================================
125
126 Handle(Geom2d_BSplineCurve) Geom2dConvert::SplitBSplineCurve (
127
128 const Handle(Geom2d_BSplineCurve)& C,
129 const Standard_Integer               FromK1, 
130 const Standard_Integer               ToK2,
131 const Standard_Boolean               SameOrientation
132 ) {
133
134   Standard_Integer TheFirst = C->FirstUKnotIndex ();
135   Standard_Integer TheLast  = C->LastUKnotIndex  ();
136   if (FromK1 == ToK2)  Standard_DomainError::Raise();
137   Standard_Integer FirstK = Min (FromK1, ToK2);
138   Standard_Integer LastK  = Max (FromK1, ToK2);
139   if (FirstK < TheFirst || LastK > TheLast) Standard_OutOfRange::Raise();
140
141   Handle(Geom2d_BSplineCurve) NewCurve = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy());
142
143   NewCurve->Segment(C->Knot(FirstK),C->Knot(LastK));
144
145   if (C->IsPeriodic()) {
146     if (!SameOrientation) NewCurve->Reverse();
147   }
148   else {
149     if (FromK1 > ToK2)    NewCurve->Reverse();
150   }
151   return NewCurve;
152 }
153
154
155 //=======================================================================
156 //function : SplitBSplineCurve
157 //purpose  : 
158 //=======================================================================
159
160 Handle(Geom2d_BSplineCurve) Geom2dConvert::SplitBSplineCurve (
161
162 const Handle(Geom2d_BSplineCurve)& C, 
163 const Standard_Real                  FromU1, 
164 const Standard_Real                  ToU2,
165 const Standard_Real, // ParametricTolerance,
166 const Standard_Boolean               SameOrientation
167
168 {
169   Standard_Real FirstU = Min( FromU1, ToU2);
170   Standard_Real LastU  = Max( FromU1, ToU2);
171   
172   Handle (Geom2d_BSplineCurve) C1 
173     = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy());
174
175   C1->Segment(FirstU, LastU);
176
177   if (C->IsPeriodic()) {
178      if (!SameOrientation) C1->Reverse();
179    }
180   else {
181     if (FromU1 > ToU2)    C1->Reverse();
182   }
183
184   return C1;
185 }
186
187
188 //=======================================================================
189 //function : CurveToBSplineCurve
190 //purpose  : 
191 //=======================================================================
192
193 Handle(Geom2d_BSplineCurve)  Geom2dConvert::CurveToBSplineCurve (
194
195 const Handle(Geom2d_Curve)& C,
196 const Convert_ParameterisationType  Parameterisation) 
197 {
198     
199   Handle (BSplineCurve) TheCurve;
200     
201   if (C->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
202     Handle (Curve) Curv;
203     Handle(Geom2d_TrimmedCurve) Ctrim = Handle(Geom2d_TrimmedCurve)::DownCast(C);
204     Curv = Ctrim->BasisCurve();
205     Standard_Real U1 = Ctrim->FirstParameter();
206     Standard_Real U2 = Ctrim->LastParameter();
207
208     // Si la courbe n'est pas vraiment restreinte, on ne risque pas 
209     // le Raise dans le BS->Segment.
210     if (!Curv->IsPeriodic()) {     
211       if (U1 < Curv->FirstParameter())
212         U1 =  Curv->FirstParameter();
213       if (U2 > Curv->LastParameter())
214         U2 = Curv->LastParameter();
215     } 
216     
217     if (Curv->IsKind(STANDARD_TYPE(Geom2d_Line))) {
218       gp_Pnt2d Pdeb = Ctrim->StartPoint();
219       gp_Pnt2d Pfin = Ctrim->EndPoint();
220       Array1OfPnt2d Poles (1, 2);
221       Poles (1) = Pdeb;
222       Poles (2) = Pfin;
223       Array1OfReal Knots (1, 2);
224       Knots (1) = Ctrim->FirstParameter ();
225       Knots (2) = Ctrim->LastParameter();
226       Array1OfInteger Mults (1, 2);
227       Mults (1) = 2;
228       Mults (2) = 2;
229       Standard_Integer Degree = 1;
230       TheCurve = new Geom2d_BSplineCurve (Poles, Knots, Mults, Degree);
231     }
232     
233     else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
234       Handle(Geom2d_Circle) TheConic= Handle(Geom2d_Circle)::DownCast(Curv);
235       Circ2d C2d (gp::OX2d(), TheConic->Radius());
236       if(Parameterisation != Convert_RationalC1) {
237         Convert_CircleToBSplineCurve Convert (C2d,
238                                               U1, 
239                                               U2, 
240                                               Parameterisation);
241         TheCurve = BSplineCurveBuilder (TheConic, Convert);
242       }
243       else {
244         if(U2 - U1 < 6.) {
245           Convert_CircleToBSplineCurve Convert (C2d, 
246                                                 U1, 
247                                                 U2, 
248                                                 Parameterisation);
249           TheCurve = BSplineCurveBuilder (TheConic, Convert);
250         }
251         else { // split circle to avoide numerical 
252                // overflow when U2 - U1 =~ 2*PI
253
254           Standard_Real Umed = (U1 + U2) * .5;
255           Convert_CircleToBSplineCurve Convert1 (C2d, 
256                                                  U1, 
257                                                  Umed, 
258                                                  Parameterisation);
259
260           Handle (BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
261
262           Convert_CircleToBSplineCurve Convert2 (C2d, 
263                                                  Umed, 
264                                                  U2, 
265                                                  Parameterisation);
266
267           Handle (BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
268
269           Geom2dConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
270                                                         Parameterisation);
271
272           CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
273           
274           
275           TheCurve = CCTBSpl.BSplineCurve();
276         }
277       }
278     }
279     
280     else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
281       Handle(Geom2d_Ellipse) TheConic = Handle(Geom2d_Ellipse)::DownCast(Curv);
282       
283       Elips2d E2d (gp::OX2d(),
284                    TheConic->MajorRadius(),
285                    TheConic->MinorRadius());
286       if(Parameterisation != Convert_RationalC1) {
287         Convert_EllipseToBSplineCurve Convert (E2d, 
288                                                U1, 
289                                                U2,
290                                                Parameterisation);
291         TheCurve = BSplineCurveBuilder (TheConic, Convert);
292       }
293       else {
294         if(U2 - U1 < 6.) {
295           Convert_EllipseToBSplineCurve Convert (E2d, 
296                                                  U1, 
297                                                  U2,
298                                                  Parameterisation);
299           TheCurve = BSplineCurveBuilder (TheConic, Convert);
300         }       
301         else { // split ellipse to avoide numerical 
302                // overflow when U2 - U1 =~ 2*PI
303
304           Standard_Real Umed = (U1 + U2) * .5;
305           Convert_EllipseToBSplineCurve Convert1 (E2d, 
306                                                   U1, 
307                                                   Umed, 
308                                                   Parameterisation);
309
310           Handle (BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
311
312           Convert_EllipseToBSplineCurve Convert2 (E2d, 
313                                                   Umed, 
314                                                   U2, 
315                                                   Parameterisation);
316
317           Handle (BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
318
319           Geom2dConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
320                                                         Parameterisation);
321
322           CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
323
324           
325           TheCurve = CCTBSpl.BSplineCurve();
326         }
327       }
328     }
329     
330     else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) {
331       Handle(Geom2d_Hyperbola) TheConic = Handle(Geom2d_Hyperbola)::DownCast(Curv);
332       
333       Hypr2d H2d (gp::OX2d(),
334                   TheConic->MajorRadius(), TheConic->MinorRadius());
335       Convert_HyperbolaToBSplineCurve Convert (H2d, U1, U2);
336       TheCurve = BSplineCurveBuilder (TheConic, Convert);
337     }
338     
339     else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Parabola))) {
340       Handle(Geom2d_Parabola) TheConic = Handle(Geom2d_Parabola)::DownCast(Curv);
341       
342       Parab2d Prb2d (gp::OX2d(), TheConic->Focal());
343       Convert_ParabolaToBSplineCurve Convert (Prb2d, U1, U2);
344       TheCurve = BSplineCurveBuilder (TheConic, Convert);
345     }
346     
347     else if (Curv->IsKind (STANDARD_TYPE(Geom2d_BezierCurve))) {
348       
349       Handle(Geom2d_BezierCurve) CBez = Handle(Geom2d_BezierCurve)::DownCast(Curv->Copy());
350       
351       CBez->Segment (U1, U2);
352       Standard_Integer NbPoles = CBez->NbPoles();
353       Standard_Integer Degree  = CBez->Degree();
354       Array1OfPnt2d     Poles   (1, NbPoles);
355       Array1OfReal    Knots   (1, 2);
356       Array1OfInteger Mults   (1, 2);
357       Knots (1) = 0.0;
358       Knots (2) = 1.0;
359       Mults (1) = Degree + 1;
360       Mults (2) = Degree + 1;
361       CBez->Poles (Poles);
362       if (CBez->IsRational()) {    
363         Array1OfReal    Weights (1, NbPoles);
364         CBez->Weights (Weights);
365         TheCurve = new BSplineCurve (Poles, Weights, Knots, Mults, Degree);
366       }
367       else {
368         TheCurve = new BSplineCurve (Poles, Knots, Mults, Degree);
369       }
370     }
371     
372     else if (Curv->IsKind (STANDARD_TYPE(Geom2d_BSplineCurve))) {
373       TheCurve = Handle(Geom2d_BSplineCurve)::DownCast(Curv->Copy());
374       TheCurve->Segment(U1,U2);
375     }
376     
377     else if (Curv->IsKind (STANDARD_TYPE(Geom2d_OffsetCurve))) {
378       
379       Standard_Real Tol2d = 1.e-4;
380       GeomAbs_Shape Order = GeomAbs_C2;
381       Standard_Integer MaxSegments = 16, MaxDegree = 14; 
382       Geom2dConvert_ApproxCurve ApprCOffs(C, Tol2d, Order, 
383                                           MaxSegments, MaxDegree);
384       if (ApprCOffs.HasResult())
385         TheCurve = ApprCOffs.Curve();
386       else  Standard_ConstructionError::Raise();
387     }
388
389     else { Standard_DomainError::Raise("No such curve"); }
390     
391   }
392   
393   
394   else { 
395     
396     if (C->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
397       Handle(Geom2d_Ellipse) TheConic = Handle(Geom2d_Ellipse)::DownCast(C);
398       
399       Elips2d E2d (gp::OX2d(),
400                    TheConic->MajorRadius(), TheConic->MinorRadius());
401       Convert_EllipseToBSplineCurve Convert (E2d,
402                                              Parameterisation);
403       TheCurve = BSplineCurveBuilder (TheConic, Convert);
404       TheCurve->SetPeriodic();
405     }
406     
407     else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
408       Handle(Geom2d_Circle) TheConic = Handle(Geom2d_Circle)::DownCast(C);
409       
410       Circ2d C2d (gp::OX2d(), TheConic->Radius());
411       Convert_CircleToBSplineCurve Convert (C2d,
412                                             Parameterisation);
413       TheCurve = BSplineCurveBuilder (TheConic, Convert);
414       TheCurve->SetPeriodic();
415     }
416     
417     else if (C->IsKind (STANDARD_TYPE(Geom2d_BezierCurve))) {
418       Handle(Geom2d_BezierCurve) CBez = Handle(Geom2d_BezierCurve)::DownCast(C);
419       
420       Standard_Integer NbPoles = CBez->NbPoles();
421       Standard_Integer Degree  = CBez->Degree();
422       Array1OfPnt2d     Poles   (1, NbPoles);
423       Array1OfReal    Knots   (1, 2);
424       Array1OfInteger Mults   (1, 2);
425       Knots (1) = 0.0;
426       Knots (2) = 1.0;
427       Mults (1) = Degree + 1;
428       Mults (2) = Degree + 1;
429       CBez->Poles (Poles);
430       if (CBez->IsRational()) {    
431         Array1OfReal    Weights (1, NbPoles);
432         CBez->Weights (Weights);
433         TheCurve = new BSplineCurve (Poles, Weights, Knots, Mults, Degree);
434       }
435       else {
436         TheCurve = new BSplineCurve (Poles, Knots, Mults, Degree);
437       }
438     }
439     else if (C->IsKind (STANDARD_TYPE(Geom2d_BSplineCurve))) {
440       TheCurve = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy());
441     }
442
443     else if (C->IsKind (STANDARD_TYPE(Geom2d_OffsetCurve))) {
444       
445       Standard_Real Tol2d = 1.e-4;
446       GeomAbs_Shape Order = GeomAbs_C2;
447       Standard_Integer MaxSegments = 16, MaxDegree = 14; 
448       Geom2dConvert_ApproxCurve ApprCOffs(C, Tol2d, Order, 
449                                           MaxSegments, MaxDegree);
450       if (ApprCOffs.HasResult())
451         TheCurve = ApprCOffs.Curve();
452       else  Standard_ConstructionError::Raise();
453     }
454
455     else { Standard_DomainError::Raise(); }
456   }
457   
458   return TheCurve;
459 }
460
461  //=======================================================================
462 //class : law_evaluator
463 //purpose  : 
464 //=======================================================================
465
466 class Geom2dConvert_law_evaluator : public BSplCLib_EvaluatorFunction
467 {
468
469 public:
470
471   Geom2dConvert_law_evaluator (const Handle(Geom2d_BSplineCurve)& theAncore)
472   : myAncore (theAncore) {}
473
474   virtual void Evaluate (const Standard_Integer theDerivativeRequest,
475                          const Standard_Real*   theStartEnd,
476                          const Standard_Real    theParameter,
477                          Standard_Real&         theResult,
478                          Standard_Integer&      theErrorCode) const
479   {
480     theErrorCode = 0;
481     if (!myAncore.IsNull() && 
482         theParameter >= theStartEnd[0] &&
483         theParameter <= theStartEnd[1] && 
484         theDerivativeRequest == 0)
485     {
486       gp_Pnt2d aPoint;
487       myAncore->D0 (theParameter, aPoint);
488       theResult = aPoint.Coord (2);
489     }
490     else
491       theErrorCode = 1;
492   }
493
494 private:
495
496   Handle(Geom2d_BSplineCurve) myAncore;
497
498 };
499
500
501 //=======================================================================
502 //function : MultNumandDenom
503 //purpose  : Multiply two BSpline curves to make one
504 //=======================================================================
505
506
507 static Handle(Geom2d_BSplineCurve) MultNumandDenom(const Handle(Geom2d_BSplineCurve)& a ,
508                                                    const Handle(Geom2d_BSplineCurve)& BS )
509      
510 { TColStd_Array1OfReal               aKnots(1,a->NbKnots());
511   TColStd_Array1OfReal               BSKnots(1,BS->NbKnots());
512   TColStd_Array1OfReal               BSFlatKnots(1,BS->NbPoles()+BS->Degree()+1);
513   TColStd_Array1OfReal               BSWeights(1,BS->NbPoles()); 
514   TColStd_Array1OfInteger            aMults(1,a->NbKnots());
515   TColStd_Array1OfInteger            BSMults(1,BS->NbKnots());
516   TColgp_Array1OfPnt2d               aPoles(1,a->NbPoles());
517   TColgp_Array1OfPnt2d               BSPoles(1,BS->NbPoles());
518   Handle(Geom2d_BSplineCurve)        res;
519   Handle(TColStd_HArray1OfReal)      resKnots;
520   Handle(TColStd_HArray1OfInteger)   resMults; 
521   Standard_Real                      start_value,end_value;
522   Standard_Real                      tolerance=Precision::Confusion();
523   Standard_Integer                   resNbPoles,degree,
524                                      ii,jj,
525                                      Status;
526   
527   BS->Knots(BSKnots);                            
528   BS->Multiplicities(BSMults);
529   BS->Poles(BSPoles);
530   BS->Weights(BSWeights);
531   BS->KnotSequence(BSFlatKnots);
532   start_value = BSKnots(1);
533   end_value = BSKnots(BS->NbKnots());
534
535   a->Knots(aKnots);
536   a->Poles(aPoles);
537   a->Multiplicities(aMults);
538   BSplCLib::Reparametrize(BS->FirstParameter(),BS->LastParameter(),aKnots);
539   Handle(Geom2d_BSplineCurve) anAncore = new Geom2d_BSplineCurve (aPoles, aKnots, aMults, a->Degree());
540
541   BSplCLib::MergeBSplineKnots(tolerance,start_value,end_value,
542                               a->Degree(),aKnots,aMults,
543                               BS->Degree(),BSKnots,BSMults,
544                               resNbPoles,resKnots,resMults);
545   degree=BS->Degree()+a->Degree();
546   TColgp_Array1OfPnt2d resNumPoles(1,resNbPoles);
547   TColStd_Array1OfReal resDenPoles(1,resNbPoles);
548   TColgp_Array1OfPnt2d resPoles(1,resNbPoles);
549   TColStd_Array1OfReal resFlatKnots(1,resNbPoles+degree+1);
550   BSplCLib::KnotSequence(resKnots->Array1(),resMults->Array1(),resFlatKnots);
551   for (ii=1;ii<=BS->NbPoles();ii++)
552     for (jj=1;jj<=2;jj++)
553       BSPoles(ii).SetCoord(jj,BSPoles(ii).Coord(jj)*BSWeights(ii));
554 //POP pour NT
555   Geom2dConvert_law_evaluator ev (anAncore);
556   BSplCLib::FunctionMultiply(ev,
557                              BS->Degree(),
558                              BSFlatKnots,
559                              BSPoles,
560                              resFlatKnots,
561                              degree,
562                              resNumPoles,
563                              Status);
564   BSplCLib::FunctionMultiply(ev,
565                              BS->Degree(),
566                              BSFlatKnots,
567                              BSWeights,
568                              resFlatKnots,
569                              degree,
570                              resDenPoles,
571                              Status);
572 //  BSplCLib::FunctionMultiply(law_evaluator,
573 //                           BS->Degree(),
574 //                           BSFlatKnots,
575 //                           BSPoles,
576 //                           resFlatKnots,
577 //                           degree,
578 //                           resNumPoles,
579 //                           Status);
580 //  BSplCLib::FunctionMultiply(law_evaluator,
581 //                           BS->Degree(),
582 //                           BSFlatKnots,
583 //                           BSWeights,
584 //                           resFlatKnots,
585 //                           degree,
586 //                           resDenPoles,
587 //                           Status);
588   for (ii=1;ii<=resNbPoles;ii++)
589     for(jj=1;jj<=2;jj++) 
590       resPoles(ii).SetCoord(jj,resNumPoles(ii).Coord(jj)/resDenPoles(ii));
591   res = new Geom2d_BSplineCurve(resPoles,resDenPoles,resKnots->Array1(),resMults->Array1(),degree);
592   return res;
593 }
594
595 //=======================================================================
596 //function : Pretreatment 
597 //purpose  : Put the two first and two last weigths at one if they are 
598 //           equal
599 //=======================================================================
600
601 static void Pretreatment(TColGeom2d_Array1OfBSplineCurve& tab)
602
603 {Standard_Integer i,j;
604  Standard_Real a;
605
606  for (i=0;i<=(tab.Length()-1);i++){
607    if (tab(i)->IsRational()) {
608      a=tab(i)->Weight(1) ;
609      if ((tab(i)->Weight(2)==a)&&
610          (tab(i)->Weight(tab(i)->NbPoles()-1)==a) &&
611          (tab(i)->Weight(tab(i)->NbPoles())==a))
612        
613        for (j=1;j<=tab(i)->NbPoles();j++)
614          tab(i)->SetWeight(j,tab(i)->Weight(j)/a) ;
615    } 
616  }
617 }
618
619 //=======================================================================
620 //function : NeedToBeTreated
621 //purpose  : Say if the BSpline is rationnal and if the two first and two
622 //           last weigths are different
623 //=======================================================================    
624
625 static Standard_Boolean NeedToBeTreated(const Handle(Geom2d_BSplineCurve)& BS)
626
627 {
628   TColStd_Array1OfReal  tabWeights(1,BS->NbPoles());
629   if (BS->IsRational()) {
630     BS->Weights(tabWeights);
631     if ((BSplCLib::IsRational(tabWeights,1,BS->NbPoles()))&&
632         ((BS->Weight(1)<(1-Precision::Confusion()))||
633          (BS->Weight(1)>(1+Precision::Confusion()))||
634          (BS->Weight(2)<(1-Precision::Confusion()))||
635          (BS->Weight(2)>(1+Precision::Confusion()))||
636          (BS->Weight(BS->NbPoles()-1)<(1-Precision::Confusion()))||
637          (BS->Weight(BS->NbPoles()-1)>(1+Precision::Confusion()))||
638          (BS->Weight(BS->NbPoles())<(1-Precision::Confusion()))||
639          (BS->Weight(BS->NbPoles())>(1+Precision::Confusion()))))
640       return Standard_True;
641     else
642       return Standard_False;
643   }
644   else 
645     return Standard_False ;
646
647 }
648
649 //=======================================================================
650 //function : Need2DegRepara
651 //purpose  : in the case of wire closed G1 it says if you will to use a 
652 //           two degree reparametrisation to close it C1
653 //=======================================================================
654
655 static Standard_Boolean Need2DegRepara(const TColGeom2d_Array1OfBSplineCurve& tab)
656
657 {Standard_Integer        i;
658  gp_Vec2d                Vec1,Vec2;
659  gp_Pnt2d                Pint;
660  Standard_Real           Rapport=1.0e0;
661
662  for (i=0;i<=tab.Length()-2;i++){
663    tab(i+1)->D1(tab(i+1)->FirstParameter(),Pint,Vec1);
664    tab(i)->D1(tab(i)->LastParameter(),Pint,Vec2);
665    Rapport=Rapport*Vec2.Magnitude()/Vec1.Magnitude();
666  }
667  if ((Rapport<=(1.0e0 +Precision::Confusion()))&&(Rapport>=(1.0e0-Precision::Confusion())))
668    return Standard_False;
669  else
670    return Standard_True;
671 }
672          
673 //=======================================================================
674 //function : Indexmin
675 //purpose  : Give the index of the curve which has the lowest degree
676 //=======================================================================
677
678 static Standard_Integer Indexmin(const TColGeom2d_Array1OfBSplineCurve& tab)
679 {
680   Standard_Integer i,index=0,degree;
681   
682   degree=tab(0)->Degree();
683   for (i=0;i<=tab.Length()-1;i++)
684     if (tab(i)->Degree()<=degree){
685       degree=tab(i)->Degree();
686       index=i;
687     }
688   return index;
689 }
690
691 //=======================================================================
692 //function : NewTabClosedG1
693 //purpose  : 
694 //=======================================================================
695
696 static void ReorderArrayOfG1(TColGeom2d_Array1OfBSplineCurve&    ArrayOfCurves, 
697                            TColStd_Array1OfReal&         ArrayOfToler,
698                            TColStd_Array1OfBoolean&            tabG1,
699                            const Standard_Integer              StartIndex,
700                            const Standard_Real                 ClosedTolerance)
701
702 {Standard_Integer i;
703  TColGeom2d_Array1OfBSplineCurve  ArraybisOfCurves(0,ArrayOfCurves.Length()-1);
704  TColStd_Array1OfReal             ArraybisOfToler(0,ArrayOfToler.Length()-1);
705  TColStd_Array1OfBoolean          tabbisG1(0,tabG1.Length()-1);
706
707  for (i=0;i<=ArrayOfCurves.Length()-1;i++){
708    if (i!=ArrayOfCurves.Length()-1){
709      ArraybisOfCurves(i)=ArrayOfCurves(i);
710      ArraybisOfToler(i)=ArrayOfToler(i);
711      tabbisG1(i)=tabG1(i);
712    }
713    else
714      ArraybisOfCurves(i)=ArrayOfCurves(i);
715  }
716
717  for (i=0;i<=(ArrayOfCurves.Length()-(StartIndex+2));i++){
718    ArrayOfCurves(i)=ArraybisOfCurves(i+StartIndex+1);
719    if (i!=(ArrayOfCurves.Length()-(StartIndex+2))){
720      ArrayOfToler(i)=ArraybisOfToler(i+StartIndex+1);
721      tabG1(i)=tabbisG1(i+StartIndex+1);
722    }
723  }
724
725  ArrayOfToler(ArrayOfCurves.Length()-(StartIndex+2))=ClosedTolerance;
726  tabG1(ArrayOfCurves.Length()-(StartIndex+2))=Standard_True;
727
728  for (i=(ArrayOfCurves.Length()-(StartIndex+1));i<=(ArrayOfCurves.Length()-1);i++){
729    if (i!=ArrayOfCurves.Length()-1){
730      ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
731      ArrayOfToler(i)=ArraybisOfToler(i-(ArrayOfCurves.Length()-(StartIndex+1)));
732      tabG1(i)=tabbisG1(i-(ArrayOfCurves.Length()-(StartIndex+1)));
733    }
734    else
735      ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
736  }
737 }
738
739 //=======================================================================
740 //function : GeomAbsToInteger
741 //purpose  : 
742 //=======================================================================
743
744 static Standard_Integer GeomAbsToInteger(const GeomAbs_Shape  gcont) 
745 {
746   Standard_Integer cont=0 ;
747   switch (gcont) {
748   case GeomAbs_C0 :
749       cont = 0 ;
750       break ;
751   case GeomAbs_G1 :
752       cont = 1 ;
753       break ;
754   case GeomAbs_C1 :
755       cont = 2 ;
756       break ;
757   case GeomAbs_G2 :
758       cont = 3 ;
759       break ;
760   case GeomAbs_C2 :
761       cont = 4 ;
762       break ;
763   case GeomAbs_C3 :
764       cont = 5 ;
765       break ;
766   case GeomAbs_CN :
767       cont = 6 ;
768       break ; 
769   } 
770  return cont ;
771 }
772 //=======================================================================
773 //function : Continuity
774 //purpose  : 
775 //=======================================================================
776
777 static GeomAbs_Shape Continuity(const Handle(Geom2d_Curve)& C1, 
778                                 const Handle(Geom2d_Curve)& C2, 
779                                 const Standard_Real u1, 
780                                 const Standard_Real u2,
781                                 const Standard_Boolean r1, 
782                                 const Standard_Boolean r2,
783                                 const Standard_Real tl,
784                                 const Standard_Real ta)
785 {
786   GeomAbs_Shape cont = GeomAbs_C0;
787   Standard_Integer index1,
788                    index2 ;
789   Standard_Real  tolerance,value ;
790 //  Standard_Boolean fini = Standard_False;
791   gp_Vec2d d1,d2;
792 //  gp_Dir2d dir1,dir2;
793   gp_Pnt2d point1, point2 ;
794   Standard_Integer cont1, cont2 ;
795   GeomAbs_Shape gcont1 = C1->Continuity(), gcont2 = C2->Continuity();
796   cont1 = GeomAbsToInteger(gcont1) ;
797   cont2 = GeomAbsToInteger(gcont2) ;
798          
799   Handle(Geom2d_Curve) aCurve1 = C1 ;
800   Handle(Geom2d_Curve) aCurve2 = C2 ;
801   if (C1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))){
802     Handle(Geom2d_TrimmedCurve) aTrimmed = Handle(Geom2d_TrimmedCurve) ::DownCast(aCurve1) ;
803     aCurve1 = aTrimmed->BasisCurve() ;
804   }
805   if (C2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))){
806     Handle(Geom2d_TrimmedCurve) aTrimmed = Handle(Geom2d_TrimmedCurve) ::DownCast(aCurve2) ;
807     aCurve2 = aTrimmed->BasisCurve() ;
808   }
809   if (aCurve1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))){
810     Handle(Geom2d_BSplineCurve) BSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(aCurve1) ;
811     BSplineCurve->Resolution(tl,
812                              tolerance) ;
813     BSplineCurve->LocateU(u1,
814                           tolerance,
815                           index1,
816                           index2) ;
817     
818     if (index1 > 1 && index2 < BSplineCurve->NbKnots() && index1 == index2) {
819        cont1 = BSplineCurve->Degree() - BSplineCurve->Multiplicity(index1) ;
820     }
821     else {
822       cont1 = 5 ;
823     }
824   }
825   if (aCurve2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))){
826     Handle(Geom2d_BSplineCurve) BSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(aCurve2) ;
827     BSplineCurve->Resolution(tl,
828                              tolerance) ;
829     BSplineCurve->LocateU(u2,
830                           tolerance,
831                           index1,
832                           index2) ;
833     
834     if (index1 > 1 && index2 < BSplineCurve->NbKnots() && index1 == index2) {
835       cont2 = BSplineCurve->Degree() - BSplineCurve->Multiplicity(index1) ;
836     }
837     else {
838       cont2 = 5 ;
839     }
840   }
841   aCurve1->D1(u1,
842               point1,
843               d1) ;
844   aCurve2->D1(u2,
845               point2,
846               d2) ;
847   if (point1.SquareDistance(point2) <= tl * tl) {
848     if (cont1 != 0 &&
849         cont2 != 0) {
850       
851       if (d1.SquareMagnitude() >= tl * tl &&
852           d2.SquareMagnitude() >= tl * tl) {
853         if (r1) {
854           d1.SetCoord(-d1.X(),-d1.Y()) ;
855         }
856         if (r2) {
857           d2.SetCoord(-d2.X(),-d2.Y()) ;
858         }
859         value = d1.Dot(d2) ;
860         if ((d1.Magnitude()<=(d2.Magnitude()+tl))&&
861             (d1.Magnitude()>=(d2.Magnitude()-tl))&&
862             (value/(d1.Magnitude()*d2.Magnitude()) >= 1.0e0 - ta * ta)) {
863           cont = GeomAbs_C1 ;
864         }
865         else {
866           d1.Normalize() ;
867           d2.Normalize() ;
868           value = Abs(d1.Dot(d2)) ;
869           if (value >= 1.0e0 - ta * ta) {
870             cont = GeomAbs_G1 ;
871           }
872         }
873         
874       }
875     }
876   }
877   else
878     Standard_Failure::Raise("Courbes non jointives");
879   return cont ;
880 }
881
882 //=======================================================================
883 //function : Continuity
884 //purpose  : 
885 //=======================================================================
886
887 static GeomAbs_Shape Continuity(const Handle(Geom2d_Curve)& C1, 
888                                 const Handle(Geom2d_Curve)& C2, 
889                                 const Standard_Real u1, 
890                                 const Standard_Real u2,
891                                 const Standard_Boolean r1, 
892                                 const Standard_Boolean r2)
893 {
894   return Continuity(C1,C2,u1,u2,r1,r2,
895                     Precision::Confusion(),Precision::Angular());
896 }
897
898 //=======================================================================
899 //class :reparameterise_evaluator 
900 //purpose  : 
901 //=======================================================================
902
903 class Geom2dConvert_reparameterise_evaluator : public BSplCLib_EvaluatorFunction
904 {
905
906 public:
907
908   Geom2dConvert_reparameterise_evaluator (const Standard_Real thePolynomialCoefficient[3])
909   {
910     memcpy(myPolynomialCoefficient, thePolynomialCoefficient, sizeof(myPolynomialCoefficient));
911   }
912
913   virtual void Evaluate (const Standard_Integer theDerivativeRequest,
914                          const Standard_Real*   /*theStartEnd*/,
915                          const Standard_Real    theParameter,
916                          Standard_Real&         theResult,
917                          Standard_Integer&      theErrorCode) const
918   {
919     theErrorCode = 0;
920     PLib::EvalPolynomial (theParameter,
921                           theDerivativeRequest,
922                           2,
923                           1,
924                           *((Standard_Real* )myPolynomialCoefficient), // function really only read values from this array
925                           theResult);
926   }
927
928 private:
929
930   Standard_Real myPolynomialCoefficient[3];
931
932 };
933
934 //=======================================================================
935 //function : ConcatG1
936 //purpose  : 
937 //=======================================================================
938
939 void  Geom2dConvert::ConcatG1(TColGeom2d_Array1OfBSplineCurve&           ArrayOfCurves, 
940                               const TColStd_Array1OfReal&                ArrayOfToler,
941                               Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
942                               const Standard_Boolean                     ClosedFlag,
943                               const Standard_Real                        ClosedTolerance) 
944
945 {Standard_Integer             nb_curve=ArrayOfCurves.Length(),
946                               nb_vertexG1,
947                               nb_group=0,
948                               index=0,i,ii,j,jj,
949                               indexmin,
950                               nb_vertex_group0=0;
951  Standard_Real                lambda,                      //coeff de raccord G1
952                               First,PreLast=0;
953  gp_Vec2d                     Vec1,Vec2;                   //vecteurs tangents consecutifs
954  gp_Pnt2d                     Pint;
955  Handle(Geom2d_BSplineCurve)  Curve1,Curve2;                       
956  TColStd_Array1OfBoolean      tabG1(0,nb_curve-2);         //tableau de continuite G1 aux raccords
957  TColStd_Array1OfReal         local_tolerance(0,
958                                               ArrayOfToler.Length()-1) ;
959  
960  for (i= 0; i < ArrayOfToler.Length() ; i++) {
961    local_tolerance(i) = ArrayOfToler(i) ;
962  }
963  for (i=0 ;i<nb_curve; i++){
964    if (i >= 1){
965      First=ArrayOfCurves(i)->FirstParameter();
966      if (Continuity(ArrayOfCurves(i-1),
967                     ArrayOfCurves(i),
968                     PreLast,First,
969                     Standard_True,
970                     Standard_True)<GeomAbs_C0)
971        Standard_ConstructionError::Raise("Geom2dConvert curves not C0") ;                //renvoi d'une erreur
972      else{
973        if (Continuity(ArrayOfCurves(i-1),
974                       ArrayOfCurves(i),
975                       PreLast,First,
976                       Standard_True,
977                       Standard_True)>=GeomAbs_G1)
978          tabG1(i-1)=Standard_True;                   //True=Continuite G1
979        else 
980          tabG1(i-1)=Standard_False;
981      }
982    }
983    PreLast=ArrayOfCurves(i)->LastParameter();     
984  }
985  
986
987  while (index<=nb_curve-1){                                 //determination des caracteristiques du Wire
988    nb_vertexG1=0;
989    while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
990      nb_vertexG1++;
991    nb_group++;
992    if (index==0)
993      nb_vertex_group0=nb_vertexG1;
994    index=index+1+nb_vertexG1;
995  }
996  
997  if ((ClosedFlag)&&(nb_group!=1)){                            //rearrangement du tableau
998    nb_group--;
999    ReorderArrayOfG1(ArrayOfCurves,
1000                   local_tolerance,
1001                   tabG1,
1002                   nb_vertex_group0,
1003                   ClosedTolerance);
1004  }
1005
1006  ArrayOfConcatenated = new 
1007    TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1);
1008
1009  Standard_Boolean       fusion;
1010 // Standard_Integer       k=0;
1011  index=0;
1012  Pretreatment(ArrayOfCurves);
1013
1014  Standard_Real aPolynomialCoefficient[3];
1015
1016  if ((nb_group==1) && (ClosedFlag)){                       //traitement d'un cas particulier
1017    indexmin=Indexmin(ArrayOfCurves);
1018    if (indexmin!=(ArrayOfCurves.Length()-1))
1019      ReorderArrayOfG1(ArrayOfCurves,
1020                     local_tolerance,
1021                     tabG1,
1022                     indexmin,
1023                     ClosedTolerance);
1024    Curve2=ArrayOfCurves(0);
1025    for (j=1;j<=nb_curve-1;j++){                //boucle secondaire a l'interieur de chaque groupe
1026      Curve1=ArrayOfCurves(j);
1027      if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){ 
1028        Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1029        Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1030        lambda=Vec2.Magnitude()/Vec1.Magnitude();
1031        TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1032        Curve1->Knots(KnotC1);
1033        Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1034        ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1035        Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1036        Standard_Real tmax,a,b,c,
1037        umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1038        tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1039        a=(lambda*lambda2-1)/(2*lambda*tmax);
1040        aPolynomialCoefficient[2] = a;              
1041        b=(1/lambda); 
1042        aPolynomialCoefficient[1] = b;
1043        c=umin;
1044        aPolynomialCoefficient[0] = c;
1045        TColStd_Array1OfReal  Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1046        TColStd_Array1OfInteger  KnotC1Mults(1,Curve1->NbKnots());
1047        Curve1->Multiplicities(KnotC1Mults);
1048        BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1049        KnotC1(1)=0.0;
1050        for (ii=2;ii<=KnotC1.Length();ii++) {
1051 //       KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1052          KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1053        }
1054        TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles());
1055        Curve1->Poles(Curve1Poles);
1056        
1057        for (ii=1;ii<=Curve1->NbKnots();ii++)
1058          KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1059        
1060        TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1061        
1062        BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1063        TColgp_Array1OfPnt2d NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1064        Standard_Integer      Status;
1065        TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1066        Curve1->Weights(Curve1Weights);
1067        for (ii=1;ii<=Curve1->NbPoles();ii++)
1068          for (jj=1;jj<=2;jj++)
1069            Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1070 //POP pour NT
1071        Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1072        BSplCLib::FunctionReparameterise(ev,
1073                                         Curve1->Degree(),
1074                                         Curve1FlatKnots,
1075                                         Curve1Poles,
1076                                         FlatKnots,
1077                                         2*Curve1->Degree(),
1078                                         NewPoles,
1079                                         Status
1080                                         );
1081        TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1082        BSplCLib::FunctionReparameterise(ev,
1083                                         Curve1->Degree(),
1084                                         Curve1FlatKnots,
1085                                         Curve1Weights,
1086                                         FlatKnots,
1087                                         2*Curve1->Degree(),
1088                                         NewWeights,
1089                                         Status
1090                                         );
1091 //      BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1092 //                                      Curve1->Degree(),
1093 //                                      Curve1FlatKnots,
1094 //                                      Curve1Poles,
1095 //                                      FlatKnots,
1096 //                                      2*Curve1->Degree(),
1097 //                                      NewPoles,
1098 //                                      Status
1099 //                                      );
1100 //       TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1101 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1102 //                                      Curve1->Degree(),
1103 //                                      Curve1FlatKnots,
1104 //                                      Curve1Weights,
1105 //                                      FlatKnots,
1106 //                                      2*Curve1->Degree(),
1107 //                                      NewWeights,
1108 //                                      Status
1109 //                                      );
1110        for (ii=1;ii<=NewPoles.Length();ii++)
1111          for (jj=1;jj<=2;jj++)
1112            NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1113        Curve1= new Geom2d_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
1114      }
1115      Geom2dConvert_CompCurveToBSplineCurve   C(Handle(Geom2d_BSplineCurve)::DownCast(Curve2));
1116      fusion=C.Add(Curve1,
1117                   local_tolerance(j-1));          //fusion de deux courbes adjacentes               
1118      if (fusion==Standard_False)
1119        Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1120      Curve2=C.BSplineCurve();
1121    }
1122    Curve2->SetPeriodic();      //1 seule courbe C1
1123    Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
1124                          Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1125                          Precision::Confusion());
1126    ArrayOfConcatenated->SetValue(0,Curve2);
1127  }
1128  
1129  else
1130    for (i=0;i<=nb_group-1;i++){                             //boucle principale sur chaque groupe de 
1131      nb_vertexG1=0;                                         //continuite interne G1
1132      
1133      while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1134        nb_vertexG1++;
1135       
1136      for (j=index;j<=index+nb_vertexG1;j++){                //boucle secondaire a l'interieur de chaque groupe
1137        Curve1=ArrayOfCurves(j);
1138        
1139        if (index==j)                                      //initialisation en debut de groupe
1140          ArrayOfConcatenated->SetValue(i,Curve1);
1141        else{
1142          Geom2dConvert_CompCurveToBSplineCurve  C(Handle(Geom2d_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(i)));
1143          fusion=C.Add(Curve1,ArrayOfToler(j-1));          //fusion de deux courbes adjacentes               
1144          if (fusion==Standard_False)
1145            Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1146          ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1147        }
1148      }
1149      index=index+1+nb_vertexG1;
1150    }
1151 }  
1152 //=======================================================================
1153 //function : ConcatC1
1154 //purpose  : 
1155 //=======================================================================
1156
1157 void  Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve&           ArrayOfCurves, 
1158                               const TColStd_Array1OfReal&                ArrayOfToler,
1159                               Handle(TColStd_HArray1OfInteger)&          ArrayOfIndices,
1160                               Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1161                               const Standard_Boolean                     ClosedFlag,
1162                               const Standard_Real                        ClosedTolerance) 
1163 {
1164  ConcatC1(ArrayOfCurves,
1165           ArrayOfToler,
1166           ArrayOfIndices,
1167           ArrayOfConcatenated,
1168           ClosedFlag,
1169           ClosedTolerance,
1170           Precision::Angular()) ;
1171 }
1172 //=======================================================================
1173 //function : ConcatC1
1174 //purpose  : 
1175 //=======================================================================
1176
1177 void  Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve&           ArrayOfCurves, 
1178                               const TColStd_Array1OfReal&                ArrayOfToler,
1179                               Handle(TColStd_HArray1OfInteger)&          ArrayOfIndices,
1180                               Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1181                               const Standard_Boolean                     ClosedFlag,
1182                               const Standard_Real                        ClosedTolerance,
1183                               const Standard_Real                        AngularTolerance) 
1184
1185 {Standard_Integer             nb_curve=ArrayOfCurves.Length(),
1186                               nb_vertexG1,
1187                               nb_group=0,
1188                               index=0,i,ii,j,jj,
1189                               indexmin,
1190                               nb_vertex_group0=0;
1191  Standard_Real                lambda,                      //coeff de raccord G1
1192                               First,PreLast=0;
1193  gp_Vec2d                     Vec1,Vec2;                   //vecteurs tangents consecutifs
1194  gp_Pnt2d                     Pint;
1195  Handle(Geom2d_BSplineCurve)  Curve1,Curve2;                       
1196  TColStd_Array1OfBoolean      tabG1(0,nb_curve-2);         //tableau de continuite G1 aux raccords
1197  TColStd_Array1OfReal         local_tolerance(0,
1198                                               ArrayOfToler.Length()-1) ;
1199
1200
1201  
1202  for (i=0 ; i < ArrayOfToler.Length() ; i++) {
1203    local_tolerance(i) = ArrayOfToler(i) ;
1204  }
1205  for (i=0 ;i<nb_curve; i++){
1206    if (i >= 1){
1207      First=ArrayOfCurves(i)->FirstParameter();
1208      if (Continuity(ArrayOfCurves(i-1),
1209                     ArrayOfCurves(i),
1210                     PreLast,First,
1211                     Standard_True,
1212                     Standard_True,
1213                     ArrayOfToler(i-1),
1214                     AngularTolerance)<GeomAbs_C0)
1215        Standard_ConstructionError::Raise("Geom2dConvert curves not C0") ;                //renvoi d'une erreur
1216      else{
1217        if (Continuity(ArrayOfCurves(i-1),
1218                       ArrayOfCurves(i),
1219                       PreLast,
1220                       First,
1221                       Standard_True,
1222                       Standard_True,
1223                       ArrayOfToler(i-1),
1224                       AngularTolerance)>=GeomAbs_G1)
1225          tabG1(i-1)=Standard_True;                   //True=Continuite G1
1226        else 
1227          tabG1(i-1)=Standard_False;
1228      }                               
1229    }
1230    PreLast=ArrayOfCurves(i)->LastParameter();     
1231  }
1232  
1233
1234  while (index<=nb_curve-1){                                 //determination des caracteristiques du Wire
1235    nb_vertexG1=0;
1236    while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1237      nb_vertexG1++;
1238    nb_group++;
1239    if (index==0)
1240      nb_vertex_group0=nb_vertexG1;
1241    index=index+1+nb_vertexG1;
1242  }
1243
1244  if ((ClosedFlag)&&(nb_group!=1)){                            //rearrangement du tableau
1245    nb_group--;
1246    ReorderArrayOfG1(ArrayOfCurves,
1247                   local_tolerance,
1248                   tabG1,
1249                   nb_vertex_group0,
1250                   ClosedTolerance);
1251  }
1252
1253  ArrayOfIndices = new TColStd_HArray1OfInteger(0,nb_group);
1254  ArrayOfConcatenated = new TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1);
1255
1256  Standard_Boolean       fusion;
1257  Standard_Integer       k=0;
1258  index=0;
1259  Pretreatment(ArrayOfCurves);
1260  Standard_Real aPolynomialCoefficient[3];
1261
1262  if ((nb_group==1) && (ClosedFlag)){                       //traitement d'un cas particulier
1263    ArrayOfIndices->SetValue(0,0);
1264    ArrayOfIndices->SetValue(1,0);
1265    indexmin=Indexmin(ArrayOfCurves);
1266    if (indexmin!=(ArrayOfCurves.Length()-1))
1267      ReorderArrayOfG1(ArrayOfCurves,
1268                     local_tolerance,
1269                     tabG1,
1270                     indexmin,
1271                     ClosedTolerance);
1272    for (j=0;j<=nb_curve-1;j++){                //boucle secondaire a l'interieur de chaque groupe
1273      if (NeedToBeTreated(ArrayOfCurves(j))) {
1274        Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1275      }
1276      else
1277        Curve1=ArrayOfCurves(j);
1278      
1279      if (j==0)                                      //initialisation en debut de groupe
1280        Curve2=Curve1;
1281      else{
1282        if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){ 
1283          Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1284          Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1285          lambda=Vec2.Magnitude()/Vec1.Magnitude();
1286          TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1287          Curve1->Knots(KnotC1);
1288          Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1289          ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1290          Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1291          Standard_Real tmax,a,b,c,
1292          umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1293          tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1294          a=(lambda*lambda2-1)/(2*lambda*tmax);
1295          aPolynomialCoefficient[2] = a;
1296          b=(1/lambda); 
1297          aPolynomialCoefficient[1] = b;
1298          c=umin;
1299          aPolynomialCoefficient[0] = c;
1300          TColStd_Array1OfReal  Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1301          TColStd_Array1OfInteger  KnotC1Mults(1,Curve1->NbKnots());
1302          Curve1->Multiplicities(KnotC1Mults);
1303          BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1304          KnotC1(1)=0.0;
1305          for (ii=2;ii<=KnotC1.Length();ii++) {
1306 //         KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1307            KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1308          }
1309          TColgp_Array1OfPnt2d  Curve1Poles(1,Curve1->NbPoles());
1310          Curve1->Poles(Curve1Poles);
1311          
1312          for (ii=1;ii<=Curve1->NbKnots();ii++)
1313            KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1314          
1315          TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1316          
1317          BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1318          TColgp_Array1OfPnt2d  NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1319          Standard_Integer      Status;
1320          TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1321          Curve1->Weights(Curve1Weights);
1322          for (ii=1;ii<=Curve1->NbPoles();ii++)
1323            for (jj=1;jj<=2;jj++)
1324              Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1325 //POP pour NT
1326          Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1327 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1328          BSplCLib::FunctionReparameterise(ev,
1329                                           Curve1->Degree(),
1330                                           Curve1FlatKnots,
1331                                           Curve1Poles,
1332                                           FlatKnots,
1333                                           2*Curve1->Degree(),
1334                                           NewPoles,
1335                                           Status
1336                                           );
1337          TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1338 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1339          BSplCLib::FunctionReparameterise(ev,
1340                                           Curve1->Degree(),
1341                                           Curve1FlatKnots,
1342                                           Curve1Weights,
1343                                           FlatKnots,
1344                                           2*Curve1->Degree(),
1345                                           NewWeights,
1346                                           Status
1347                                           );
1348          for (ii=1;ii<=NewPoles.Length();ii++) {
1349            for (jj=1;jj<=2;jj++)
1350              NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1351          }
1352          Curve1= new Geom2d_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
1353        }
1354        Geom2dConvert_CompCurveToBSplineCurve   C(Handle(Geom2d_BSplineCurve)::DownCast(Curve2));
1355        fusion=C.Add(Curve1,
1356                     local_tolerance(j-1));          //fusion de deux courbes adjacentes               
1357        if (fusion==Standard_False)
1358          Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1359        Curve2=C.BSplineCurve();
1360      }
1361    }
1362    Curve2->SetPeriodic();      //1 seule courbe C1
1363    Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
1364                          Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1365                          Precision::Confusion());
1366    ArrayOfConcatenated->SetValue(0,Curve2);
1367  }
1368  
1369  else
1370    for (i=0;i<=nb_group-1;i++){                             //boucle principale sur chaque groupe de 
1371      nb_vertexG1=0;                                         //continuite interne G1
1372       
1373      while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1374        nb_vertexG1++;
1375       
1376      if ((!ClosedFlag)||(nb_group==1)){                        //remplissage du tableau des indices conserves
1377        k++;
1378        ArrayOfIndices->SetValue(k-1,index);
1379        if (k==nb_group)
1380          ArrayOfIndices->SetValue(k,0);
1381      }
1382      else{
1383        k++;
1384        ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1);
1385        if (k==nb_group)
1386          ArrayOfIndices->SetValue(k,nb_vertex_group0+1);
1387      }
1388       
1389      for (j=index;j<=index+nb_vertexG1;j++){                //boucle secondaire a l'interieur de chaque groupe
1390        if (NeedToBeTreated(ArrayOfCurves(j)))
1391          Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1392        else
1393          Curve1=ArrayOfCurves(j);
1394        
1395        if (index==j)                                      //initialisation en debut de groupe
1396          ArrayOfConcatenated->SetValue(i,Curve1);
1397        else{
1398          Geom2dConvert_CompCurveToBSplineCurve  C(Handle(Geom2d_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(i)));
1399          fusion=C.Add(Curve1,ArrayOfToler(j-1));          //fusion de deux courbes adjacentes               
1400          if (fusion==Standard_False)
1401            Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1402          ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1403        }
1404      }
1405      index=index+1+nb_vertexG1;
1406    }
1407 }
1408
1409 //=======================================================================
1410 //function : C0BSplineToC1BSplineCurve
1411 //purpose  : 
1412 //=======================================================================
1413
1414 void Geom2dConvert::C0BSplineToC1BSplineCurve(Handle(Geom2d_BSplineCurve)& BS,
1415                                               const Standard_Real          tolerance)
1416
1417 {
1418   TColStd_Array1OfInteger          BSMults(1,BS->NbKnots());
1419  TColStd_Array1OfReal             BSKnots(1,BS->NbKnots());
1420  Standard_Integer                 i,j,nbcurveC1=1;
1421  Standard_Real                    U1,U2;
1422  Standard_Boolean                 closed_flag = Standard_False ;
1423  gp_Pnt2d                         point;
1424  gp_Vec2d                         V1,V2;
1425  Standard_Boolean                 fusion;
1426
1427  BS->Knots(BSKnots);
1428  BS->Multiplicities(BSMults);
1429  for (i=BS->FirstUKnotIndex() + 1;i<=(BS->LastUKnotIndex()-1);i++){
1430    if (BSMults(i)==BS->Degree())
1431      nbcurveC1++;   
1432  }
1433
1434   nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1); 
1435
1436  if (nbcurveC1>1){
1437    TColGeom2d_Array1OfBSplineCurve  ArrayOfCurves(0,nbcurveC1-1);
1438    TColStd_Array1OfReal             ArrayOfToler(0,nbcurveC1-2);
1439    
1440    for (i=0;i<=nbcurveC1-2;i++)
1441      ArrayOfToler(i)=tolerance;
1442    U2=BS->FirstParameter() ;
1443    j=BS->FirstUKnotIndex() + 1 ;
1444    for (i=0;i<nbcurveC1;i++){
1445      U1=U2;
1446
1447      while (j < BS->LastUKnotIndex() && BSMults(j) < BS->Degree())
1448        j++;
1449      
1450      U2=BSKnots(j);
1451      j++;
1452      Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy());
1453      BSbis->Segment(U1,U2);
1454      ArrayOfCurves(i)=BSbis;
1455    }
1456    Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1457    Handle(TColGeom2d_HArray1OfBSplineCurve) ArrayOfConcatenated;
1458     
1459    BS->D1(BS->FirstParameter(),point,V1);  //a verifier
1460    BS->D1(BS->LastParameter(),point,V2);
1461    
1462    if ((BS->IsClosed())&&(V1.IsParallel(V2,Precision::Confusion())))
1463      closed_flag = Standard_True ;
1464     
1465    Geom2dConvert::ConcatC1(ArrayOfCurves,
1466                            ArrayOfToler,
1467                            ArrayOfIndices,
1468                            ArrayOfConcatenated,
1469                            closed_flag,
1470                            tolerance);
1471     
1472    Geom2dConvert_CompCurveToBSplineCurve   
1473      C(Handle(Geom2d_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(0)));
1474    if (ArrayOfConcatenated->Length()>=2){
1475      for (i=1;i<ArrayOfConcatenated->Length();i++){
1476        fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance);
1477        if (fusion==Standard_False)
1478          Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1479      }
1480    }
1481    BS=C.BSplineCurve();
1482  }
1483 }
1484 //=======================================================================
1485 //function : C0BSplineToArrayOfC1BSplineCurve
1486 //purpose  : 
1487 //=======================================================================
1488
1489 void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) &        BS,
1490                                                      Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1491                                                      const Standard_Real                        tolerance)
1492   {
1493     C0BSplineToArrayOfC1BSplineCurve(BS,
1494                                      tabBS,
1495                                      tolerance,
1496                                      Precision::Angular());
1497   }
1498 //=======================================================================
1499 //function : C0BSplineToArrayOfC1BSplineCurve
1500 //purpose  : 
1501 //=======================================================================
1502
1503 void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) &        BS,
1504                                                      Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1505                                                      const Standard_Real                        AngularTolerance,
1506                                                      const Standard_Real                        Tolerance) 
1507
1508 {
1509   TColStd_Array1OfInteger          BSMults(1,BS->NbKnots());
1510   TColStd_Array1OfReal             BSKnots(1,BS->NbKnots());
1511   Standard_Integer                 i,j,nbcurveC1=1;
1512   Standard_Real                    U1,U2;
1513   Standard_Boolean                 closed_flag = Standard_False ;
1514   gp_Pnt2d                         point;
1515   gp_Vec2d                         V1,V2;
1516 //  Standard_Boolean                 fusion;
1517   
1518   BS->Knots(BSKnots);
1519   BS->Multiplicities(BSMults);
1520   for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){
1521     if (BSMults(i)==BS->Degree())
1522       nbcurveC1++;   
1523   }
1524   
1525   nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1); 
1526
1527   if (nbcurveC1>1){
1528     TColGeom2d_Array1OfBSplineCurve  ArrayOfCurves(0,nbcurveC1-1);
1529     TColStd_Array1OfReal             ArrayOfToler(0,nbcurveC1-2);
1530     
1531     for (i=0;i<=nbcurveC1-2;i++)
1532       ArrayOfToler(i)=Tolerance;
1533     U2=BS->FirstParameter() ;
1534     j=BS->FirstUKnotIndex()+ 1 ;
1535     for (i=0;i<nbcurveC1;i++){
1536       U1=U2;
1537       while (j < BS->LastUKnotIndex() && BSMults(j)<BS->Degree())
1538         j++;
1539       U2=BSKnots(j);
1540       j++;
1541       Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy());
1542       BSbis->Segment(U1,U2);
1543       ArrayOfCurves(i)=BSbis;
1544     }
1545     
1546     Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1547     
1548     BS->D1(BS->FirstParameter(),point,V1);  
1549     BS->D1(BS->LastParameter(),point,V2);
1550     
1551     if ((BS->IsClosed())&&(V1.IsParallel(V2,AngularTolerance)))
1552       closed_flag = Standard_True ;
1553     
1554     Geom2dConvert::ConcatC1(ArrayOfCurves,
1555                             ArrayOfToler,
1556                             ArrayOfIndices,
1557                             tabBS,
1558                             closed_flag,
1559                             Tolerance,
1560                             AngularTolerance) ;
1561   }
1562   else{
1563     tabBS = new TColGeom2d_HArray1OfBSplineCurve(0,0);
1564     tabBS->SetValue(0,BS);
1565   }
1566 }  
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608