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