1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
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
19 #include <GeomConvert.ixx>
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>
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>
38 #include <gp_Trsf.hxx>
42 #include <Geom2d_BSplineCurve.hxx>
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>
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>
71 #include <Precision.hxx>
73 #include <Standard_DomainError.hxx>
74 #include <Standard_ConstructionError.hxx>
75 #include <Geom_OffsetCurve.hxx>
76 #include <GeomConvert_ApproxCurve.hxx>
80 //=======================================================================
81 //function : BSplineCurveBuilder
83 //=======================================================================
85 static Handle(Geom_BSplineCurve) BSplineCurveBuilder
86 (const Handle(Geom_Conic)& TheConic,
87 const Convert_ConicToBSplineCurve& Convert)
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);
100 for (i = 1; i <= NbPoles; i++) {
101 P2d = Convert.Pole (i);
102 P3d.SetCoord (P2d.X(), P2d.Y(), 0.0);
104 Weights (i) = Convert.Weight (i);
106 for (i = 1; i <= NbKnots; i++) {
107 Knots (i) = Convert.Knot (i);
108 Mults (i) = Convert.Multiplicity (i);
111 new Geom_BSplineCurve (Poles, Weights, Knots, Mults,
112 Convert.Degree(), Convert.IsPeriodic());
114 T.SetTransformation (TheConic->Position(), gp::XOY());
115 Handle(Geom_BSplineCurve) Cres;
116 Cres = Handle(Geom_BSplineCurve)::DownCast(TheCurve->Transformed (T));
122 //=======================================================================
123 //function : SplitBSplineCurve
125 //=======================================================================
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)
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();
140 Handle(Geom_BSplineCurve) C1
141 = Handle(Geom_BSplineCurve)::DownCast(C->Copy ());
143 C1->Segment( C->Knot(FirstK),C->Knot(LastK));
145 if (C->IsPeriodic()) {
146 if (!SameOrientation) C1->Reverse();
149 if (FromK1 > ToK2) C1->Reverse();
155 //=======================================================================
156 //function : SplitBSplineCurve
158 //=======================================================================
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 )
167 Standard_Real FirstU = Min( FromU1, ToU2);
168 Standard_Real LastU = Max( FromU1, ToU2);
170 Handle (Geom_BSplineCurve) C1
171 = Handle(Geom_BSplineCurve)::DownCast(C->Copy());
173 C1->Segment(FirstU, LastU);
175 if (C->IsPeriodic()) {
176 if (!SameOrientation) C1->Reverse();
179 if (FromU1 > ToU2) C1->Reverse();
188 //=======================================================================
189 //function : CurveToBSplineCurve
191 //=======================================================================
193 Handle(Geom_BSplineCurve) GeomConvert::CurveToBSplineCurve
194 (const Handle(Geom_Curve)& C,
195 const Convert_ParameterisationType Parameterisation)
197 Handle (Geom_BSplineCurve) TheCurve;
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();
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();
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);
221 TColStd_Array1OfReal Knots (1, 2);
222 Knots (1) = Ctrim->FirstParameter ();
223 Knots (2) = Ctrim->LastParameter ();
224 TColStd_Array1OfInteger Mults (1, 2);
227 Standard_Integer Degree = 1;
228 TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
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,
239 TheCurve = BSplineCurveBuilder (TheConic, Convert);
243 Convert_CircleToBSplineCurve Convert (C2d,
247 TheCurve = BSplineCurveBuilder (TheConic, Convert);
249 else { // split circle to avoide numerical
250 // overflow when U2 - U1 =~ 2*PI
252 Standard_Real Umed = (U1 + U2) * .5;
253 Convert_CircleToBSplineCurve Convert1 (C2d,
258 Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
260 Convert_CircleToBSplineCurve Convert2 (C2d,
265 Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
267 GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
270 CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
273 TheCurve = CCTBSpl.BSplineCurve();
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,
289 TheCurve = BSplineCurveBuilder (TheConic, Convert);
293 Convert_EllipseToBSplineCurve Convert (E2d,
297 TheCurve = BSplineCurveBuilder (TheConic, Convert);
299 else { // split ellipse to avoide numerical
300 // overflow when U2 - U1 =~ 2*PI
302 Standard_Real Umed = (U1 + U2) * .5;
303 Convert_EllipseToBSplineCurve Convert1 (E2d,
308 Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
310 Convert_EllipseToBSplineCurve Convert2 (E2d,
315 Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
317 GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
320 CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
323 TheCurve = CCTBSpl.BSplineCurve();
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);
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);
343 else if (Curv->IsKind (STANDARD_TYPE(Geom_BezierCurve))) {
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);
355 Mults (1) = Degree + 1;
356 Mults (2) = Degree + 1;
358 if (CBez->IsRational()) {
359 TColStd_Array1OfReal Weights (1, NbPoles);
360 CBez->Weights (Weights);
362 new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree);
366 new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
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())
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();
381 ///////////////////////////////////////////////
382 TheCurve->Segment(U1,U2);
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();
394 else { Standard_DomainError::Raise("No such curve"); }
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(); }
406 else if ( Parameterisation == Convert_QuasiAngular) {
407 Convert_EllipseToBSplineCurve Convert (E2d,
412 TheCurve = BSplineCurveBuilder (TheConic, Convert);
413 TheCurve->SetPeriodic();
416 Convert_EllipseToBSplineCurve Convert (E2d,
418 TheCurve = BSplineCurveBuilder (TheConic, Convert);
419 TheCurve->SetPeriodic(); // pour polynomial et quasi angular
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(); }
430 else if ( Parameterisation == Convert_QuasiAngular) {
431 Convert_CircleToBSplineCurve Convert (C2d,
436 TheCurve = BSplineCurveBuilder (TheConic, Convert);
439 Convert_CircleToBSplineCurve Convert (C2d,
441 TheCurve = BSplineCurveBuilder (TheConic, Convert);
442 TheCurve->SetPeriodic();
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);
455 Mults (1) = Degree + 1;
456 Mults (2) = Degree + 1;
458 if (CBez->IsRational()) {
459 TColStd_Array1OfReal Weights (1, NbPoles);
460 CBez->Weights (Weights);
462 new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree);
465 TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
469 else if (C->IsKind (STANDARD_TYPE(Geom_BSplineCurve))) {
470 TheCurve = Handle(Geom_BSplineCurve)::DownCast(C->Copy());
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();
483 else { Standard_DomainError::Raise("No such curve"); }
490 //=======================================================================
491 //class : law_evaluator
492 //purpose : usefull to estimate the value of a function
493 //=======================================================================
495 class GeomConvert_law_evaluator : public BSplCLib_EvaluatorFunction
500 GeomConvert_law_evaluator (const Handle(Geom2d_BSplineCurve)& theAncore)
501 : myAncore (theAncore) {}
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
510 if (!myAncore.IsNull() &&
511 theParameter >= theStartEnd[0] &&
512 theParameter <= theStartEnd[1] &&
513 theDerivativeRequest == 0)
516 myAncore->D0 (theParameter, aPoint);
517 theResult = aPoint.Coord(2);
525 Handle(Geom2d_BSplineCurve) myAncore;
529 //=======================================================================
530 //function : MultNumandDenom
531 //purpose : Multiply two BSpline curves to make one
532 //=======================================================================
535 static Handle(Geom_BSplineCurve) MultNumandDenom(const Handle(Geom2d_BSplineCurve)& a ,
536 const Handle(Geom_BSplineCurve)& BS )
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,
555 BS->Knots(BSKnots); //storage of the two BSpline
556 BS->Multiplicities(BSMults); //features
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;
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());
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));
585 GeomConvert_law_evaluator ev (anAncore);
587 BSplCLib::FunctionMultiply(ev,
596 BSplCLib::FunctionMultiply(ev,
604 for (ii=1;ii<=resNbPoles;ii++)
606 resPoles(ii).SetCoord(jj,resNumPoles(ii).Coord(jj)/resDenPoles(ii));
607 res = new Geom_BSplineCurve(resPoles,resDenPoles,resKnots->Array1(),resMults->Array1(),degree);
611 //=======================================================================
612 //function : Pretreatment
613 //purpose : Put the two first and two last weigths at one if they are
615 //=======================================================================
617 static void Pretreatment(TColGeom_Array1OfBSplineCurve& tab)
619 {Standard_Integer i,j;
622 for (i=0;i<=(tab.Length()-1);i++){
623 if (tab(i)->IsRational()) {
625 if ((tab(i)->Weight(2)==a)&&
626 (tab(i)->Weight(tab(i)->NbPoles()-1)==a)&&
627 (tab(i)->Weight(tab(i)->NbPoles())==a))
629 for (j=1;j<=tab(i)->NbPoles();j++)
630 tab(i)->SetWeight(j,tab(i)->Weight(j)/a);
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 //=======================================================================
641 static Standard_Boolean NeedToBeTreated(const Handle(Geom_BSplineCurve)& BS)
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;
658 return Standard_False;
661 return Standard_False ;
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 //=======================================================================
671 static Standard_Boolean Need2DegRepara(const TColGeom_Array1OfBSplineCurve& tab)
676 Standard_Real Rapport=1.0e0;
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();
683 if ((Rapport<=(1.0e0+Precision::Confusion()))&&(Rapport>=(1.0e0-Precision::Confusion())))
684 return Standard_False;
686 return Standard_True;
689 //=======================================================================
690 //function : Indexmin
691 //purpose : Give the index of the curve which has the lowest degree
692 //=======================================================================
694 static Standard_Integer Indexmin(const TColGeom_Array1OfBSplineCurve& tab)
696 Standard_Integer i = 0, index = 0, degree = 0;
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();
707 //=======================================================================
708 //function : NewTabClosedG1
709 //purpose : Sort the array of BSplines to start at the nb_vertex_group0 index
710 //=======================================================================
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)
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);
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);
730 ArraybisOfCurves(i)=ArrayOfCurves(i);
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);
741 ArrayOfToler(ArrayOfCurves.Length()-(StartIndex+2))=ClosedTolerance;
742 tabG1(ArrayOfCurves.Length()-(StartIndex+2))=Standard_True;
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)));
751 ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
755 //=======================================================================
756 //class : reparameterise_evaluator
758 //=======================================================================
760 class GeomConvert_reparameterise_evaluator : public BSplCLib_EvaluatorFunction
765 GeomConvert_reparameterise_evaluator (const Standard_Real thePolynomialCoefficient[3])
767 memcpy (myPolynomialCoefficient, thePolynomialCoefficient, sizeof(myPolynomialCoefficient));
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
777 PLib::EvalPolynomial (theParameter,
778 theDerivativeRequest,
781 *((Standard_Real* )myPolynomialCoefficient), // function really only read values from this array
787 Standard_Real myPolynomialCoefficient[3];
791 //=======================================================================
792 //function : ConcatG1
794 //=======================================================================
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)
802 {Standard_Integer nb_curve=ArrayOfCurves.Length(),
808 Standard_Real lambda, //G1 coefficient
810 Standard_Real PreLast = 0.;
812 gp_Vec Vec1,Vec2; //concecutive tangential vectors
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) ;
819 for (i=0 ; i < ArrayOfToler.Length() ; i++) {
820 local_tolerance(i) = ArrayOfToler(i) ;
822 for (i=0 ;i<nb_curve; i++){
824 First=ArrayOfCurves(i)->FirstParameter();
825 Cont = GeomLProp::Continuity(ArrayOfCurves(i-1),
828 Standard_True,Standard_True);
830 Standard_ConstructionError::Raise("GeomConvert curves not C0") ;
832 if (Cont>=GeomAbs_G1)
833 tabG1(i-1)=Standard_True; //True=G1 continuity
835 tabG1(i-1)=Standard_False;
838 PreLast=ArrayOfCurves(i)->LastParameter();
842 while (index<=nb_curve-1){ //determination of the Wire features
844 while(((index+nb_vertexG1)<=nb_curve-2)&&
845 (tabG1(index+nb_vertexG1)==Standard_True))
849 nb_vertex_group0=nb_vertexG1;
850 index=index+1+nb_vertexG1;
853 if ((ClosedG1Flag)&&(nb_group!=1)){ //sort of the array
855 ReorderArrayOfG1Curves(ArrayOfCurves,
862 ArrayOfConcatenated = new TColGeom_HArray1OfBSplineCurve(0,nb_group-1);
863 Standard_Boolean fusion;
866 Pretreatment(ArrayOfCurves);
867 Standard_Real aPolynomialCoefficient[3];
869 if ((nb_group==1) && (ClosedG1Flag)){ //treatment of a particular case
870 indexmin=Indexmin(ArrayOfCurves);
871 if (indexmin!=(ArrayOfCurves.Length()-1))
872 ReorderArrayOfG1Curves(ArrayOfCurves,
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;
895 aPolynomialCoefficient[1] = b;
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);
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
907 TColgp_Array1OfPnt Curve1Poles(1,Curve1->NbPoles());
908 Curve1->Poles(Curve1Poles);
910 for (ii=1;ii<=Curve1->NbKnots();ii++)
911 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
913 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
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));
924 GeomConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
925 // BSplCLib::FunctionReparameterise(reparameterise_evaluator,
926 BSplCLib::FunctionReparameterise(ev,
935 TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
936 // BSplCLib::FunctionReparameterise(reparameterise_evaluator,
937 BSplCLib::FunctionReparameterise(ev,
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());
951 GeomConvert_CompCurveToBSplineCurve C(Handle(Geom_BSplineCurve)::DownCast(Curve2));
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();
958 Curve2->SetPeriodic();
959 Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
960 Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
961 Precision::Confusion());
962 ArrayOfConcatenated->SetValue(0,Curve2);
966 for (i=0;i<=nb_group-1;i++){ //principal loop on each G1 continuity
967 nb_vertexG1=0; //group
969 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
972 for (j=index;j<=index+nb_vertexG1;j++){ //secondary loop inside each group
973 Curve1=ArrayOfCurves(j);
975 if (index==j) //initialisation at the begining of the loop
976 ArrayOfConcatenated->SetValue(i,Curve1);
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());
985 index=index+1+nb_vertexG1;
988 //=======================================================================
989 //function : ConcatC1
991 //=======================================================================
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)
1000 ConcatC1(ArrayOfCurves,
1003 ArrayOfConcatenated,
1006 Precision::Angular()) ;
1008 //=======================================================================
1009 //function : ConcatC1
1011 //=======================================================================
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)
1021 {Standard_Integer nb_curve=ArrayOfCurves.Length(),
1027 Standard_Real lambda, //G1 coefficient
1029 Standard_Real PreLast = 0.;
1032 gp_Vec Vec1,Vec2; //concecutive tangential vectors
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) ;
1039 for (i=0 ; i < ArrayOfToler.Length() ; i++) {
1040 local_tolerance(i) = ArrayOfToler(i) ;
1042 for (i=0 ;i<nb_curve; i++){
1044 First=ArrayOfCurves(i)->FirstParameter();
1045 Cont = GeomLProp::Continuity(ArrayOfCurves(i-1),
1051 local_tolerance(i-1),
1053 if (Cont<GeomAbs_C0)
1054 Standard_ConstructionError::Raise("GeomConvert curves not C0");
1056 if (Cont>=GeomAbs_G1)
1057 tabG1(i-1)=Standard_True; //True=G1 continuity
1059 tabG1(i-1)=Standard_False;
1062 PreLast=ArrayOfCurves(i)->LastParameter();
1066 while (index<=nb_curve-1){ //determination of the Wire features
1068 while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1072 nb_vertex_group0=nb_vertexG1;
1073 index=index+1+nb_vertexG1;
1076 if ((ClosedG1Flag)&&(nb_group!=1)){ //sort of the array
1078 ReorderArrayOfG1Curves(ArrayOfCurves,
1086 new TColStd_HArray1OfInteger(0,nb_group);
1087 ArrayOfConcatenated =
1088 new TColGeom_HArray1OfBSplineCurve(0,nb_group-1);
1090 Standard_Boolean fusion;
1091 Standard_Integer k=0;
1093 Pretreatment(ArrayOfCurves);
1094 Standard_Real aPolynomialCoefficient[3];
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,
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));
1110 Curve1=ArrayOfCurves(j);
1112 if (j==0) //initialisation at the begining of the loop
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;
1130 aPolynomialCoefficient[1] = b;
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);
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
1142 TColgp_Array1OfPnt Curve1Poles(1,Curve1->NbPoles());
1143 Curve1->Poles(Curve1Poles);
1145 for (ii=1;ii<=Curve1->NbKnots();ii++)
1146 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1148 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
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));
1159 GeomConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1161 BSplCLib::FunctionReparameterise(ev,
1170 TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1172 BSplCLib::FunctionReparameterise(ev,
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());
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();
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);
1202 for (i=0;i<=nb_group-1;i++){ //principal loop on each G1 continuity
1203 nb_vertexG1=0; //group
1205 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1208 if ((!ClosedG1Flag)||(nb_group==1)){ //filling of the array of index which are kept
1210 ArrayOfIndices->SetValue(k-1,index);
1212 ArrayOfIndices->SetValue(k,0);
1216 ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1);
1218 ArrayOfIndices->SetValue(k,nb_vertex_group0+1);
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));
1225 Curve1=ArrayOfCurves(j);
1227 if (index==j) //initialisation at the begining of the loop
1228 ArrayOfConcatenated->SetValue(i,Curve1);
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());
1238 index=index+1+nb_vertexG1;
1242 //=======================================================================
1243 //function : C0BSplineToC1BSplineCurve
1245 //=======================================================================
1247 void GeomConvert::C0BSplineToC1BSplineCurve(Handle(Geom_BSplineCurve)& BS,
1248 const Standard_Real tolerance,
1249 const Standard_Real AngularTol)
1252 Standard_Boolean fusion;
1253 Handle(TColGeom_HArray1OfBSplineCurve) ArrayOfConcatenated;
1254 //the array with the resulting curves
1256 GeomConvert::C0BSplineToArrayOfC1BSplineCurve(BS, ArrayOfConcatenated,
1257 AngularTol, tolerance);
1259 GeomConvert_CompCurveToBSplineCurve C
1260 (Handle(Geom_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(0)));
1261 if (ArrayOfConcatenated->Length()>=2){
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") ;
1269 BS=C.BSplineCurve();
1272 //=======================================================================
1273 //function : C0BSplineToArrayOfC1BSplineCurve
1275 //=======================================================================
1277 void GeomConvert::C0BSplineToArrayOfC1BSplineCurve(
1278 const Handle(Geom_BSplineCurve) & BS,
1279 Handle(TColGeom_HArray1OfBSplineCurve) & tabBS,
1280 const Standard_Real tolerance)
1282 C0BSplineToArrayOfC1BSplineCurve(BS,
1284 Precision::Angular(),
1288 //=======================================================================
1289 //function : C0BSplineToArrayOfC1BSplineCurve
1291 //=======================================================================
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)
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 ;
1306 // Standard_Boolean fusion;
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())
1316 TColGeom_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1);
1317 TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2);
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
1328 //with the curves C1 segmented
1329 while (BSMults(j)<BS->Degree() && j < BS->LastUKnotIndex())
1333 Handle(Geom_BSplineCurve)
1334 BSbis=Handle(Geom_BSplineCurve::DownCast(BS->Copy()));
1335 BSbis->Segment(U1,U2);
1336 ArrayOfCurves(i)=BSbis;
1339 Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1341 BS->D1(BS->FirstParameter(),point,V1);
1342 BS->D1(BS->LastParameter(),point,V2);
1344 if ((BS->IsClosed())&&(V1.IsParallel(V2,AngularTolerance))){
1345 //check if the BSpline is closed G1
1346 closed_flag = Standard_True ;
1349 GeomConvert::ConcatC1(ArrayOfCurves,
1358 tabBS = new TColGeom_HArray1OfBSplineCurve(0,0);
1359 tabBS->SetValue(0,BS);