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