0027104: DownCast() cannot return null for mismatched handle
[occt.git] / src / GeomConvert / GeomConvert.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 + Debug
17 // Modif JCV correction bug le 2/08/1993
18
19 #include <BSplCLib.hxx>
20 #include <Convert_CircleToBSplineCurve.hxx>
21 #include <Convert_ConicToBSplineCurve.hxx>
22 #include <Convert_EllipseToBSplineCurve.hxx>
23 #include <Convert_HyperbolaToBSplineCurve.hxx>
24 #include <Convert_ParabolaToBSplineCurve.hxx>
25 #include <ElCLib.hxx>
26 #include <Geom2d_BSplineCurve.hxx>
27 #include <Geom_BezierCurve.hxx>
28 #include <Geom_BSplineCurve.hxx>
29 #include <Geom_BSplineSurface.hxx>
30 #include <Geom_Circle.hxx>
31 #include <Geom_Conic.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_Ellipse.hxx>
34 #include <Geom_Geometry.hxx>
35 #include <Geom_Hyperbola.hxx>
36 #include <Geom_Line.hxx>
37 #include <Geom_OffsetCurve.hxx>
38 #include <Geom_Parabola.hxx>
39 #include <Geom_Surface.hxx>
40 #include <Geom_TrimmedCurve.hxx>
41 #include <GeomConvert.hxx>
42 #include <GeomConvert_ApproxCurve.hxx>
43 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
44 #include <GeomLProp.hxx>
45 #include <gp.hxx>
46 #include <gp_Ax3.hxx>
47 #include <gp_Circ2d.hxx>
48 #include <gp_Elips2d.hxx>
49 #include <gp_Hypr2d.hxx>
50 #include <gp_Lin.hxx>
51 #include <gp_Parab2d.hxx>
52 #include <gp_Pnt.hxx>
53 #include <gp_Pnt2d.hxx>
54 #include <gp_Trsf.hxx>
55 #include <gp_Vec.hxx>
56 #include <Hermit.hxx>
57 #include <PLib.hxx>
58 #include <Precision.hxx>
59 #include <Standard_ConstructionError.hxx>
60 #include <Standard_DomainError.hxx>
61 #include <TColGeom_Array1OfCurve.hxx>
62 #include <TColgp_Array1OfPnt.hxx>
63 #include <TColgp_Array1OfPnt2d.hxx>
64 #include <TColStd_Array1OfBoolean.hxx>
65 #include <TColStd_Array1OfInteger.hxx>
66 #include <TColStd_Array1OfReal.hxx>
67 #include <TColStd_HArray1OfInteger.hxx>
68 #include <TColStd_HArray1OfReal.hxx>
69
70 //=======================================================================
71 //function : BSplineCurveBuilder
72 //purpose  : 
73 //=======================================================================
74 static Handle(Geom_BSplineCurve) BSplineCurveBuilder 
75        (const Handle(Geom_Conic)&          TheConic,
76         const Convert_ConicToBSplineCurve& Convert) 
77
78 {
79   Handle(Geom_BSplineCurve) TheCurve;
80   Standard_Integer NbPoles = Convert.NbPoles();
81   Standard_Integer NbKnots = Convert.NbKnots();
82   TColgp_Array1OfPnt      Poles   (1, NbPoles);
83   TColStd_Array1OfReal    Weights (1, NbPoles);
84   TColStd_Array1OfReal    Knots   (1, NbKnots);
85   TColStd_Array1OfInteger Mults   (1, NbKnots);
86   Standard_Integer i;
87   gp_Pnt2d P2d;
88   gp_Pnt   P3d;
89   for (i = 1; i <= NbPoles; i++) {
90     P2d = Convert.Pole (i);
91     P3d.SetCoord (P2d.X(), P2d.Y(), 0.0);
92     Poles (i) = P3d;
93     Weights (i) = Convert.Weight (i);         
94   }
95   for (i = 1; i <= NbKnots; i++) {
96     Knots (i) = Convert.Knot (i);
97     Mults (i) = Convert.Multiplicity (i);
98   }
99   TheCurve = 
100     new Geom_BSplineCurve (Poles, Weights, Knots, Mults, 
101                            Convert.Degree(), Convert.IsPeriodic());
102   gp_Trsf T;
103   T.SetTransformation (TheConic->Position(), gp::XOY());
104   Handle(Geom_BSplineCurve) Cres;
105   Cres = Handle(Geom_BSplineCurve)::DownCast(TheCurve->Transformed (T));
106   return Cres;
107 }
108
109
110
111 //=======================================================================
112 //function : SplitBSplineCurve
113 //purpose  : 
114 //=======================================================================
115
116 Handle(Geom_BSplineCurve) GeomConvert::SplitBSplineCurve 
117   (const Handle(Geom_BSplineCurve)& C,
118    const Standard_Integer               FromK1, 
119    const Standard_Integer               ToK2,
120    const Standard_Boolean               SameOrientation) 
121 {
122   Standard_Integer TheFirst = C->FirstUKnotIndex ();
123   Standard_Integer TheLast  = C->LastUKnotIndex ();
124   if (FromK1 == ToK2)  Standard_DomainError::Raise();
125   Standard_Integer FirstK = Min (FromK1, ToK2);
126   Standard_Integer LastK  = Max (FromK1, ToK2);
127   if (FirstK < TheFirst || LastK > TheLast) Standard_DomainError::Raise();
128
129   Handle(Geom_BSplineCurve) C1
130     = Handle(Geom_BSplineCurve)::DownCast(C->Copy ());
131
132   C1->Segment( C->Knot(FirstK),C->Knot(LastK));
133
134   if (C->IsPeriodic()) {
135     if (!SameOrientation) C1->Reverse();
136   }
137   else {
138     if (FromK1 > ToK2)    C1->Reverse();
139   }
140   return C1;
141 }
142
143
144 //=======================================================================
145 //function : SplitBSplineCurve
146 //purpose  : 
147 //=======================================================================
148
149 Handle(Geom_BSplineCurve) GeomConvert::SplitBSplineCurve 
150   (const Handle(Geom_BSplineCurve)& C, 
151    const Standard_Real              FromU1, 
152    const Standard_Real              ToU2,
153    const Standard_Real              , //ParametricTolerance,
154    const Standard_Boolean            SameOrientation    ) 
155 {
156   Standard_Real FirstU = Min( FromU1, ToU2);
157   Standard_Real LastU  = Max( FromU1, ToU2);
158
159   Handle (Geom_BSplineCurve) C1 
160     = Handle(Geom_BSplineCurve)::DownCast(C->Copy());
161
162   C1->Segment(FirstU, LastU);
163
164   if (C->IsPeriodic()) {
165      if (!SameOrientation) C1->Reverse();
166    }
167   else {
168     if (FromU1 > ToU2)    C1->Reverse();
169   }
170
171   return C1;
172 }
173
174
175
176
177 //=======================================================================
178 //function : CurveToBSplineCurve
179 //purpose  : 
180 //=======================================================================
181
182 Handle(Geom_BSplineCurve)  GeomConvert::CurveToBSplineCurve 
183   (const Handle(Geom_Curve)&          C,
184    const Convert_ParameterisationType Parameterisation) 
185 {
186   Handle (Geom_BSplineCurve) TheCurve;
187
188   if (C->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
189     Handle(Geom_Curve) Curv;
190     Handle(Geom_TrimmedCurve) Ctrim = Handle(Geom_TrimmedCurve)::DownCast(C);
191     Curv = Ctrim->BasisCurve();
192     Standard_Real U1 = Ctrim->FirstParameter();
193     Standard_Real U2 = Ctrim->LastParameter();
194
195     // Si la courbe n'est pas vraiment restreinte, on ne risque pas 
196     // le Raise dans le BS->Segment.
197     if (!Curv->IsPeriodic()) {
198       if (U1 < Curv->FirstParameter())
199         U1 =  Curv->FirstParameter();
200       if (U2 > Curv->LastParameter())
201         U2 = Curv->LastParameter();
202     }
203
204     if (Curv->IsKind(STANDARD_TYPE(Geom_Line))) {
205        gp_Pnt Pdeb = Ctrim->StartPoint();
206        gp_Pnt Pfin = Ctrim->EndPoint();
207        TColgp_Array1OfPnt Poles (1, 2);
208        Poles (1) = Pdeb;
209        Poles (2) = Pfin;
210        TColStd_Array1OfReal Knots (1, 2);
211        Knots (1) = Ctrim->FirstParameter ();
212        Knots (2) = Ctrim->LastParameter  ();
213        TColStd_Array1OfInteger Mults (1, 2);
214        Mults (1) = 2;
215        Mults (2) = 2;
216        Standard_Integer Degree = 1;
217        TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
218     }
219
220     else if (Curv->IsKind(STANDARD_TYPE(Geom_Circle))) {
221       Handle(Geom_Circle) TheConic = Handle(Geom_Circle)::DownCast(Curv);
222       gp_Circ2d C2d (gp::OX2d(), TheConic->Radius());
223       if(Parameterisation != Convert_RationalC1) {
224         Convert_CircleToBSplineCurve Convert (C2d,
225                                               U1, 
226                                               U2, 
227                                               Parameterisation);
228         TheCurve = BSplineCurveBuilder (TheConic, Convert);
229       }
230       else {
231         if(U2 - U1 < 6.) {
232           Convert_CircleToBSplineCurve Convert (C2d,
233                                                 U1, 
234                                                 U2, 
235                                                 Parameterisation);
236           TheCurve = BSplineCurveBuilder (TheConic, Convert);
237         }
238         else { // split circle to avoide numerical 
239                // overflow when U2 - U1 =~ 2*PI
240
241           Standard_Real Umed = (U1 + U2) * .5;
242           Convert_CircleToBSplineCurve Convert1 (C2d, 
243                                                  U1, 
244                                                  Umed, 
245                                                  Parameterisation);
246
247           Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
248
249           Convert_CircleToBSplineCurve Convert2 (C2d, 
250                                                  Umed, 
251                                                  U2, 
252                                                  Parameterisation);
253
254           Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
255
256           GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
257                                                       Parameterisation);
258
259           CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
260
261           
262           TheCurve = CCTBSpl.BSplineCurve();
263         }
264       }
265
266     }
267
268     else if (Curv->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
269       Handle(Geom_Ellipse) TheConic = Handle(Geom_Ellipse)::DownCast(Curv);
270       gp_Elips2d E2d (gp::OX2d(),
271                       TheConic->MajorRadius(),
272                       TheConic->MinorRadius());
273       if(Parameterisation != Convert_RationalC1) {
274         Convert_EllipseToBSplineCurve Convert (E2d, 
275                                                U1, 
276                                                U2,
277                                                Parameterisation);
278         TheCurve = BSplineCurveBuilder (TheConic, Convert);
279       }
280       else {
281         if(U2 - U1 < 6.) {
282           Convert_EllipseToBSplineCurve Convert (E2d, 
283                                                  U1, 
284                                                  U2,
285                                                  Parameterisation);
286           TheCurve = BSplineCurveBuilder (TheConic, Convert);
287         }       
288         else { // split ellipse to avoide numerical 
289                // overflow when U2 - U1 =~ 2*PI
290
291           Standard_Real Umed = (U1 + U2) * .5;
292           Convert_EllipseToBSplineCurve Convert1 (E2d, 
293                                                   U1, 
294                                                   Umed, 
295                                                   Parameterisation);
296
297           Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
298
299           Convert_EllipseToBSplineCurve Convert2 (E2d, 
300                                                 Umed, 
301                                                 U2, 
302                                                 Parameterisation);
303
304           Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
305
306           GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
307                                                       Parameterisation);
308
309           CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
310
311           
312           TheCurve = CCTBSpl.BSplineCurve();
313         }
314       }
315     }
316
317     else if (Curv->IsKind(STANDARD_TYPE(Geom_Hyperbola))) {
318       Handle(Geom_Hyperbola) TheConic = Handle(Geom_Hyperbola)::DownCast(Curv);
319       gp_Hypr2d H2d (gp::OX2d(), 
320                      TheConic->MajorRadius(), TheConic->MinorRadius());
321       Convert_HyperbolaToBSplineCurve Convert (H2d, U1, U2);
322       TheCurve = BSplineCurveBuilder (TheConic, Convert);
323     }
324
325     else if (Curv->IsKind(STANDARD_TYPE(Geom_Parabola))) {
326       Handle(Geom_Parabola) TheConic = Handle(Geom_Parabola)::DownCast(Curv);
327       gp_Parab2d Prb2d (gp::OX2d(), TheConic->Focal());
328       Convert_ParabolaToBSplineCurve Convert (Prb2d, U1, U2);
329       TheCurve = BSplineCurveBuilder (TheConic, Convert);
330     }
331
332     else if (Curv->IsKind (STANDARD_TYPE(Geom_BezierCurve))) {
333  
334       Handle(Geom_BezierCurve) CBez 
335         = Handle(Geom_BezierCurve)::DownCast(Curv->Copy());
336       CBez->Segment (U1, U2);
337       Standard_Integer NbPoles = CBez->NbPoles();
338       Standard_Integer Degree  = CBez->Degree();
339       TColgp_Array1OfPnt     Poles   (1, NbPoles);
340       TColStd_Array1OfReal    Knots   (1, 2);
341       TColStd_Array1OfInteger Mults   (1, 2);
342       Knots (1) = 0.0;
343       Knots (2) = 1.0;
344       Mults (1) = Degree + 1;
345       Mults (2) = Degree + 1;
346       CBez->Poles (Poles);
347       if (CBez->IsRational()) {    
348         TColStd_Array1OfReal    Weights (1, NbPoles);
349         CBez->Weights (Weights);
350         TheCurve = 
351           new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree);
352       }
353       else {
354         TheCurve = 
355           new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
356       }
357     }
358     else if (Curv->IsKind (STANDARD_TYPE(Geom_BSplineCurve))) {
359       TheCurve = Handle(Geom_BSplineCurve)::DownCast(Curv->Copy());
360       //// modified by jgv, 14.01.05 for OCC7355 ////
361       if (TheCurve->IsPeriodic())
362         {
363           Standard_Real Uf = TheCurve->FirstParameter();
364           Standard_Real Ul = TheCurve->LastParameter();
365           ElCLib::AdjustPeriodic( Uf, Ul, Precision::Confusion(), U1, U2 );
366           if (Abs(U1 - Uf) <= Precision::Confusion() &&
367               Abs(U2 - Ul) <= Precision::Confusion())
368             TheCurve->SetNotPeriodic();
369         }
370       ///////////////////////////////////////////////
371       TheCurve->Segment(U1,U2);
372     }
373     else if (Curv->IsKind (STANDARD_TYPE(Geom_OffsetCurve))) {
374      Standard_Real Tol3d = 1.e-4;
375      GeomAbs_Shape Order = GeomAbs_C2;
376      Standard_Integer MaxSegments = 16, MaxDegree = 14; 
377      GeomConvert_ApproxCurve ApprCOffs(C, Tol3d, Order, 
378                                          MaxSegments, MaxDegree);
379      if (ApprCOffs.HasResult())
380        TheCurve = ApprCOffs.Curve();
381      else  Standard_ConstructionError::Raise();
382     }
383     else { Standard_DomainError::Raise("No such curve"); }
384   }
385
386   else { 
387     if (C->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
388       Handle(Geom_Ellipse) TheConic= Handle(Geom_Ellipse)::DownCast(C);
389       gp_Elips2d E2d (gp::OX2d(), 
390                       TheConic->MajorRadius(), TheConic->MinorRadius());
391 /*      if (Parameterisation == Convert_TgtThetaOver2_1 ||
392           Parameterisation == Convert_TgtThetaOver2_2) {
393         Standard_DomainError::Raise(); }
394  
395       else if ( Parameterisation == Convert_QuasiAngular) {
396         Convert_EllipseToBSplineCurve Convert (E2d,
397                                                0.0e0,
398                                                2.0e0 * M_PI,
399                                                Parameterisation);
400
401         TheCurve = BSplineCurveBuilder (TheConic, Convert);
402         TheCurve->SetPeriodic();
403       }
404       else {*/
405         Convert_EllipseToBSplineCurve Convert (E2d,
406                                               Parameterisation);
407         TheCurve = BSplineCurveBuilder (TheConic, Convert);
408         TheCurve->SetPeriodic(); // pour polynomial et quasi angular
409 //      }
410     }
411     
412     else if (C->IsKind(STANDARD_TYPE(Geom_Circle))) {
413       Handle(Geom_Circle) TheConic = Handle(Geom_Circle)::DownCast(C);
414       gp_Circ2d C2d (gp::OX2d(), TheConic->Radius());
415 /*      if (Parameterisation == Convert_TgtThetaOver2_1 ||
416           Parameterisation == Convert_TgtThetaOver2_2) {
417         Standard_DomainError::Raise(); }
418  
419       else if ( Parameterisation == Convert_QuasiAngular) {
420         Convert_CircleToBSplineCurve Convert (C2d,
421                                               0.0e0,
422                                               2.0e0 * M_PI,
423                                               Parameterisation);
424         
425         TheCurve = BSplineCurveBuilder (TheConic, Convert);                                  
426       }
427       else {*/
428         Convert_CircleToBSplineCurve Convert (C2d,
429                                               Parameterisation);
430         TheCurve = BSplineCurveBuilder (TheConic, Convert);
431         TheCurve->SetPeriodic();
432 //      }
433     }
434     
435     else if (C->IsKind (STANDARD_TYPE(Geom_BezierCurve))) {
436       Handle(Geom_BezierCurve) CBez= Handle(Geom_BezierCurve)::DownCast(C);
437       Standard_Integer NbPoles = CBez->NbPoles();
438       Standard_Integer Degree  = CBez->Degree();
439       TColgp_Array1OfPnt     Poles   (1, NbPoles);
440       TColStd_Array1OfReal    Knots   (1, 2);
441       TColStd_Array1OfInteger Mults   (1, 2);
442       Knots (1) = 0.0;
443       Knots (2) = 1.0;
444       Mults (1) = Degree + 1;
445       Mults (2) = Degree + 1;
446       CBez->Poles (Poles);
447       if (CBez->IsRational()) {    
448         TColStd_Array1OfReal    Weights (1, NbPoles);
449         CBez->Weights (Weights);
450         TheCurve = 
451           new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree);
452       }
453       else {
454         TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
455       }
456     }
457     
458     else if (C->IsKind (STANDARD_TYPE(Geom_BSplineCurve))) {
459       TheCurve = Handle(Geom_BSplineCurve)::DownCast(C->Copy());
460     }
461
462     else if (C->IsKind (STANDARD_TYPE(Geom_OffsetCurve))) {
463      Standard_Real Tol3d = 1.e-4;
464      GeomAbs_Shape Order = GeomAbs_C2;
465      Standard_Integer MaxSegments = 16, MaxDegree = 14; 
466      GeomConvert_ApproxCurve ApprCOffs(C, Tol3d, Order, 
467                                          MaxSegments, MaxDegree);
468      if (ApprCOffs.HasResult())
469        TheCurve = ApprCOffs.Curve();
470      else  Standard_ConstructionError::Raise();
471    }
472     else { Standard_DomainError::Raise("No such curve"); }
473   }
474   
475   return TheCurve;
476 }
477
478
479 //=======================================================================
480 //class : law_evaluator
481 //purpose  : usefull to estimate the value of a function
482 //=======================================================================
483
484 class GeomConvert_law_evaluator : public BSplCLib_EvaluatorFunction
485 {
486
487 public:
488
489   GeomConvert_law_evaluator (const Handle(Geom2d_BSplineCurve)& theAncore)
490   : myAncore (theAncore) {}
491
492   virtual void Evaluate (const Standard_Integer theDerivativeRequest,
493                          const Standard_Real*   theStartEnd,
494                          const Standard_Real    theParameter,
495                          Standard_Real&         theResult,
496                          Standard_Integer&      theErrorCode) const
497   {
498     theErrorCode = 0;
499     if (!myAncore.IsNull() &&
500         theParameter >= theStartEnd[0] &&
501         theParameter <= theStartEnd[1] && 
502         theDerivativeRequest == 0)
503     {
504       gp_Pnt2d aPoint;
505       myAncore->D0 (theParameter, aPoint);
506       theResult = aPoint.Coord(2);
507     }    
508     else 
509       theErrorCode = 1;
510   }
511
512 private:
513
514   Handle(Geom2d_BSplineCurve) myAncore;
515
516 };
517
518 //=======================================================================
519 //function : MultNumandDenom
520 //purpose  : Multiply two BSpline curves to make one
521 //=======================================================================
522
523
524 static Handle(Geom_BSplineCurve) MultNumandDenom(const Handle(Geom2d_BSplineCurve)& a ,
525                                                  const Handle(Geom_BSplineCurve)&   BS )
526      
527 { TColStd_Array1OfReal               aKnots(1,a->NbKnots());
528   TColStd_Array1OfReal               BSKnots(1,BS->NbKnots());
529   TColStd_Array1OfReal               BSFlatKnots(1,BS->NbPoles()+BS->Degree()+1);
530   TColStd_Array1OfReal               BSWeights(1,BS->NbPoles()); 
531   TColStd_Array1OfInteger            aMults(1,a->NbKnots());
532   TColStd_Array1OfInteger            BSMults(1,BS->NbKnots());
533   TColgp_Array1OfPnt2d               aPoles(1,a->NbPoles());
534   TColgp_Array1OfPnt                 BSPoles(1,BS->NbPoles());
535   Handle(Geom_BSplineCurve)          res;
536   Handle(TColStd_HArray1OfReal)      resKnots;
537   Handle(TColStd_HArray1OfInteger)   resMults; 
538   Standard_Real                      start_value,end_value;
539   Standard_Real                      tolerance=Precision::PConfusion();
540   Standard_Integer                   resNbPoles,degree,
541                                      ii,jj,
542                                      Status;
543   
544   BS->Knots(BSKnots);            //storage of the two BSpline 
545   BS->Multiplicities(BSMults);   //features
546   BS->Poles(BSPoles);
547   BS->Weights(BSWeights);
548   BS->KnotSequence(BSFlatKnots);
549   start_value = BSKnots(1);
550   end_value = BSKnots(BS->NbKnots());
551   if ((end_value - start_value)/5 < tolerance) 
552     tolerance = (end_value - start_value)/5;
553
554   a->Knots(aKnots);
555   a->Poles(aPoles);
556   a->Multiplicities(aMults);
557   BSplCLib::Reparametrize(BS->FirstParameter(),BS->LastParameter(),aKnots);
558   Handle(Geom2d_BSplineCurve) anAncore = new Geom2d_BSplineCurve (aPoles, aKnots, aMults, a->Degree());
559
560   BSplCLib::MergeBSplineKnots(tolerance,start_value,end_value, //merge of the knots
561                               a->Degree(),aKnots,aMults,
562                               BS->Degree(),BSKnots,BSMults,
563                               resNbPoles,resKnots,resMults);
564   degree=BS->Degree()+a->Degree();
565   TColgp_Array1OfPnt resNumPoles(1,resNbPoles);
566   TColStd_Array1OfReal resDenPoles(1,resNbPoles);
567   TColgp_Array1OfPnt resPoles(1,resNbPoles);
568   TColStd_Array1OfReal resFlatKnots(1,resNbPoles+degree+1);
569   BSplCLib::KnotSequence(resKnots->Array1(),resMults->Array1(),resFlatKnots);
570   for (ii=1;ii<=BS->NbPoles();ii++)
571     for (jj=1;jj<=3;jj++)
572       BSPoles(ii).SetCoord(jj,BSPoles(ii).Coord(jj)*BSWeights(ii));
573 //POP pour WNT
574   GeomConvert_law_evaluator ev (anAncore);
575
576   BSplCLib::FunctionMultiply(ev,                             
577                              BS->Degree(),
578                              BSFlatKnots,
579                              BSPoles,
580                              resFlatKnots,
581                              degree,
582                              resNumPoles,
583                              Status);
584
585   BSplCLib::FunctionMultiply(ev,
586                              BS->Degree(),
587                              BSFlatKnots,
588                              BSWeights,
589                              resFlatKnots,
590                              degree,
591                              resDenPoles,
592                              Status);
593   for (ii=1;ii<=resNbPoles;ii++)
594     for(jj=1;jj<=3;jj++) 
595       resPoles(ii).SetCoord(jj,resNumPoles(ii).Coord(jj)/resDenPoles(ii));
596   res = new Geom_BSplineCurve(resPoles,resDenPoles,resKnots->Array1(),resMults->Array1(),degree);
597   return res;
598 }
599
600 //=======================================================================
601 //function : Pretreatment 
602 //purpose  : Put the two first and two last weigths at one if they are 
603 //           equal
604 //=======================================================================
605
606 static void Pretreatment(TColGeom_Array1OfBSplineCurve& tab)
607
608 {Standard_Integer i,j;
609  Standard_Real a;
610
611  for (i=0;i<=(tab.Length()-1);i++){
612    if (tab(i)->IsRational()) {
613      a=tab(i)->Weight(1);                                 
614      if ((tab(i)->Weight(2)==a)&&
615          (tab(i)->Weight(tab(i)->NbPoles()-1)==a)&&
616          (tab(i)->Weight(tab(i)->NbPoles())==a))
617        
618        for (j=1;j<=tab(i)->NbPoles();j++)
619          tab(i)->SetWeight(j,tab(i)->Weight(j)/a);
620    }
621  }
622 }
623          
624 //=======================================================================
625 //function : NeedToBeTreated
626 //purpose  : Say if the BSpline is rationnal and if the two first and two
627 //           last weigths are different
628 //=======================================================================    
629
630 static Standard_Boolean NeedToBeTreated(const Handle(Geom_BSplineCurve)& BS)
631
632 {
633   TColStd_Array1OfReal  tabWeights(1,BS->NbPoles());
634   if (BS->IsRational()) {
635     BS->Weights(tabWeights);
636     if ((BSplCLib::IsRational(tabWeights,1,BS->NbPoles()))&&
637         ((BS->Weight(1)<(1-Precision::Confusion()))||
638          (BS->Weight(1)>(1+Precision::Confusion()))||
639          (BS->Weight(2)<(1-Precision::Confusion()))||
640          (BS->Weight(2)>(1+Precision::Confusion()))||
641          (BS->Weight(BS->NbPoles()-1)<(1-Precision::Confusion()))||
642          (BS->Weight(BS->NbPoles()-1)>(1+Precision::Confusion()))||
643          (BS->Weight(BS->NbPoles())<(1-Precision::Confusion()))||
644          (BS->Weight(BS->NbPoles())>(1+Precision::Confusion()))))
645       return Standard_True;
646     else
647       return Standard_False;
648   }
649   else 
650     return Standard_False ;
651  
652 }
653
654 //=======================================================================
655 //function : Need2DegRepara
656 //purpose  : in the case of wire closed G1 it says if you will to use a 
657 //           two degree reparametrisation to close it C1
658 //=======================================================================
659
660 static Standard_Boolean Need2DegRepara(const TColGeom_Array1OfBSplineCurve& tab)
661
662 {Standard_Integer        i;
663  gp_Vec                  Vec1,Vec2;
664  gp_Pnt                  Pint;
665  Standard_Real           Rapport=1.0e0;
666
667  for (i=0;i<=tab.Length()-2;i++){
668    tab(i+1)->D1(tab(i+1)->FirstParameter(),Pint,Vec1);
669    tab(i)->D1(tab(i)->LastParameter(),Pint,Vec2);
670    Rapport=Rapport*Vec2.Magnitude()/Vec1.Magnitude();
671  }
672  if ((Rapport<=(1.0e0+Precision::Confusion()))&&(Rapport>=(1.0e0-Precision::Confusion())))
673    return Standard_False;
674  else
675    return Standard_True;
676 }
677
678 //=======================================================================
679 //function : Indexmin
680 //purpose  : Give the index of the curve which has the lowest degree
681 //=======================================================================
682
683 static Standard_Integer Indexmin(const TColGeom_Array1OfBSplineCurve& tab)
684 {
685   Standard_Integer i = 0, index = 0, degree = 0;
686   
687   degree=tab(0)->Degree();
688   for (i=0;i<=tab.Length()-1;i++)
689     if (tab(i)->Degree()<=degree){
690       degree=tab(i)->Degree();
691       index=i;
692     }
693   return index;
694 }
695
696 //=======================================================================
697 //function : NewTabClosedG1
698 //purpose  : Sort the array of BSplines to start at the nb_vertex_group0 index
699 //=======================================================================
700
701 static void ReorderArrayOfG1Curves(TColGeom_Array1OfBSplineCurve&    ArrayOfCurves, 
702                            TColStd_Array1OfReal&             ArrayOfToler,
703                            TColStd_Array1OfBoolean&          tabG1,
704                            const Standard_Integer            StartIndex,
705                            const Standard_Real               ClosedTolerance)
706
707 {Standard_Integer i;
708  TColGeom_Array1OfBSplineCurve  ArraybisOfCurves(0,ArrayOfCurves.Length()-1);  //temporary
709  TColStd_Array1OfReal           ArraybisOfToler(0,ArrayOfToler.Length()-1);    //arrays
710  TColStd_Array1OfBoolean        tabbisG1(0,tabG1.Length()-1);
711
712  for (i=0;i<=ArrayOfCurves.Length()-1;i++){
713    if (i!=ArrayOfCurves.Length()-1){
714      ArraybisOfCurves(i)=ArrayOfCurves(i);
715      ArraybisOfToler(i)=ArrayOfToler(i);
716      tabbisG1(i)=tabG1(i);
717    }
718    else
719      ArraybisOfCurves(i)=ArrayOfCurves(i);
720  }
721
722  for (i=0;i<=(ArrayOfCurves.Length()-(StartIndex+2));i++){
723    ArrayOfCurves(i)=ArraybisOfCurves(i+StartIndex+1);
724    if (i!=(ArrayOfCurves.Length()-(StartIndex+2))){
725      ArrayOfToler(i)=ArraybisOfToler(i+StartIndex+1);
726      tabG1(i)=tabbisG1(i+StartIndex+1);
727    }
728  }
729
730  ArrayOfToler(ArrayOfCurves.Length()-(StartIndex+2))=ClosedTolerance;
731  tabG1(ArrayOfCurves.Length()-(StartIndex+2))=Standard_True;
732
733  for (i=(ArrayOfCurves.Length()-(StartIndex+1));i<=(ArrayOfCurves.Length()-1);i++){
734    if (i!=ArrayOfCurves.Length()-1){
735      ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
736      ArrayOfToler(i)=ArraybisOfToler(i-(ArrayOfCurves.Length()-(StartIndex+1)));
737      tabG1(i)=tabbisG1(i-(ArrayOfCurves.Length()-(StartIndex+1)));
738    }
739    else
740      ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
741  }
742 }
743
744 //=======================================================================
745 //class   : reparameterise_evaluator
746 //purpose :
747 //=======================================================================
748
749 class GeomConvert_reparameterise_evaluator : public BSplCLib_EvaluatorFunction
750 {
751
752 public:
753
754   GeomConvert_reparameterise_evaluator (const Standard_Real thePolynomialCoefficient[3])
755   {
756     memcpy (myPolynomialCoefficient, thePolynomialCoefficient, sizeof(myPolynomialCoefficient));
757   }
758
759   virtual void Evaluate (const Standard_Integer theDerivativeRequest,
760                          const Standard_Real*   /*theStartEnd*/,
761                          const Standard_Real    theParameter,
762                          Standard_Real&         theResult,
763                          Standard_Integer&      theErrorCode) const
764   {
765     theErrorCode = 0;
766     PLib::EvalPolynomial (theParameter,
767                           theDerivativeRequest,
768                           2,
769                           1,
770                           *((Standard_Real* )myPolynomialCoefficient), // function really only read values from this array
771                           theResult);
772   }
773
774 private:
775
776   Standard_Real myPolynomialCoefficient[3];
777
778 };
779
780 //=======================================================================
781 //function : ConcatG1
782 //purpose  : 
783 //=======================================================================
784
785  void  GeomConvert::ConcatG1(TColGeom_Array1OfBSplineCurve&           ArrayOfCurves, 
786                              const TColStd_Array1OfReal&              ArrayOfToler,
787                              Handle(TColGeom_HArray1OfBSplineCurve) & ArrayOfConcatenated,
788                              const Standard_Boolean                   ClosedG1Flag,
789                              const Standard_Real                      ClosedTolerance) 
790
791 {Standard_Integer             nb_curve=ArrayOfCurves.Length(),
792                               nb_vertexG1=0,
793                               nb_group=0,
794                               index=0,i,ii,j,jj,
795                               indexmin,
796                               nb_vertex_group0=0;
797  Standard_Real                lambda,                      //G1 coefficient
798                               First;
799  Standard_Real PreLast = 0.;
800  GeomAbs_Shape                Cont;
801  gp_Vec                       Vec1,Vec2;                   //concecutive tangential vectors 
802  gp_Pnt                       Pint;
803  Handle(Geom_BSplineCurve)    Curve1,Curve2;                       
804  TColStd_Array1OfBoolean      tabG1(0,nb_curve-2);         //array of the G1 continuity at the intersections
805  TColStd_Array1OfReal         local_tolerance(0,
806                                               ArrayOfToler.Length()-1) ;
807  
808  for (i=0 ; i < ArrayOfToler.Length() ; i++) {
809    local_tolerance(i) = ArrayOfToler(i) ;
810  }
811  for (i=0 ;i<nb_curve; i++){
812    if (i >= 1){
813      First=ArrayOfCurves(i)->FirstParameter();
814      Cont = GeomLProp::Continuity(ArrayOfCurves(i-1),
815                                   ArrayOfCurves(i),
816                                   PreLast,First,
817                                   Standard_True,Standard_True);
818      if (Cont<GeomAbs_C0)
819        Standard_ConstructionError::Raise("GeomConvert curves not C0") ;                
820      else{
821        if (Cont>=GeomAbs_G1)
822          tabG1(i-1)=Standard_True;                   //True=G1 continuity
823        else 
824          tabG1(i-1)=Standard_False;
825      }
826    }
827    PreLast=ArrayOfCurves(i)->LastParameter();     
828  }
829  
830
831  while (index<=nb_curve-1){ //determination of the Wire features
832    nb_vertexG1=0;
833    while(((index+nb_vertexG1)<=nb_curve-2)&&
834          (tabG1(index+nb_vertexG1)==Standard_True))
835      nb_vertexG1++;
836    nb_group++;
837    if (index==0)
838      nb_vertex_group0=nb_vertexG1;
839    index=index+1+nb_vertexG1;
840  }
841
842  if ((ClosedG1Flag)&&(nb_group!=1)){                            //sort of the array
843    nb_group--;
844    ReorderArrayOfG1Curves(ArrayOfCurves,
845                   local_tolerance,
846                   tabG1,
847                   nb_vertex_group0,
848                   ClosedTolerance);
849  }
850
851  ArrayOfConcatenated = new TColGeom_HArray1OfBSplineCurve(0,nb_group-1);
852  Standard_Boolean       fusion;
853
854  index=0;
855  Pretreatment(ArrayOfCurves);
856  Standard_Real aPolynomialCoefficient[3];
857
858  if ((nb_group==1) && (ClosedG1Flag)){ //treatment of a particular case
859    indexmin=Indexmin(ArrayOfCurves);
860    if (indexmin!=(ArrayOfCurves.Length()-1))
861      ReorderArrayOfG1Curves(ArrayOfCurves,
862                     local_tolerance,
863                     tabG1,
864                     indexmin,
865                     ClosedTolerance);
866    Curve2=ArrayOfCurves(0);
867    for (j=1;j<=nb_curve-1;j++){                          //secondary loop inside each group
868      Curve1=ArrayOfCurves(j);
869      if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){ 
870        Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
871        Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
872        lambda=Vec2.Magnitude()/Vec1.Magnitude();
873        TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
874        Curve1->Knots(KnotC1);
875        Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
876        ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
877        Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
878        Standard_Real tmax,a,b,c,
879        umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
880        tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
881        a=(lambda*lambda2-1)/(2*lambda*tmax);
882        aPolynomialCoefficient[2] = a;
883        b=(1/lambda); 
884        aPolynomialCoefficient[1] = b;
885        c=umin;
886        aPolynomialCoefficient[0] = c;
887        TColStd_Array1OfReal  Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
888        TColStd_Array1OfInteger  KnotC1Mults(1,Curve1->NbKnots());
889        Curve1->Multiplicities(KnotC1Mults);
890        BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
891        KnotC1(1)=0.0;
892        for (ii=2;ii<=KnotC1.Length();ii++) {
893 //       KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
894          KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); // ifv 17.05.00 buc60667
895        }
896        TColgp_Array1OfPnt  Curve1Poles(1,Curve1->NbPoles());
897        Curve1->Poles(Curve1Poles);
898        
899        for (ii=1;ii<=Curve1->NbKnots();ii++)
900          KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
901        
902        TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
903        
904        BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
905        TColgp_Array1OfPnt  NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
906        Standard_Integer      Status;
907        TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
908        Curve1->Weights(Curve1Weights);
909        for (ii=1;ii<=Curve1->NbPoles();ii++)
910          for (jj=1;jj<=3;jj++)
911            Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
912 //POP pour WNT
913        GeomConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
914 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
915        BSplCLib::FunctionReparameterise(ev,
916                                         Curve1->Degree(),
917                                         Curve1FlatKnots,
918                                         Curve1Poles,
919                                         FlatKnots,
920                                         2*Curve1->Degree(),
921                                         NewPoles,
922                                         Status
923                                         );
924        TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
925 //       BSplCLib::FunctionReparameterise(reparameterise_evaluator,
926        BSplCLib::FunctionReparameterise(ev,
927                                         Curve1->Degree(),
928                                         Curve1FlatKnots,
929                                         Curve1Weights,
930                                         FlatKnots,
931                                         2*Curve1->Degree(),
932                                         NewWeights,
933                                         Status
934                                         );
935        for (ii=1;ii<=NewPoles.Length();ii++)
936          for (jj=1;jj<=3;jj++)
937            NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
938        Curve1= new Geom_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
939      }
940      GeomConvert_CompCurveToBSplineCurve C (Curve2);
941      fusion=C.Add(Curve1,
942                   local_tolerance(j-1));                //merge of two consecutive curves               
943      if (fusion==Standard_False)
944        Standard_ConstructionError::Raise("GeomConvert Concatenation Error") ;
945      Curve2=C.BSplineCurve();
946    }
947    Curve2->SetPeriodic();      
948    Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
949                          Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
950                          Precision::Confusion());
951    ArrayOfConcatenated->SetValue(0,Curve2);
952  }
953  
954  else
955    for (i=0;i<=nb_group-1;i++){                             //principal loop on each G1 continuity 
956      nb_vertexG1=0;                                         //group
957      
958      while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
959        nb_vertexG1++;
960       
961      for (j=index;j<=index+nb_vertexG1;j++){                //secondary loop inside each group
962        Curve1=ArrayOfCurves(j);
963        
964        if (index==j)                                        //initialisation at the begining of the loop
965          ArrayOfConcatenated->SetValue(i,Curve1);
966        else{
967          GeomConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(i));
968          fusion=C.Add(Curve1,ArrayOfToler(j-1));            //merge of two consecutive curves               
969          if (fusion==Standard_False)
970            Standard_ConstructionError::Raise("GeomConvert Concatenation Error") ;
971          ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
972        }
973      }
974      index=index+1+nb_vertexG1;
975    }
976 }  
977 //=======================================================================
978 //function : ConcatC1
979 //purpose  : 
980 //=======================================================================
981
982 void  GeomConvert::ConcatC1(TColGeom_Array1OfBSplineCurve&           ArrayOfCurves, 
983                             const TColStd_Array1OfReal&              ArrayOfToler,
984                             Handle(TColStd_HArray1OfInteger)&        ArrayOfIndices,
985                             Handle(TColGeom_HArray1OfBSplineCurve)&  ArrayOfConcatenated,
986                             const Standard_Boolean                   ClosedG1Flag,
987                             const Standard_Real                      ClosedTolerance) 
988 {
989   ConcatC1(ArrayOfCurves,
990            ArrayOfToler,
991            ArrayOfIndices,
992            ArrayOfConcatenated,
993            ClosedG1Flag,
994            ClosedTolerance,
995            Precision::Angular()) ;
996 }
997 //=======================================================================
998 //function : ConcatC1
999 //purpose  : 
1000 //=======================================================================
1001
1002 void  GeomConvert::ConcatC1(TColGeom_Array1OfBSplineCurve&           ArrayOfCurves, 
1003                             const TColStd_Array1OfReal&              ArrayOfToler,
1004                             Handle(TColStd_HArray1OfInteger)&        ArrayOfIndices,
1005                             Handle(TColGeom_HArray1OfBSplineCurve)&  ArrayOfConcatenated,
1006                             const Standard_Boolean                   ClosedG1Flag,
1007                             const Standard_Real                      ClosedTolerance,
1008                             const Standard_Real                      AngularTolerance)
1009
1010 {Standard_Integer             nb_curve=ArrayOfCurves.Length(),
1011                               nb_vertexG1,
1012                               nb_group=0,
1013                               index=0,i,ii,j,jj,
1014                               indexmin,
1015                               nb_vertex_group0=0;
1016  Standard_Real                lambda,                      //G1 coefficient
1017                               First;
1018  Standard_Real PreLast = 0.;
1019
1020  GeomAbs_Shape                Cont;
1021  gp_Vec                       Vec1,Vec2;                   //concecutive tangential vectors
1022  gp_Pnt                       Pint;
1023  Handle(Geom_BSplineCurve)    Curve1,Curve2;                       
1024  TColStd_Array1OfBoolean      tabG1(0,nb_curve-2);         //array of the G1 continuity at the intersections
1025  TColStd_Array1OfReal         local_tolerance(0,
1026                                               ArrayOfToler.Length()-1) ;
1027  
1028  for (i=0 ; i < ArrayOfToler.Length() ; i++) {
1029    local_tolerance(i) = ArrayOfToler(i) ;
1030  }
1031  for (i=0 ;i<nb_curve; i++){
1032    if (i >= 1){
1033      First=ArrayOfCurves(i)->FirstParameter();
1034      Cont = GeomLProp::Continuity(ArrayOfCurves(i-1),
1035                                ArrayOfCurves(i),
1036                                PreLast,
1037                                First,
1038                                Standard_True,
1039                                Standard_True,
1040                                local_tolerance(i-1),
1041                                AngularTolerance);
1042      if (Cont<GeomAbs_C0)
1043        Standard_ConstructionError::Raise("GeomConvert curves not C0");
1044      else{
1045        if (Cont>=GeomAbs_G1)
1046          tabG1(i-1)=Standard_True;                   //True=G1 continuity
1047        else 
1048          tabG1(i-1)=Standard_False;
1049      }
1050    }
1051    PreLast=ArrayOfCurves(i)->LastParameter();     
1052  }
1053  
1054
1055  while (index<=nb_curve-1){                                 //determination of the Wire features
1056    nb_vertexG1=0;
1057    while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1058      nb_vertexG1++;
1059    nb_group++;
1060    if (index==0)
1061      nb_vertex_group0=nb_vertexG1;
1062    index=index+1+nb_vertexG1;
1063  }
1064
1065  if ((ClosedG1Flag)&&(nb_group!=1)){                            //sort of the array
1066    nb_group--;
1067    ReorderArrayOfG1Curves(ArrayOfCurves,
1068                           local_tolerance,
1069                           tabG1,
1070                           nb_vertex_group0,
1071                           ClosedTolerance);
1072  }
1073
1074  ArrayOfIndices = 
1075    new TColStd_HArray1OfInteger(0,nb_group);
1076  ArrayOfConcatenated = 
1077    new TColGeom_HArray1OfBSplineCurve(0,nb_group-1);
1078
1079  Standard_Boolean       fusion;
1080  Standard_Integer       k=0;
1081  index=0;
1082  Pretreatment(ArrayOfCurves);
1083  Standard_Real aPolynomialCoefficient[3];
1084
1085  if ((nb_group==1) && (ClosedG1Flag)){                       //treatment of a particular case
1086    ArrayOfIndices->SetValue(0,0);
1087    ArrayOfIndices->SetValue(1,0);
1088    indexmin=Indexmin(ArrayOfCurves);
1089    if (indexmin!=(ArrayOfCurves.Length()-1))
1090      ReorderArrayOfG1Curves(ArrayOfCurves,
1091                             local_tolerance,
1092                             tabG1,
1093                             indexmin,
1094                             ClosedTolerance);
1095    for (j=0;j<=nb_curve-1;j++){                          //secondary loop inside each group
1096      if (NeedToBeTreated(ArrayOfCurves(j)))
1097        Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1098      else
1099        Curve1=ArrayOfCurves(j);
1100      
1101      if (j==0)                                           //initialisation at the begining of the loop
1102        Curve2=Curve1;
1103      else{
1104        if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){ 
1105          Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1106          Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1107          lambda=Vec2.Magnitude()/Vec1.Magnitude();
1108          TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1109          Curve1->Knots(KnotC1);
1110          Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1111          ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1112          Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1113          Standard_Real tmax,a,b,c,
1114          umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1115          tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1116          a=(lambda*lambda2-1)/(2*lambda*tmax);
1117          aPolynomialCoefficient[2] = a;
1118          b=(1/lambda); 
1119          aPolynomialCoefficient[1] = b;
1120          c=umin;
1121          aPolynomialCoefficient[0] = c;
1122          TColStd_Array1OfReal  Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1123          TColStd_Array1OfInteger  KnotC1Mults(1,Curve1->NbKnots());
1124          Curve1->Multiplicities(KnotC1Mults);
1125          BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1126          KnotC1(1)=0.0;
1127          for (ii=2;ii<=KnotC1.Length();ii++) {
1128 //         KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1129            KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); // ifv 17.05.00 buc60667
1130          }
1131          TColgp_Array1OfPnt  Curve1Poles(1,Curve1->NbPoles());
1132          Curve1->Poles(Curve1Poles);
1133          
1134          for (ii=1;ii<=Curve1->NbKnots();ii++)
1135            KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1136          
1137          TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1138          
1139          BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1140          TColgp_Array1OfPnt  NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1141          Standard_Integer      Status;
1142          TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1143          Curve1->Weights(Curve1Weights);
1144          for (ii=1;ii<=Curve1->NbPoles();ii++)
1145            for (jj=1;jj<=3;jj++)
1146              Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1147 //POP pour WNT
1148          GeomConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1149
1150          BSplCLib::FunctionReparameterise(ev,
1151                                           Curve1->Degree(),
1152                                           Curve1FlatKnots,
1153                                           Curve1Poles,
1154                                           FlatKnots,
1155                                           2*Curve1->Degree(),
1156                                           NewPoles,
1157                                           Status
1158                                           );
1159          TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1160
1161          BSplCLib::FunctionReparameterise(ev,
1162                                           Curve1->Degree(),
1163                                           Curve1FlatKnots,
1164                                           Curve1Weights,
1165                                           FlatKnots,
1166                                           2*Curve1->Degree(),
1167                                           NewWeights,
1168                                           Status
1169                                           );
1170          for (ii=1;ii<=NewPoles.Length();ii++)
1171            for (jj=1;jj<=3;jj++)
1172              NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1173          Curve1= new Geom_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
1174        }
1175        GeomConvert_CompCurveToBSplineCurve C (Curve2);
1176        fusion=C.Add(Curve1,
1177                     local_tolerance(j-1));          //merge of two consecutive curves               
1178        if (fusion==Standard_False)
1179          Standard_ConstructionError::Raise("GeomConvert Concatenation Error") ;
1180        Curve2=C.BSplineCurve();
1181      }
1182    }
1183    Curve2->SetPeriodic();                               //only one C1 curve
1184    Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
1185                          Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1186                          Precision::Confusion());
1187    ArrayOfConcatenated->SetValue(0,Curve2);
1188  }
1189  
1190  else
1191    for (i=0;i<=nb_group-1;i++){                             //principal loop on each G1 continuity 
1192      nb_vertexG1=0;                                         //group
1193       
1194      while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1195        nb_vertexG1++;
1196       
1197      if ((!ClosedG1Flag)||(nb_group==1)){                        //filling of the array of index which are kept
1198        k++;
1199        ArrayOfIndices->SetValue(k-1,index);
1200        if (k==nb_group)
1201          ArrayOfIndices->SetValue(k,0);
1202      }
1203      else{
1204        k++;
1205        ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1);
1206        if (k==nb_group)
1207          ArrayOfIndices->SetValue(k,nb_vertex_group0+1);
1208      }
1209       
1210      for (j=index;j<=index+nb_vertexG1;j++){                //secondary loop inside each group
1211        if (NeedToBeTreated(ArrayOfCurves(j)))
1212          Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1213        else
1214          Curve1=ArrayOfCurves(j);
1215        
1216        if (index==j)                                      //initialisation at the begining of the loop
1217          ArrayOfConcatenated->SetValue(i,Curve1);
1218        else
1219        {
1220          // Merge of two consecutive curves.
1221          GeomConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(i));
1222          fusion=C.Add(Curve1, local_tolerance(j-1), Standard_True);
1223          if (fusion==Standard_False)
1224            Standard_ConstructionError::Raise("GeomConvert Concatenation Error");
1225          ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1226        }
1227      }
1228      index=index+1+nb_vertexG1;
1229    }
1230 }
1231            
1232 //=======================================================================
1233 //function : C0BSplineToC1BSplineCurve
1234 //purpose  : 
1235 //=======================================================================
1236
1237 void GeomConvert::C0BSplineToC1BSplineCurve(Handle(Geom_BSplineCurve)& BS,
1238                                             const Standard_Real tolerance, 
1239                                             const Standard_Real AngularTol)
1240
1241 {
1242   Standard_Boolean fusion;
1243   Handle(TColGeom_HArray1OfBSplineCurve) ArrayOfConcatenated; 
1244   //the array with the resulting curves
1245     
1246   GeomConvert::C0BSplineToArrayOfC1BSplineCurve(BS, ArrayOfConcatenated, 
1247                                                 AngularTol, tolerance);
1248     
1249   GeomConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(0));
1250   if (ArrayOfConcatenated->Length()>=2){
1251     Standard_Integer i;
1252     for (i=1;i<ArrayOfConcatenated->Length();i++){
1253       fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance);
1254       if (fusion==Standard_False)
1255         Standard_ConstructionError::Raise("GeomConvert Concatenation Error") ;
1256     }
1257   }
1258   BS=C.BSplineCurve();
1259 }
1260
1261 //=======================================================================
1262 //function : C0BSplineToArrayOfC1BSplineCurve
1263 //purpose  : 
1264 //=======================================================================
1265
1266 void GeomConvert::C0BSplineToArrayOfC1BSplineCurve(
1267                                 const Handle(Geom_BSplineCurve) &        BS,
1268                                 Handle(TColGeom_HArray1OfBSplineCurve) & tabBS,
1269                                 const Standard_Real                      tolerance)
1270 {
1271    C0BSplineToArrayOfC1BSplineCurve(BS,
1272                                     tabBS,
1273                                     Precision::Angular(),
1274                                     tolerance) ;
1275 }
1276
1277 //=======================================================================
1278 //function : C0BSplineToArrayOfC1BSplineCurve
1279 //purpose  : 
1280 //=======================================================================
1281
1282 void GeomConvert::C0BSplineToArrayOfC1BSplineCurve(
1283                                 const Handle(Geom_BSplineCurve) &        BS,
1284                                 Handle(TColGeom_HArray1OfBSplineCurve) & tabBS,
1285                                 const Standard_Real                      AngularTolerance,
1286                                 const Standard_Real                      tolerance)
1287
1288 {TColStd_Array1OfInteger          BSMults(1,BS->NbKnots());
1289  TColStd_Array1OfReal             BSKnots(1,BS->NbKnots());
1290  Standard_Integer                 i,j,nbcurveC1=1;
1291  Standard_Real                    U1,U2;
1292  Standard_Boolean                 closed_flag= Standard_False ;
1293  gp_Pnt                           point;
1294  gp_Vec                           V1,V2;
1295 // Standard_Boolean                 fusion;
1296
1297  BS->Knots(BSKnots);
1298  BS->Multiplicities(BSMults);
1299  for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){                                 //give the number of C1 curves
1300    if (BSMults(i)==BS->Degree())
1301      nbcurveC1++;   
1302  }
1303
1304  if (nbcurveC1>1){
1305    TColGeom_Array1OfBSplineCurve    ArrayOfCurves(0,nbcurveC1-1);
1306    TColStd_Array1OfReal             ArrayOfToler(0,nbcurveC1-2);
1307    
1308    for (i=0;i<=nbcurveC1-2;i++)                                      
1309      //filling of the array of tolerances  
1310      ArrayOfToler(i)=tolerance;                                      
1311    //with the variable tolerance
1312    U2=BS->FirstParameter() ;
1313    j=BS->FirstUKnotIndex() + 1;
1314    for (i=0;i<nbcurveC1;i++){                                        
1315      //filling of the array of curves
1316      U1=U2;                                                          
1317      //with the curves C1 segmented
1318      while (BSMults(j)<BS->Degree() && j < BS->LastUKnotIndex())
1319        j++;
1320      U2=BSKnots(j);
1321      j++;
1322      Handle(Geom_BSplineCurve) 
1323        BSbis=Handle(Geom_BSplineCurve)::DownCast(BS->Copy());
1324      BSbis->Segment(U1,U2);
1325      ArrayOfCurves(i)=BSbis;
1326    }
1327     
1328    Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1329      
1330    BS->D1(BS->FirstParameter(),point,V1);  
1331    BS->D1(BS->LastParameter(),point,V2);
1332     
1333    if ((BS->IsClosed())&&(V1.IsParallel(V2,AngularTolerance))){
1334      //check if the BSpline is closed G1
1335      closed_flag = Standard_True ;
1336    }
1337     
1338    GeomConvert::ConcatC1(ArrayOfCurves,
1339                          ArrayOfToler,
1340                          ArrayOfIndices,
1341                          tabBS,
1342                          closed_flag,
1343                          tolerance,
1344                          AngularTolerance);
1345  }
1346  else{
1347    tabBS = new TColGeom_HArray1OfBSplineCurve(0,0);
1348    tabBS->SetValue(0,BS);
1349  }
1350 }  
1351
1352
1353
1354
1355