0031029: BRepLib::SameParameter regression in OCCT 7.4 from OCCT 7.3
[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)  throw Standard_DomainError();
137   Standard_Integer FirstK = Min (FromK1, ToK2);
138   Standard_Integer LastK  = Max (FromK1, ToK2);
139   if (FirstK < TheFirst || LastK > TheLast) throw Standard_OutOfRange();
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  throw Standard_ConstructionError();
387     }
388
389     else { throw Standard_DomainError("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  throw Standard_ConstructionError();
453     }
454
455     else { throw Standard_DomainError(); }
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                                      aStatus;
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                              aStatus);
564   BSplCLib::FunctionMultiply(ev,
565                              BS->Degree(),
566                              BSFlatKnots,
567                              BSWeights,
568                              resFlatKnots,
569                              degree,
570                              resDenPoles,
571                              aStatus);
572 //  BSplCLib::FunctionMultiply(law_evaluator,
573 //                           BS->Degree(),
574 //                           BSFlatKnots,
575 //                           BSPoles,
576 //                           resFlatKnots,
577 //                           degree,
578 //                           resNumPoles,
579 //                           aStatus);
580 //  BSplCLib::FunctionMultiply(law_evaluator,
581 //                           BS->Degree(),
582 //                           BSFlatKnots,
583 //                           BSWeights,
584 //                           resFlatKnots,
585 //                           degree,
586 //                           resDenPoles,
587 //                           aStatus);
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     throw Standard_Failure("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                               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        throw Standard_ConstructionError("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  Standard_Boolean NeedDoubleDegRepara = Need2DegRepara(ArrayOfCurves);
1017  if (nb_group==1 && ClosedFlag && NeedDoubleDegRepara)
1018  {
1019    Curve1 = ArrayOfCurves(nb_curve-1);
1020    if (Curve1->Degree() > Geom2d_BSplineCurve::MaxDegree()/2)
1021      ClosedFlag = Standard_False;
1022  }
1023
1024  if ((nb_group==1) && (ClosedFlag)){                       //traitement d'un cas particulier
1025    indexmin=Indexmin(ArrayOfCurves);
1026    if (indexmin!=(ArrayOfCurves.Length()-1))
1027      ReorderArrayOfG1(ArrayOfCurves,
1028                     local_tolerance,
1029                     tabG1,
1030                     indexmin,
1031                     ClosedTolerance);
1032    Curve2=ArrayOfCurves(0);
1033    for (j=1;j<=nb_curve-1;j++){                //boucle secondaire a l'interieur de chaque groupe
1034      Curve1=ArrayOfCurves(j);
1035      if ( (j==(nb_curve-1)) && (NeedDoubleDegRepara)){ 
1036        const Standard_Integer aNewCurveDegree = 2 * Curve1->Degree();
1037        Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1038        Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1039        lambda=Vec2.Magnitude()/Vec1.Magnitude();
1040        TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1041        Curve1->Knots(KnotC1);
1042        Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1043        ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1044        Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1045        Standard_Real tmax,a,b,c,
1046        umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1047        tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1048        a=(lambda*lambda2-1)/(2*lambda*tmax);
1049        aPolynomialCoefficient[2] = a;              
1050        b=(1/lambda); 
1051        aPolynomialCoefficient[1] = b;
1052        c=umin;
1053        aPolynomialCoefficient[0] = c;
1054        TColStd_Array1OfReal  Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1055        TColStd_Array1OfInteger  KnotC1Mults(1,Curve1->NbKnots());
1056        Curve1->Multiplicities(KnotC1Mults);
1057        BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1058        KnotC1(1)=0.0;
1059        for (ii=2;ii<=KnotC1.Length();ii++) {
1060 //       KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1061          KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1062        }
1063        TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles());
1064        Curve1->Poles(Curve1Poles);
1065        
1066        for (ii=1;ii<=Curve1->NbKnots();ii++)
1067          KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1068        
1069        TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1070        
1071        BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1072        TColgp_Array1OfPnt2d NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1073        Standard_Integer      aStatus;
1074        TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1075        Curve1->Weights(Curve1Weights);
1076        for (ii=1;ii<=Curve1->NbPoles();ii++)
1077          for (jj=1;jj<=2;jj++)
1078            Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1079 //POP pour NT
1080        Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1081        BSplCLib::FunctionReparameterise(ev,
1082                                         Curve1->Degree(),
1083                                         Curve1FlatKnots,
1084                                         Curve1Poles,
1085                                         FlatKnots,
1086                                         aNewCurveDegree,
1087                                         NewPoles,
1088                                         aStatus
1089                                         );
1090        TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1091        BSplCLib::FunctionReparameterise(ev,
1092                                         Curve1->Degree(),
1093                                         Curve1FlatKnots,
1094                                         Curve1Weights,
1095                                         FlatKnots,
1096                                         aNewCurveDegree,
1097                                         NewWeights,
1098                                         aStatus
1099                                         );
1100 //      BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1101 //                                      Curve1->Degree(),
1102 //                                      Curve1FlatKnots,
1103 //                                      Curve1Poles,
1104 //                                      FlatKnots,
1105 //                                      2*Curve1->Degree(),
1106 //                                      NewPoles,
1107 //                                      aStatus
1108 //                                      );
1109 //       TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1110 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1111 //                                      Curve1->Degree(),
1112 //                                      Curve1FlatKnots,
1113 //                                      Curve1Weights,
1114 //                                      FlatKnots,
1115 //                                      2*Curve1->Degree(),
1116 //                                      NewWeights,
1117 //                                      aStatus
1118 //                                      );
1119        for (ii=1;ii<=NewPoles.Length();ii++)
1120          for (jj=1;jj<=2;jj++)
1121            NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1122        Curve1 = new Geom2d_BSplineCurve(NewPoles, NewWeights, KnotC1, KnotC1Mults, aNewCurveDegree);
1123      }
1124      Geom2dConvert_CompCurveToBSplineCurve C(Curve2);
1125      fusion=C.Add(Curve1,
1126                   local_tolerance(j-1));          //fusion de deux courbes adjacentes               
1127      if (fusion==Standard_False)
1128        throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
1129      Curve2=C.BSplineCurve();
1130    }
1131    Curve2->SetPeriodic();      //1 seule courbe C1
1132    Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
1133                          Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1134                          Precision::Confusion());
1135    ArrayOfConcatenated->SetValue(0,Curve2);
1136  }
1137  
1138  else
1139    for (i=0;i<=nb_group-1;i++){                             //boucle principale sur chaque groupe de 
1140      nb_vertexG1=0;                                         //continuite interne G1
1141      
1142      while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1143        nb_vertexG1++;
1144       
1145      for (j=index;j<=index+nb_vertexG1;j++){                //boucle secondaire a l'interieur de chaque groupe
1146        Curve1=ArrayOfCurves(j);
1147        
1148        if (index==j)                                      //initialisation en debut de groupe
1149          ArrayOfConcatenated->SetValue(i,Curve1);
1150        else{
1151          Geom2dConvert_CompCurveToBSplineCurve  C(ArrayOfConcatenated->Value(i));
1152          fusion=C.Add(Curve1,ArrayOfToler(j-1));          //fusion de deux courbes adjacentes               
1153          if (fusion==Standard_False)
1154            throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
1155          ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1156        }
1157      }
1158      index=index+1+nb_vertexG1;
1159    }
1160 }  
1161 //=======================================================================
1162 //function : ConcatC1
1163 //purpose  : 
1164 //=======================================================================
1165
1166 void  Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve&           ArrayOfCurves, 
1167                               const TColStd_Array1OfReal&                ArrayOfToler,
1168                               Handle(TColStd_HArray1OfInteger)&          ArrayOfIndices,
1169                               Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1170                               Standard_Boolean&                          ClosedFlag,
1171                               const Standard_Real                        ClosedTolerance) 
1172 {
1173  ConcatC1(ArrayOfCurves,
1174           ArrayOfToler,
1175           ArrayOfIndices,
1176           ArrayOfConcatenated,
1177           ClosedFlag,
1178           ClosedTolerance,
1179           Precision::Angular()) ;
1180 }
1181 //=======================================================================
1182 //function : ConcatC1
1183 //purpose  : 
1184 //=======================================================================
1185
1186 void  Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve&           ArrayOfCurves, 
1187                               const TColStd_Array1OfReal&                ArrayOfToler,
1188                               Handle(TColStd_HArray1OfInteger)&          ArrayOfIndices,
1189                               Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1190                               Standard_Boolean&                          ClosedFlag,
1191                               const Standard_Real                        ClosedTolerance,
1192                               const Standard_Real                        AngularTolerance) 
1193
1194 {Standard_Integer             nb_curve=ArrayOfCurves.Length(),
1195                               nb_vertexG1,
1196                               nb_group=0,
1197                               index=0,i,ii,j,jj,
1198                               indexmin,
1199                               nb_vertex_group0=0;
1200  Standard_Real                lambda,                      //coeff de raccord G1
1201                               First,PreLast=0;
1202  gp_Vec2d                     Vec1,Vec2;                   //vecteurs tangents consecutifs
1203  gp_Pnt2d                     Pint;
1204  Handle(Geom2d_BSplineCurve)  Curve1,Curve2;                       
1205  TColStd_Array1OfBoolean      tabG1(0,nb_curve-2);         //tableau de continuite G1 aux raccords
1206  TColStd_Array1OfReal         local_tolerance(0,
1207                                               ArrayOfToler.Length()-1) ;
1208
1209
1210  
1211  for (i=0 ; i < ArrayOfToler.Length() ; i++) {
1212    local_tolerance(i) = ArrayOfToler(i) ;
1213  }
1214  for (i=0 ;i<nb_curve; i++){
1215    if (i >= 1){
1216      First=ArrayOfCurves(i)->FirstParameter();
1217      if (Continuity(ArrayOfCurves(i-1),
1218                     ArrayOfCurves(i),
1219                     PreLast,First,
1220                     Standard_True,
1221                     Standard_True,
1222                     ArrayOfToler(i-1),
1223                     AngularTolerance)<GeomAbs_C0)
1224        throw Standard_ConstructionError("Geom2dConvert curves not C0") ;                //renvoi d'une erreur
1225      else{
1226        if (Continuity(ArrayOfCurves(i-1),
1227                       ArrayOfCurves(i),
1228                       PreLast,
1229                       First,
1230                       Standard_True,
1231                       Standard_True,
1232                       ArrayOfToler(i-1),
1233                       AngularTolerance)>=GeomAbs_G1)
1234          tabG1(i-1)=Standard_True;                   //True=Continuite G1
1235        else 
1236          tabG1(i-1)=Standard_False;
1237      }                               
1238    }
1239    PreLast=ArrayOfCurves(i)->LastParameter();     
1240  }
1241  
1242
1243  while (index<=nb_curve-1){                                 //determination des caracteristiques du Wire
1244    nb_vertexG1=0;
1245    while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1246      nb_vertexG1++;
1247    nb_group++;
1248    if (index==0)
1249      nb_vertex_group0=nb_vertexG1;
1250    index=index+1+nb_vertexG1;
1251  }
1252
1253  if ((ClosedFlag)&&(nb_group!=1)){                            //rearrangement du tableau
1254    nb_group--;
1255    ReorderArrayOfG1(ArrayOfCurves,
1256                   local_tolerance,
1257                   tabG1,
1258                   nb_vertex_group0,
1259                   ClosedTolerance);
1260  }
1261
1262  ArrayOfIndices = new TColStd_HArray1OfInteger(0,nb_group);
1263  ArrayOfConcatenated = new TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1);
1264
1265  Standard_Boolean       fusion;
1266  Standard_Integer       k=0;
1267  index=0;
1268  Pretreatment(ArrayOfCurves);
1269  Standard_Real aPolynomialCoefficient[3];
1270
1271  Standard_Boolean NeedDoubleDegRepara = Need2DegRepara(ArrayOfCurves);
1272  if (nb_group==1 && ClosedFlag && NeedDoubleDegRepara)
1273  {
1274    Curve1 = ArrayOfCurves(nb_curve-1);
1275    if (Curve1->Degree() > Geom2d_BSplineCurve::MaxDegree()/2)
1276      ClosedFlag = Standard_False;
1277  }
1278
1279  if ((nb_group==1) && (ClosedFlag)){                       //traitement d'un cas particulier
1280    ArrayOfIndices->SetValue(0,0);
1281    ArrayOfIndices->SetValue(1,0);
1282    indexmin=Indexmin(ArrayOfCurves);
1283    if (indexmin!=(ArrayOfCurves.Length()-1))
1284      ReorderArrayOfG1(ArrayOfCurves,
1285                     local_tolerance,
1286                     tabG1,
1287                     indexmin,
1288                     ClosedTolerance);
1289    for (j=0;j<=nb_curve-1;j++){                //boucle secondaire a l'interieur de chaque groupe
1290      if (NeedToBeTreated(ArrayOfCurves(j))) {
1291        Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1292      }
1293      else
1294        Curve1=ArrayOfCurves(j);
1295      
1296      const Standard_Integer aNewCurveDegree = 2 * Curve1->Degree();
1297
1298      if (j==0)                                      //initialisation en debut de groupe
1299        Curve2=Curve1;
1300      else{
1301        if ( (j==(nb_curve-1)) && (NeedDoubleDegRepara)){ 
1302          Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1303          Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1304          lambda=Vec2.Magnitude()/Vec1.Magnitude();
1305          TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1306          Curve1->Knots(KnotC1);
1307          Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1308          ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1309          Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1310          Standard_Real tmax,a,b,c,
1311          umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1312          tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1313          a=(lambda*lambda2-1)/(2*lambda*tmax);
1314          aPolynomialCoefficient[2] = a;
1315          b=(1/lambda); 
1316          aPolynomialCoefficient[1] = b;
1317          c=umin;
1318          aPolynomialCoefficient[0] = c;
1319          TColStd_Array1OfReal  Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1320          TColStd_Array1OfInteger  KnotC1Mults(1,Curve1->NbKnots());
1321          Curve1->Multiplicities(KnotC1Mults);
1322          BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1323          KnotC1(1)=0.0;
1324          for (ii=2;ii<=KnotC1.Length();ii++) {
1325 //         KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1326            KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1327          }
1328          TColgp_Array1OfPnt2d  Curve1Poles(1,Curve1->NbPoles());
1329          Curve1->Poles(Curve1Poles);
1330          
1331          for (ii=1;ii<=Curve1->NbKnots();ii++)
1332            KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1333          
1334          TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1335          
1336          BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1337          TColgp_Array1OfPnt2d  NewPoles(1, FlatKnots.Length() - (aNewCurveDegree + 1));
1338          Standard_Integer      aStatus;
1339          TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1340          Curve1->Weights(Curve1Weights);
1341          for (ii=1;ii<=Curve1->NbPoles();ii++)
1342            for (jj=1;jj<=2;jj++)
1343              Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1344 //POP pour NT
1345          Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1346 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1347          BSplCLib::FunctionReparameterise(ev,
1348                                           Curve1->Degree(),
1349                                           Curve1FlatKnots,
1350                                           Curve1Poles,
1351                                           FlatKnots,
1352                                           aNewCurveDegree,
1353                                           NewPoles,
1354                                           aStatus
1355                                           );
1356          TColStd_Array1OfReal NewWeights(1, FlatKnots.Length() - (aNewCurveDegree + 1));
1357 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1358          BSplCLib::FunctionReparameterise(ev,
1359                                           Curve1->Degree(),
1360                                           Curve1FlatKnots,
1361                                           Curve1Weights,
1362                                           FlatKnots,
1363                                           aNewCurveDegree,
1364                                           NewWeights,
1365                                           aStatus
1366                                           );
1367          for (ii=1;ii<=NewPoles.Length();ii++) {
1368            for (jj=1;jj<=2;jj++)
1369              NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1370          }
1371          Curve1 = new Geom2d_BSplineCurve(NewPoles, NewWeights, KnotC1, KnotC1Mults, aNewCurveDegree);
1372        }
1373        Geom2dConvert_CompCurveToBSplineCurve C(Curve2);
1374        fusion=C.Add(Curve1,
1375                     local_tolerance(j-1));          //fusion de deux courbes adjacentes               
1376        if (fusion==Standard_False)
1377          throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
1378        Curve2=C.BSplineCurve();
1379      }
1380    }
1381    Curve2->SetPeriodic();      //1 seule courbe C1
1382    Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
1383                          Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1384                          Precision::Confusion());
1385    ArrayOfConcatenated->SetValue(0,Curve2);
1386  }
1387  
1388  else
1389    for (i=0;i<=nb_group-1;i++){                             //boucle principale sur chaque groupe de 
1390      nb_vertexG1=0;                                         //continuite interne G1
1391       
1392      while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1393        nb_vertexG1++;
1394       
1395      if ((!ClosedFlag)||(nb_group==1)){                        //remplissage du tableau des indices conserves
1396        k++;
1397        ArrayOfIndices->SetValue(k-1,index);
1398        if (k==nb_group)
1399          ArrayOfIndices->SetValue(k,0);
1400      }
1401      else{
1402        k++;
1403        ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1);
1404        if (k==nb_group)
1405          ArrayOfIndices->SetValue(k,nb_vertex_group0+1);
1406      }
1407       
1408      for (j=index;j<=index+nb_vertexG1;j++){                //boucle secondaire a l'interieur de chaque groupe
1409        if (NeedToBeTreated(ArrayOfCurves(j)))
1410          Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1411        else
1412          Curve1=ArrayOfCurves(j);
1413        
1414        if (index==j)                                      //initialisation en debut de groupe
1415          ArrayOfConcatenated->SetValue(i,Curve1);
1416        else{
1417          Geom2dConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(i));
1418          fusion=C.Add(Curve1,ArrayOfToler(j-1));          //fusion de deux courbes adjacentes               
1419          if (fusion==Standard_False)
1420            throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
1421          ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1422        }
1423      }
1424      index=index+1+nb_vertexG1;
1425    }
1426 }
1427
1428 //=======================================================================
1429 //function : C0BSplineToC1BSplineCurve
1430 //purpose  : 
1431 //=======================================================================
1432
1433 void Geom2dConvert::C0BSplineToC1BSplineCurve(Handle(Geom2d_BSplineCurve)& BS,
1434                                               const Standard_Real          tolerance)
1435
1436 {
1437   TColStd_Array1OfInteger          BSMults(1,BS->NbKnots());
1438  TColStd_Array1OfReal             BSKnots(1,BS->NbKnots());
1439  Standard_Integer                 i,j,nbcurveC1=1;
1440  Standard_Real                    U1,U2;
1441  Standard_Boolean                 closed_flag = Standard_False ;
1442  gp_Pnt2d                         point1, point2;
1443  gp_Vec2d                         V1,V2;
1444  Standard_Boolean                 fusion;
1445
1446  BS->Knots(BSKnots);
1447  BS->Multiplicities(BSMults);
1448  for (i=BS->FirstUKnotIndex() + 1;i<=(BS->LastUKnotIndex()-1);i++){
1449    if (BSMults(i)==BS->Degree())
1450      nbcurveC1++;   
1451  }
1452
1453   nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1); 
1454
1455  if (nbcurveC1>1){
1456    TColGeom2d_Array1OfBSplineCurve  ArrayOfCurves(0,nbcurveC1-1);
1457    TColStd_Array1OfReal             ArrayOfToler(0,nbcurveC1-2);
1458    
1459    for (i=0;i<=nbcurveC1-2;i++)
1460      ArrayOfToler(i)=tolerance;
1461    U2=BS->FirstParameter() ;
1462    j=BS->FirstUKnotIndex() + 1 ;
1463    for (i=0;i<nbcurveC1;i++){
1464      U1=U2;
1465
1466      while (j < BS->LastUKnotIndex() && BSMults(j) < BS->Degree())
1467        j++;
1468      
1469      U2=BSKnots(j);
1470      j++;
1471      Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy());
1472      BSbis->Segment(U1,U2);
1473      ArrayOfCurves(i)=BSbis;
1474    }
1475
1476    const Standard_Real anAngularToler = 1.0e-7;
1477    Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1478    Handle(TColGeom2d_HArray1OfBSplineCurve) ArrayOfConcatenated;
1479     
1480    BS->D1(BS->FirstParameter(),point1,V1);  //a verifier
1481    BS->D1(BS->LastParameter(),point2,V2);
1482
1483    if ((point1.SquareDistance(point2) < tolerance * tolerance) &&
1484        (V1.IsParallel(V2, anAngularToler)))
1485    {
1486      closed_flag = Standard_True;
1487    }
1488
1489    Geom2dConvert::ConcatC1(ArrayOfCurves,
1490                            ArrayOfToler,
1491                            ArrayOfIndices,
1492                            ArrayOfConcatenated,
1493                            closed_flag,
1494                            tolerance);
1495     
1496    Geom2dConvert_CompCurveToBSplineCurve C(ArrayOfConcatenated->Value(0));
1497    if (ArrayOfConcatenated->Length()>=2){
1498      for (i=1;i<ArrayOfConcatenated->Length();i++){
1499        fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance, Standard_True);
1500        if (fusion==Standard_False)
1501          throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ;
1502      }
1503    }
1504    BS=C.BSplineCurve();
1505  }
1506 }
1507 //=======================================================================
1508 //function : C0BSplineToArrayOfC1BSplineCurve
1509 //purpose  : 
1510 //=======================================================================
1511
1512 void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) &        BS,
1513                                                      Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1514                                                      const Standard_Real                        tolerance)
1515   {
1516     C0BSplineToArrayOfC1BSplineCurve(BS,
1517                                      tabBS,
1518                                      tolerance,
1519                                      Precision::Angular());
1520   }
1521 //=======================================================================
1522 //function : C0BSplineToArrayOfC1BSplineCurve
1523 //purpose  : 
1524 //=======================================================================
1525
1526 void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) &        BS,
1527                                                      Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1528                                                      const Standard_Real                        AngularTolerance,
1529                                                      const Standard_Real                        Tolerance) 
1530
1531 {
1532   TColStd_Array1OfInteger          BSMults(1,BS->NbKnots());
1533   TColStd_Array1OfReal             BSKnots(1,BS->NbKnots());
1534   Standard_Integer                 i,j,nbcurveC1=1;
1535   Standard_Real                    U1,U2;
1536   Standard_Boolean                 closed_flag = Standard_False ;
1537   gp_Pnt2d                         point1, point2;
1538   gp_Vec2d                         V1,V2;
1539 //  Standard_Boolean                 fusion;
1540   
1541   BS->Knots(BSKnots);
1542   BS->Multiplicities(BSMults);
1543   for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){
1544     if (BSMults(i)==BS->Degree())
1545       nbcurveC1++;   
1546   }
1547   
1548   nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1); 
1549
1550   if (nbcurveC1>1){
1551     TColGeom2d_Array1OfBSplineCurve  ArrayOfCurves(0,nbcurveC1-1);
1552     TColStd_Array1OfReal             ArrayOfToler(0,nbcurveC1-2);
1553     
1554     for (i=0;i<=nbcurveC1-2;i++)
1555       ArrayOfToler(i)=Tolerance;
1556     U2=BS->FirstParameter() ;
1557     j=BS->FirstUKnotIndex()+ 1 ;
1558     for (i=0;i<nbcurveC1;i++){
1559       U1=U2;
1560       while (j < BS->LastUKnotIndex() && BSMults(j)<BS->Degree())
1561         j++;
1562       U2=BSKnots(j);
1563       j++;
1564       Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy());
1565       BSbis->Segment(U1,U2);
1566       ArrayOfCurves(i)=BSbis;
1567     }
1568     
1569     Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1570     
1571     BS->D1(BS->FirstParameter(),point1,V1);  
1572     BS->D1(BS->LastParameter(),point2,V2);
1573     
1574     if (((point1.SquareDistance(point2) < Tolerance)) &&
1575         (V1.IsParallel(V2, AngularTolerance)))
1576     {
1577       closed_flag = Standard_True;
1578     }
1579     
1580     Geom2dConvert::ConcatC1(ArrayOfCurves,
1581                             ArrayOfToler,
1582                             ArrayOfIndices,
1583                             tabBS,
1584                             closed_flag,
1585                             Tolerance,
1586                             AngularTolerance) ;
1587   }
1588   else{
1589     tabBS = new TColGeom2d_HArray1OfBSplineCurve(0,0);
1590     tabBS->SetValue(0,BS);
1591   }
1592 }  
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634