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