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