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
19 #include <Geom2dConvert.ixx>
21 #include <Convert_ConicToBSplineCurve.hxx>
22 #include <Convert_CircleToBSplineCurve.hxx>
23 #include <Convert_EllipseToBSplineCurve.hxx>
24 #include <Convert_HyperbolaToBSplineCurve.hxx>
25 #include <Convert_ParabolaToBSplineCurve.hxx>
30 #include <gp_Circ2d.hxx>
31 #include <gp_Elips2d.hxx>
32 #include <gp_Parab2d.hxx>
33 #include <gp_Hypr2d.hxx>
34 #include <gp_Pnt2d.hxx>
36 #include <gp_Trsf2d.hxx>
37 #include <gp_Vec2d.hxx>
38 #include <gp_Dir2d.hxx>
40 #include <BSplCLib.hxx>
42 #include <Geom2d_Curve.hxx>
43 #include <Geom2d_Line.hxx>
44 #include <Geom2d_Circle.hxx>
45 #include <Geom2d_Ellipse.hxx>
46 #include <Geom2d_Hyperbola.hxx>
47 #include <Geom2d_Parabola.hxx>
48 #include <Geom2d_Geometry.hxx>
49 #include <Geom2d_BSplineCurve.hxx>
50 #include <Geom2d_BezierCurve.hxx>
51 #include <Geom2d_TrimmedCurve.hxx>
52 #include <Geom2d_Conic.hxx>
53 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
54 #include <Geom2dConvert_ApproxCurve.hxx>
55 #include <Geom2d_OffsetCurve.hxx>
56 #include <GeomAbs_Shape.hxx>
60 #include <Precision.hxx>
64 #include <TColStd_Array1OfReal.hxx>
65 #include <TColStd_Array1OfBoolean.hxx>
66 #include <TColStd_HArray1OfReal.hxx>
67 #include <TColStd_Array1OfInteger.hxx>
68 #include <TColgp_Array1OfPnt2d.hxx>
70 #include <Standard_OutOfRange.hxx>
71 #include <Standard_DomainError.hxx>
73 #include <Standard_ConstructionError.hxx>
75 typedef gp_Circ2d Circ2d;
76 typedef gp_Elips2d Elips2d;
77 typedef gp_Hypr2d Hypr2d;
78 typedef gp_Parab2d Parab2d;
79 typedef gp_Pnt2d Pnt2d;
80 typedef gp_Trsf2d Trsf2d;
82 typedef Geom2d_Curve Curve;
83 typedef Geom2d_BSplineCurve BSplineCurve;
84 typedef Handle(Geom2d_Curve) Handle(Curve);
85 typedef Handle(Geom2d_Conic) Handle(Conic);
86 typedef Handle(Geom2d_Circle) Handle(Circle);
87 typedef Handle(Geom2d_Ellipse) Handle(Ellipse);
88 typedef Handle(Geom2d_Hyperbola) Handle(Hyperbola);
89 typedef Handle(Geom2d_Parabola) Handle(Parabola);
90 typedef Handle(Geom2d_Geometry) Handle(Geometry);
91 typedef Handle(Geom2d_BezierCurve) Handle(BezierCurve);
92 typedef Handle(Geom2d_TrimmedCurve) Handle(TrimmedCurve);
93 typedef Handle(Geom2d_BSplineCurve) Handle(BSplineCurve);
96 typedef TColStd_Array1OfReal Array1OfReal;
97 typedef TColStd_Array1OfInteger Array1OfInteger;
98 typedef TColgp_Array1OfPnt2d Array1OfPnt2d;
102 //=======================================================================
103 //function : BSplineCurveBuilder
105 //=======================================================================
107 static Handle(BSplineCurve) BSplineCurveBuilder (
109 const Handle(Conic)& TheConic,
110 const Convert_ConicToBSplineCurve& Convert
113 Handle(BSplineCurve) TheCurve;
114 Standard_Integer NbPoles = Convert.NbPoles();
115 Standard_Integer NbKnots = Convert.NbKnots();
116 Array1OfPnt2d Poles (1, NbPoles);
117 Array1OfReal Weights (1, NbPoles);
118 Array1OfReal Knots (1, NbKnots);
119 Array1OfInteger Mults (1, NbKnots);
121 for (i = 1; i <= NbPoles; i++) {
122 Poles (i) = Convert.Pole (i);
123 Weights (i) = Convert.Weight (i);
125 for (i = 1; i <= NbKnots; i++) {
126 Knots (i) = Convert.Knot (i);
127 Mults (i) = Convert.Multiplicity (i);
129 TheCurve = new BSplineCurve (
130 Poles, Weights, Knots, Mults,
131 Convert.Degree(), Convert.IsPeriodic());
133 gp_Ax22d Axis = TheConic->Position();
134 if ( ( Axis.XDirection() ^ Axis.YDirection()) < 0.) {
135 // Then the axis is left-handed, apply a symetry to the curve.
137 Sym.SetMirror(gp::OX2d());
138 TheCurve->Transform(Sym);
142 T.SetTransformation (TheConic->XAxis(), gp::OX2d());
143 Handle(BSplineCurve) Cres =
144 Handle(BSplineCurve)::DownCast(TheCurve->Transformed (T));
149 //=======================================================================
150 //function : SplitBSplineCurve
152 //=======================================================================
154 Handle(BSplineCurve) Geom2dConvert::SplitBSplineCurve (
156 const Handle(BSplineCurve)& C,
157 const Standard_Integer FromK1,
158 const Standard_Integer ToK2,
159 const Standard_Boolean SameOrientation
162 Standard_Integer TheFirst = C->FirstUKnotIndex ();
163 Standard_Integer TheLast = C->LastUKnotIndex ();
164 if (FromK1 == ToK2) Standard_DomainError::Raise();
165 Standard_Integer FirstK = Min (FromK1, ToK2);
166 Standard_Integer LastK = Max (FromK1, ToK2);
167 if (FirstK < TheFirst || LastK > TheLast) Standard_OutOfRange::Raise();
169 Handle(BSplineCurve) NewCurve = Handle(BSplineCurve)::DownCast(C->Copy());
171 NewCurve->Segment(C->Knot(FirstK),C->Knot(LastK));
173 if (C->IsPeriodic()) {
174 if (!SameOrientation) NewCurve->Reverse();
177 if (FromK1 > ToK2) NewCurve->Reverse();
183 //=======================================================================
184 //function : SplitBSplineCurve
186 //=======================================================================
188 Handle(BSplineCurve) Geom2dConvert::SplitBSplineCurve (
190 const Handle(BSplineCurve)& C,
191 const Standard_Real FromU1,
192 const Standard_Real ToU2,
193 const Standard_Real, // ParametricTolerance,
194 const Standard_Boolean SameOrientation
197 Standard_Real FirstU = Min( FromU1, ToU2);
198 Standard_Real LastU = Max( FromU1, ToU2);
200 Handle (Geom2d_BSplineCurve) C1
201 = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy());
203 C1->Segment(FirstU, LastU);
205 if (C->IsPeriodic()) {
206 if (!SameOrientation) C1->Reverse();
209 if (FromU1 > ToU2) C1->Reverse();
216 //=======================================================================
217 //function : CurveToBSplineCurve
219 //=======================================================================
221 Handle(BSplineCurve) Geom2dConvert::CurveToBSplineCurve (
223 const Handle(Curve)& C,
224 const Convert_ParameterisationType Parameterisation)
227 Handle (BSplineCurve) TheCurve;
229 if (C->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
231 Handle(TrimmedCurve) Ctrim = Handle(TrimmedCurve)::DownCast(C);
232 Curv = Ctrim->BasisCurve();
233 Standard_Real U1 = Ctrim->FirstParameter();
234 Standard_Real U2 = Ctrim->LastParameter();
236 // Si la courbe n'est pas vraiment restreinte, on ne risque pas
237 // le Raise dans le BS->Segment.
238 if (!Curv->IsPeriodic()) {
239 if (U1 < Curv->FirstParameter())
240 U1 = Curv->FirstParameter();
241 if (U2 > Curv->LastParameter())
242 U2 = Curv->LastParameter();
245 if (Curv->IsKind(STANDARD_TYPE(Geom2d_Line))) {
246 gp_Pnt2d Pdeb = Ctrim->StartPoint();
247 gp_Pnt2d Pfin = Ctrim->EndPoint();
248 Array1OfPnt2d Poles (1, 2);
251 Array1OfReal Knots (1, 2);
252 Knots (1) = Ctrim->FirstParameter ();
253 Knots (2) = Ctrim->LastParameter();
254 Array1OfInteger Mults (1, 2);
257 Standard_Integer Degree = 1;
258 TheCurve = new Geom2d_BSplineCurve (Poles, Knots, Mults, Degree);
261 else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
262 Handle(Circle) TheConic= Handle(Circle)::DownCast(Curv);
263 Circ2d C2d (gp::OX2d(), TheConic->Radius());
264 if(Parameterisation != Convert_RationalC1) {
265 Convert_CircleToBSplineCurve Convert (C2d,
269 TheCurve = BSplineCurveBuilder (TheConic, Convert);
273 Convert_CircleToBSplineCurve Convert (C2d,
277 TheCurve = BSplineCurveBuilder (TheConic, Convert);
279 else { // split circle to avoide numerical
280 // overflow when U2 - U1 =~ 2*PI
282 Standard_Real Umed = (U1 + U2) * .5;
283 Convert_CircleToBSplineCurve Convert1 (C2d,
288 Handle (BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
290 Convert_CircleToBSplineCurve Convert2 (C2d,
295 Handle (BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
297 Geom2dConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
300 CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
303 TheCurve = CCTBSpl.BSplineCurve();
308 else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
309 Handle(Ellipse) TheConic = Handle(Ellipse)::DownCast(Curv);
311 Elips2d E2d (gp::OX2d(),
312 TheConic->MajorRadius(),
313 TheConic->MinorRadius());
314 if(Parameterisation != Convert_RationalC1) {
315 Convert_EllipseToBSplineCurve Convert (E2d,
319 TheCurve = BSplineCurveBuilder (TheConic, Convert);
323 Convert_EllipseToBSplineCurve Convert (E2d,
327 TheCurve = BSplineCurveBuilder (TheConic, Convert);
329 else { // split ellipse to avoide numerical
330 // overflow when U2 - U1 =~ 2*PI
332 Standard_Real Umed = (U1 + U2) * .5;
333 Convert_EllipseToBSplineCurve Convert1 (E2d,
338 Handle (BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
340 Convert_EllipseToBSplineCurve Convert2 (E2d,
345 Handle (BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
347 Geom2dConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
350 CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
353 TheCurve = CCTBSpl.BSplineCurve();
358 else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) {
359 Handle(Hyperbola) TheConic = Handle(Hyperbola)::DownCast(Curv);
361 Hypr2d H2d (gp::OX2d(),
362 TheConic->MajorRadius(), TheConic->MinorRadius());
363 Convert_HyperbolaToBSplineCurve Convert (H2d, U1, U2);
364 TheCurve = BSplineCurveBuilder (TheConic, Convert);
367 else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Parabola))) {
368 Handle(Parabola) TheConic = Handle(Parabola)::DownCast(Curv);
370 Parab2d Prb2d (gp::OX2d(), TheConic->Focal());
371 Convert_ParabolaToBSplineCurve Convert (Prb2d, U1, U2);
372 TheCurve = BSplineCurveBuilder (TheConic, Convert);
375 else if (Curv->IsKind (STANDARD_TYPE(Geom2d_BezierCurve))) {
377 Handle(BezierCurve) CBez = Handle(BezierCurve)::DownCast(Curv->Copy());
379 CBez->Segment (U1, U2);
380 Standard_Integer NbPoles = CBez->NbPoles();
381 Standard_Integer Degree = CBez->Degree();
382 Array1OfPnt2d Poles (1, NbPoles);
383 Array1OfReal Knots (1, 2);
384 Array1OfInteger Mults (1, 2);
387 Mults (1) = Degree + 1;
388 Mults (2) = Degree + 1;
390 if (CBez->IsRational()) {
391 Array1OfReal Weights (1, NbPoles);
392 CBez->Weights (Weights);
393 TheCurve = new BSplineCurve (Poles, Weights, Knots, Mults, Degree);
396 TheCurve = new BSplineCurve (Poles, Knots, Mults, Degree);
400 else if (Curv->IsKind (STANDARD_TYPE(Geom2d_BSplineCurve))) {
401 TheCurve = Handle(Geom2d_BSplineCurve)::DownCast(Curv->Copy());
402 TheCurve->Segment(U1,U2);
405 else if (Curv->IsKind (STANDARD_TYPE(Geom2d_OffsetCurve))) {
407 Standard_Real Tol2d = 1.e-4;
408 GeomAbs_Shape Order = GeomAbs_C2;
409 Standard_Integer MaxSegments = 16, MaxDegree = 14;
410 Geom2dConvert_ApproxCurve ApprCOffs(C, Tol2d, Order,
411 MaxSegments, MaxDegree);
412 if (ApprCOffs.HasResult())
413 TheCurve = ApprCOffs.Curve();
414 else Standard_ConstructionError::Raise();
417 else { Standard_DomainError::Raise("No such curve"); }
424 if (C->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
425 Handle(Ellipse) TheConic = Handle(Ellipse)::DownCast(C);
427 Elips2d E2d (gp::OX2d(),
428 TheConic->MajorRadius(), TheConic->MinorRadius());
429 Convert_EllipseToBSplineCurve Convert (E2d,
431 TheCurve = BSplineCurveBuilder (TheConic, Convert);
432 TheCurve->SetPeriodic();
435 else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
436 Handle(Circle) TheConic = Handle(Circle)::DownCast(C);
438 Circ2d C2d (gp::OX2d(), TheConic->Radius());
439 Convert_CircleToBSplineCurve Convert (C2d,
441 TheCurve = BSplineCurveBuilder (TheConic, Convert);
442 TheCurve->SetPeriodic();
445 else if (C->IsKind (STANDARD_TYPE(Geom2d_BezierCurve))) {
446 Handle(BezierCurve) CBez = Handle(BezierCurve)::DownCast(C);
448 Standard_Integer NbPoles = CBez->NbPoles();
449 Standard_Integer Degree = CBez->Degree();
450 Array1OfPnt2d Poles (1, NbPoles);
451 Array1OfReal Knots (1, 2);
452 Array1OfInteger Mults (1, 2);
455 Mults (1) = Degree + 1;
456 Mults (2) = Degree + 1;
458 if (CBez->IsRational()) {
459 Array1OfReal Weights (1, NbPoles);
460 CBez->Weights (Weights);
461 TheCurve = new BSplineCurve (Poles, Weights, Knots, Mults, Degree);
464 TheCurve = new BSplineCurve (Poles, Knots, Mults, Degree);
467 else if (C->IsKind (STANDARD_TYPE(Geom2d_BSplineCurve))) {
468 TheCurve = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy());
471 else if (C->IsKind (STANDARD_TYPE(Geom2d_OffsetCurve))) {
473 Standard_Real Tol2d = 1.e-4;
474 GeomAbs_Shape Order = GeomAbs_C2;
475 Standard_Integer MaxSegments = 16, MaxDegree = 14;
476 Geom2dConvert_ApproxCurve ApprCOffs(C, Tol2d, Order,
477 MaxSegments, MaxDegree);
478 if (ApprCOffs.HasResult())
479 TheCurve = ApprCOffs.Curve();
480 else Standard_ConstructionError::Raise();
483 else { Standard_DomainError::Raise(); }
489 //=======================================================================
490 //class : law_evaluator
492 //=======================================================================
494 class Geom2dConvert_law_evaluator : public BSplCLib_EvaluatorFunction
499 Geom2dConvert_law_evaluator (const Handle(Geom2d_BSplineCurve)& theAncore)
500 : myAncore (theAncore) {}
502 virtual void Evaluate (const Standard_Integer theDerivativeRequest,
503 const Standard_Real* theStartEnd,
504 const Standard_Real theParameter,
505 Standard_Real& theResult,
506 Standard_Integer& theErrorCode) const
509 if (!myAncore.IsNull() &&
510 theParameter >= theStartEnd[0] &&
511 theParameter <= theStartEnd[1] &&
512 theDerivativeRequest == 0)
515 myAncore->D0 (theParameter, aPoint);
516 theResult = aPoint.Coord (2);
524 Handle(Geom2d_BSplineCurve) myAncore;
529 //=======================================================================
530 //function : MultNumandDenom
531 //purpose : Multiply two BSpline curves to make one
532 //=======================================================================
535 static Handle(Geom2d_BSplineCurve) MultNumandDenom(const Handle(Geom2d_BSplineCurve)& a ,
536 const Handle(Geom2d_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_Array1OfPnt2d BSPoles(1,BS->NbPoles());
546 Handle(Geom2d_BSplineCurve) res;
547 Handle(TColStd_HArray1OfReal) resKnots;
548 Handle(TColStd_HArray1OfInteger) resMults;
549 Standard_Real start_value,end_value;
550 Standard_Real tolerance=Precision::Confusion();
551 Standard_Integer resNbPoles,degree,
556 BS->Multiplicities(BSMults);
558 BS->Weights(BSWeights);
559 BS->KnotSequence(BSFlatKnots);
560 start_value = BSKnots(1);
561 end_value = BSKnots(BS->NbKnots());
565 a->Multiplicities(aMults);
566 BSplCLib::Reparametrize(BS->FirstParameter(),BS->LastParameter(),aKnots);
567 Handle(Geom2d_BSplineCurve) anAncore = new Geom2d_BSplineCurve (aPoles, aKnots, aMults, a->Degree());
569 BSplCLib::MergeBSplineKnots(tolerance,start_value,end_value,
570 a->Degree(),aKnots,aMults,
571 BS->Degree(),BSKnots,BSMults,
572 resNbPoles,resKnots,resMults);
573 degree=BS->Degree()+a->Degree();
574 TColgp_Array1OfPnt2d resNumPoles(1,resNbPoles);
575 TColStd_Array1OfReal resDenPoles(1,resNbPoles);
576 TColgp_Array1OfPnt2d resPoles(1,resNbPoles);
577 TColStd_Array1OfReal resFlatKnots(1,resNbPoles+degree+1);
578 BSplCLib::KnotSequence(resKnots->Array1(),resMults->Array1(),resFlatKnots);
579 for (ii=1;ii<=BS->NbPoles();ii++)
580 for (jj=1;jj<=2;jj++)
581 BSPoles(ii).SetCoord(jj,BSPoles(ii).Coord(jj)*BSWeights(ii));
583 Geom2dConvert_law_evaluator ev (anAncore);
584 BSplCLib::FunctionMultiply(ev,
592 BSplCLib::FunctionMultiply(ev,
600 // BSplCLib::FunctionMultiply(law_evaluator,
608 // BSplCLib::FunctionMultiply(law_evaluator,
616 for (ii=1;ii<=resNbPoles;ii++)
618 resPoles(ii).SetCoord(jj,resNumPoles(ii).Coord(jj)/resDenPoles(ii));
619 res = new Geom2d_BSplineCurve(resPoles,resDenPoles,resKnots->Array1(),resMults->Array1(),degree);
623 //=======================================================================
624 //function : Pretreatment
625 //purpose : Put the two first and two last weigths at one if they are
627 //=======================================================================
629 static void Pretreatment(TColGeom2d_Array1OfBSplineCurve& tab)
631 {Standard_Integer i,j;
634 for (i=0;i<=(tab.Length()-1);i++){
635 if (tab(i)->IsRational()) {
636 a=tab(i)->Weight(1) ;
637 if ((tab(i)->Weight(2)==a)&&
638 (tab(i)->Weight(tab(i)->NbPoles()-1)==a) &&
639 (tab(i)->Weight(tab(i)->NbPoles())==a))
641 for (j=1;j<=tab(i)->NbPoles();j++)
642 tab(i)->SetWeight(j,tab(i)->Weight(j)/a) ;
647 //=======================================================================
648 //function : NeedToBeTreated
649 //purpose : Say if the BSpline is rationnal and if the two first and two
650 // last weigths are different
651 //=======================================================================
653 static Standard_Boolean NeedToBeTreated(const Handle(Geom2d_BSplineCurve)& BS)
656 TColStd_Array1OfReal tabWeights(1,BS->NbPoles());
657 if (BS->IsRational()) {
658 BS->Weights(tabWeights);
659 if ((BSplCLib::IsRational(tabWeights,1,BS->NbPoles()))&&
660 ((BS->Weight(1)<(1-Precision::Confusion()))||
661 (BS->Weight(1)>(1+Precision::Confusion()))||
662 (BS->Weight(2)<(1-Precision::Confusion()))||
663 (BS->Weight(2)>(1+Precision::Confusion()))||
664 (BS->Weight(BS->NbPoles()-1)<(1-Precision::Confusion()))||
665 (BS->Weight(BS->NbPoles()-1)>(1+Precision::Confusion()))||
666 (BS->Weight(BS->NbPoles())<(1-Precision::Confusion()))||
667 (BS->Weight(BS->NbPoles())>(1+Precision::Confusion()))))
668 return Standard_True;
670 return Standard_False;
673 return Standard_False ;
677 //=======================================================================
678 //function : Need2DegRepara
679 //purpose : in the case of wire closed G1 it says if you will to use a
680 // two degree reparametrisation to close it C1
681 //=======================================================================
683 static Standard_Boolean Need2DegRepara(const TColGeom2d_Array1OfBSplineCurve& tab)
688 Standard_Real Rapport=1.0e0;
690 for (i=0;i<=tab.Length()-2;i++){
691 tab(i+1)->D1(tab(i+1)->FirstParameter(),Pint,Vec1);
692 tab(i)->D1(tab(i)->LastParameter(),Pint,Vec2);
693 Rapport=Rapport*Vec2.Magnitude()/Vec1.Magnitude();
695 if ((Rapport<=(1.0e0 +Precision::Confusion()))&&(Rapport>=(1.0e0-Precision::Confusion())))
696 return Standard_False;
698 return Standard_True;
701 //=======================================================================
702 //function : Indexmin
703 //purpose : Give the index of the curve which has the lowest degree
704 //=======================================================================
706 static Standard_Integer Indexmin(const TColGeom2d_Array1OfBSplineCurve& tab)
708 Standard_Integer i,index=0,degree;
710 degree=tab(0)->Degree();
711 for (i=0;i<=tab.Length()-1;i++)
712 if (tab(i)->Degree()<=degree){
713 degree=tab(i)->Degree();
719 //=======================================================================
720 //function : NewTabClosedG1
722 //=======================================================================
724 static void ReorderArrayOfG1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
725 TColStd_Array1OfReal& ArrayOfToler,
726 TColStd_Array1OfBoolean& tabG1,
727 const Standard_Integer StartIndex,
728 const Standard_Real ClosedTolerance)
731 TColGeom2d_Array1OfBSplineCurve ArraybisOfCurves(0,ArrayOfCurves.Length()-1);
732 TColStd_Array1OfReal ArraybisOfToler(0,ArrayOfToler.Length()-1);
733 TColStd_Array1OfBoolean tabbisG1(0,tabG1.Length()-1);
735 for (i=0;i<=ArrayOfCurves.Length()-1;i++){
736 if (i!=ArrayOfCurves.Length()-1){
737 ArraybisOfCurves(i)=ArrayOfCurves(i);
738 ArraybisOfToler(i)=ArrayOfToler(i);
739 tabbisG1(i)=tabG1(i);
742 ArraybisOfCurves(i)=ArrayOfCurves(i);
745 for (i=0;i<=(ArrayOfCurves.Length()-(StartIndex+2));i++){
746 ArrayOfCurves(i)=ArraybisOfCurves(i+StartIndex+1);
747 if (i!=(ArrayOfCurves.Length()-(StartIndex+2))){
748 ArrayOfToler(i)=ArraybisOfToler(i+StartIndex+1);
749 tabG1(i)=tabbisG1(i+StartIndex+1);
753 ArrayOfToler(ArrayOfCurves.Length()-(StartIndex+2))=ClosedTolerance;
754 tabG1(ArrayOfCurves.Length()-(StartIndex+2))=Standard_True;
756 for (i=(ArrayOfCurves.Length()-(StartIndex+1));i<=(ArrayOfCurves.Length()-1);i++){
757 if (i!=ArrayOfCurves.Length()-1){
758 ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
759 ArrayOfToler(i)=ArraybisOfToler(i-(ArrayOfCurves.Length()-(StartIndex+1)));
760 tabG1(i)=tabbisG1(i-(ArrayOfCurves.Length()-(StartIndex+1)));
763 ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
767 //=======================================================================
768 //function : GeomAbsToInteger
770 //=======================================================================
772 static Standard_Integer GeomAbsToInteger(const GeomAbs_Shape gcont)
774 Standard_Integer cont=0 ;
800 //=======================================================================
801 //function : Continuity
803 //=======================================================================
805 static GeomAbs_Shape Continuity(const Handle(Geom2d_Curve)& C1,
806 const Handle(Geom2d_Curve)& C2,
807 const Standard_Real u1,
808 const Standard_Real u2,
809 const Standard_Boolean r1,
810 const Standard_Boolean r2,
811 const Standard_Real tl,
812 const Standard_Real ta)
814 GeomAbs_Shape cont = GeomAbs_C0;
815 Standard_Integer index1,
817 Standard_Real tolerance,value ;
818 // Standard_Boolean fini = Standard_False;
820 // gp_Dir2d dir1,dir2;
821 gp_Pnt2d point1, point2 ;
822 Standard_Integer cont1, cont2 ;
823 GeomAbs_Shape gcont1 = C1->Continuity(), gcont2 = C2->Continuity();
824 cont1 = GeomAbsToInteger(gcont1) ;
825 cont2 = GeomAbsToInteger(gcont2) ;
827 Handle(Geom2d_Curve) aCurve1 = C1 ;
828 Handle(Geom2d_Curve) aCurve2 = C2 ;
829 if (C1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))){
830 Handle(Geom2d_TrimmedCurve) aTrimmed = Handle(Geom2d_TrimmedCurve) ::DownCast(aCurve1) ;
831 aCurve1 = aTrimmed->BasisCurve() ;
833 if (C2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))){
834 Handle(Geom2d_TrimmedCurve) aTrimmed = Handle(Geom2d_TrimmedCurve) ::DownCast(aCurve2) ;
835 aCurve2 = aTrimmed->BasisCurve() ;
837 if (aCurve1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))){
838 Handle(Geom2d_BSplineCurve) BSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(aCurve1) ;
839 BSplineCurve->Resolution(tl,
841 BSplineCurve->LocateU(u1,
846 if (index1 > 1 && index2 < BSplineCurve->NbKnots() && index1 == index2) {
847 cont1 = BSplineCurve->Degree() - BSplineCurve->Multiplicity(index1) ;
853 if (aCurve2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))){
854 Handle(Geom2d_BSplineCurve) BSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(aCurve2) ;
855 BSplineCurve->Resolution(tl,
857 BSplineCurve->LocateU(u2,
862 if (index1 > 1 && index2 < BSplineCurve->NbKnots() && index1 == index2) {
863 cont2 = BSplineCurve->Degree() - BSplineCurve->Multiplicity(index1) ;
875 if (point1.SquareDistance(point2) <= tl * tl) {
879 if (d1.SquareMagnitude() >= tl * tl &&
880 d2.SquareMagnitude() >= tl * tl) {
882 d1.SetCoord(-d1.X(),-d1.Y()) ;
885 d2.SetCoord(-d2.X(),-d2.Y()) ;
888 if ((d1.Magnitude()<=(d2.Magnitude()+tl))&&
889 (d1.Magnitude()>=(d2.Magnitude()-tl))&&
890 (value/(d1.Magnitude()*d2.Magnitude()) >= 1.0e0 - ta * ta)) {
896 value = Abs(d1.Dot(d2)) ;
897 if (value >= 1.0e0 - ta * ta) {
906 Standard_Failure::Raise("Courbes non jointives");
910 //=======================================================================
911 //function : Continuity
913 //=======================================================================
915 static GeomAbs_Shape Continuity(const Handle(Geom2d_Curve)& C1,
916 const Handle(Geom2d_Curve)& C2,
917 const Standard_Real u1,
918 const Standard_Real u2,
919 const Standard_Boolean r1,
920 const Standard_Boolean r2)
922 return Continuity(C1,C2,u1,u2,r1,r2,
923 Precision::Confusion(),Precision::Angular());
926 //=======================================================================
927 //class :reparameterise_evaluator
929 //=======================================================================
931 class Geom2dConvert_reparameterise_evaluator : public BSplCLib_EvaluatorFunction
936 Geom2dConvert_reparameterise_evaluator (const Standard_Real thePolynomialCoefficient[3])
938 memcpy(myPolynomialCoefficient, thePolynomialCoefficient, sizeof(myPolynomialCoefficient));
941 virtual void Evaluate (const Standard_Integer theDerivativeRequest,
942 const Standard_Real* /*theStartEnd*/,
943 const Standard_Real theParameter,
944 Standard_Real& theResult,
945 Standard_Integer& theErrorCode) const
948 PLib::EvalPolynomial (theParameter,
949 theDerivativeRequest,
952 *((Standard_Real* )myPolynomialCoefficient), // function really only read values from this array
958 Standard_Real myPolynomialCoefficient[3];
962 //=======================================================================
963 //function : ConcatG1
965 //=======================================================================
967 void Geom2dConvert::ConcatG1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
968 const TColStd_Array1OfReal& ArrayOfToler,
969 Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
970 const Standard_Boolean ClosedFlag,
971 const Standard_Real ClosedTolerance)
973 {Standard_Integer nb_curve=ArrayOfCurves.Length(),
979 Standard_Real lambda, //coeff de raccord G1
981 gp_Vec2d Vec1,Vec2; //vecteurs tangents consecutifs
983 Handle(Geom2d_BSplineCurve) Curve1,Curve2;
984 TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //tableau de continuite G1 aux raccords
985 TColStd_Array1OfReal local_tolerance(0,
986 ArrayOfToler.Length()-1) ;
988 for (i= 0; i < ArrayOfToler.Length() ; i++) {
989 local_tolerance(i) = ArrayOfToler(i) ;
991 for (i=0 ;i<nb_curve; i++){
993 First=ArrayOfCurves(i)->FirstParameter();
994 if (Continuity(ArrayOfCurves(i-1),
998 Standard_True)<GeomAbs_C0)
999 Standard_ConstructionError::Raise("Geom2dConvert curves not C0") ; //renvoi d'une erreur
1001 if (Continuity(ArrayOfCurves(i-1),
1005 Standard_True)>=GeomAbs_G1)
1006 tabG1(i-1)=Standard_True; //True=Continuite G1
1008 tabG1(i-1)=Standard_False;
1011 PreLast=ArrayOfCurves(i)->LastParameter();
1015 while (index<=nb_curve-1){ //determination des caracteristiques du Wire
1017 while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1021 nb_vertex_group0=nb_vertexG1;
1022 index=index+1+nb_vertexG1;
1025 if ((ClosedFlag)&&(nb_group!=1)){ //rearrangement du tableau
1027 ReorderArrayOfG1(ArrayOfCurves,
1034 ArrayOfConcatenated = new
1035 TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1);
1037 Standard_Boolean fusion;
1038 // Standard_Integer k=0;
1040 Pretreatment(ArrayOfCurves);
1042 Standard_Real aPolynomialCoefficient[3];
1044 if ((nb_group==1) && (ClosedFlag)){ //traitement d'un cas particulier
1045 indexmin=Indexmin(ArrayOfCurves);
1046 if (indexmin!=(ArrayOfCurves.Length()-1))
1047 ReorderArrayOfG1(ArrayOfCurves,
1052 Curve2=ArrayOfCurves(0);
1053 for (j=1;j<=nb_curve-1;j++){ //boucle secondaire a l'interieur de chaque groupe
1054 Curve1=ArrayOfCurves(j);
1055 if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){
1056 Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1057 Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1058 lambda=Vec2.Magnitude()/Vec1.Magnitude();
1059 TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1060 Curve1->Knots(KnotC1);
1061 Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1062 ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1063 Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1064 Standard_Real tmax,a,b,c,
1065 umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1066 tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1067 a=(lambda*lambda2-1)/(2*lambda*tmax);
1068 aPolynomialCoefficient[2] = a;
1070 aPolynomialCoefficient[1] = b;
1072 aPolynomialCoefficient[0] = c;
1073 TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1074 TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots());
1075 Curve1->Multiplicities(KnotC1Mults);
1076 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1078 for (ii=2;ii<=KnotC1.Length();ii++) {
1079 // KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1080 KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1082 TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles());
1083 Curve1->Poles(Curve1Poles);
1085 for (ii=1;ii<=Curve1->NbKnots();ii++)
1086 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1088 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1090 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1091 TColgp_Array1OfPnt2d NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1092 Standard_Integer Status;
1093 TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1094 Curve1->Weights(Curve1Weights);
1095 for (ii=1;ii<=Curve1->NbPoles();ii++)
1096 for (jj=1;jj<=2;jj++)
1097 Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1099 Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1100 BSplCLib::FunctionReparameterise(ev,
1109 TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1110 BSplCLib::FunctionReparameterise(ev,
1119 // BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1120 // Curve1->Degree(),
1124 // 2*Curve1->Degree(),
1128 // TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1129 // BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1130 // Curve1->Degree(),
1134 // 2*Curve1->Degree(),
1138 for (ii=1;ii<=NewPoles.Length();ii++)
1139 for (jj=1;jj<=2;jj++)
1140 NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1141 Curve1= new Geom2d_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
1143 Geom2dConvert_CompCurveToBSplineCurve C(Handle(Geom2d_BSplineCurve)::DownCast(Curve2));
1144 fusion=C.Add(Curve1,
1145 local_tolerance(j-1)); //fusion de deux courbes adjacentes
1146 if (fusion==Standard_False)
1147 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1148 Curve2=C.BSplineCurve();
1150 Curve2->SetPeriodic(); //1 seule courbe C1
1151 Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
1152 Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1153 Precision::Confusion());
1154 ArrayOfConcatenated->SetValue(0,Curve2);
1158 for (i=0;i<=nb_group-1;i++){ //boucle principale sur chaque groupe de
1159 nb_vertexG1=0; //continuite interne G1
1161 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1164 for (j=index;j<=index+nb_vertexG1;j++){ //boucle secondaire a l'interieur de chaque groupe
1165 Curve1=ArrayOfCurves(j);
1167 if (index==j) //initialisation en debut de groupe
1168 ArrayOfConcatenated->SetValue(i,Curve1);
1170 Geom2dConvert_CompCurveToBSplineCurve C(Handle(Geom2d_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(i)));
1171 fusion=C.Add(Curve1,ArrayOfToler(j-1)); //fusion de deux courbes adjacentes
1172 if (fusion==Standard_False)
1173 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1174 ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1177 index=index+1+nb_vertexG1;
1180 //=======================================================================
1181 //function : ConcatC1
1183 //=======================================================================
1185 void Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
1186 const TColStd_Array1OfReal& ArrayOfToler,
1187 Handle(TColStd_HArray1OfInteger)& ArrayOfIndices,
1188 Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1189 const Standard_Boolean ClosedFlag,
1190 const Standard_Real ClosedTolerance)
1192 ConcatC1(ArrayOfCurves,
1195 ArrayOfConcatenated,
1198 Precision::Angular()) ;
1200 //=======================================================================
1201 //function : ConcatC1
1203 //=======================================================================
1205 void Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves,
1206 const TColStd_Array1OfReal& ArrayOfToler,
1207 Handle(TColStd_HArray1OfInteger)& ArrayOfIndices,
1208 Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated,
1209 const Standard_Boolean ClosedFlag,
1210 const Standard_Real ClosedTolerance,
1211 const Standard_Real AngularTolerance)
1213 {Standard_Integer nb_curve=ArrayOfCurves.Length(),
1219 Standard_Real lambda, //coeff de raccord G1
1221 gp_Vec2d Vec1,Vec2; //vecteurs tangents consecutifs
1223 Handle(Geom2d_BSplineCurve) Curve1,Curve2;
1224 TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //tableau de continuite G1 aux raccords
1225 TColStd_Array1OfReal local_tolerance(0,
1226 ArrayOfToler.Length()-1) ;
1230 for (i=0 ; i < ArrayOfToler.Length() ; i++) {
1231 local_tolerance(i) = ArrayOfToler(i) ;
1233 for (i=0 ;i<nb_curve; i++){
1235 First=ArrayOfCurves(i)->FirstParameter();
1236 if (Continuity(ArrayOfCurves(i-1),
1242 AngularTolerance)<GeomAbs_C0)
1243 Standard_ConstructionError::Raise("Geom2dConvert curves not C0") ; //renvoi d'une erreur
1245 if (Continuity(ArrayOfCurves(i-1),
1252 AngularTolerance)>=GeomAbs_G1)
1253 tabG1(i-1)=Standard_True; //True=Continuite G1
1255 tabG1(i-1)=Standard_False;
1258 PreLast=ArrayOfCurves(i)->LastParameter();
1262 while (index<=nb_curve-1){ //determination des caracteristiques du Wire
1264 while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1268 nb_vertex_group0=nb_vertexG1;
1269 index=index+1+nb_vertexG1;
1272 if ((ClosedFlag)&&(nb_group!=1)){ //rearrangement du tableau
1274 ReorderArrayOfG1(ArrayOfCurves,
1281 ArrayOfIndices = new TColStd_HArray1OfInteger(0,nb_group);
1282 ArrayOfConcatenated = new TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1);
1284 Standard_Boolean fusion;
1285 Standard_Integer k=0;
1287 Pretreatment(ArrayOfCurves);
1288 Standard_Real aPolynomialCoefficient[3];
1290 if ((nb_group==1) && (ClosedFlag)){ //traitement d'un cas particulier
1291 ArrayOfIndices->SetValue(0,0);
1292 ArrayOfIndices->SetValue(1,0);
1293 indexmin=Indexmin(ArrayOfCurves);
1294 if (indexmin!=(ArrayOfCurves.Length()-1))
1295 ReorderArrayOfG1(ArrayOfCurves,
1300 for (j=0;j<=nb_curve-1;j++){ //boucle secondaire a l'interieur de chaque groupe
1301 if (NeedToBeTreated(ArrayOfCurves(j))) {
1302 Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1305 Curve1=ArrayOfCurves(j);
1307 if (j==0) //initialisation en debut de groupe
1310 if ( (j==(nb_curve-1)) &&(Need2DegRepara(ArrayOfCurves))){
1311 Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1312 Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1313 lambda=Vec2.Magnitude()/Vec1.Magnitude();
1314 TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1315 Curve1->Knots(KnotC1);
1316 Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1317 ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1318 Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1319 Standard_Real tmax,a,b,c,
1320 umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1321 tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1322 a=(lambda*lambda2-1)/(2*lambda*tmax);
1323 aPolynomialCoefficient[2] = a;
1325 aPolynomialCoefficient[1] = b;
1327 aPolynomialCoefficient[0] = c;
1328 TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1329 TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots());
1330 Curve1->Multiplicities(KnotC1Mults);
1331 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1333 for (ii=2;ii<=KnotC1.Length();ii++) {
1334 // KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1335 KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667
1337 TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles());
1338 Curve1->Poles(Curve1Poles);
1340 for (ii=1;ii<=Curve1->NbKnots();ii++)
1341 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1343 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1345 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1346 TColgp_Array1OfPnt2d NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1347 Standard_Integer Status;
1348 TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1349 Curve1->Weights(Curve1Weights);
1350 for (ii=1;ii<=Curve1->NbPoles();ii++)
1351 for (jj=1;jj<=2;jj++)
1352 Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1354 Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1355 // BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1356 BSplCLib::FunctionReparameterise(ev,
1365 TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1366 // BSplCLib::FunctionReparameterise(reparameterise_evaluator,
1367 BSplCLib::FunctionReparameterise(ev,
1376 for (ii=1;ii<=NewPoles.Length();ii++) {
1377 for (jj=1;jj<=2;jj++)
1378 NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1380 Curve1= new Geom2d_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
1382 Geom2dConvert_CompCurveToBSplineCurve C(Handle(Geom2d_BSplineCurve)::DownCast(Curve2));
1383 fusion=C.Add(Curve1,
1384 local_tolerance(j-1)); //fusion de deux courbes adjacentes
1385 if (fusion==Standard_False)
1386 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1387 Curve2=C.BSplineCurve();
1390 Curve2->SetPeriodic(); //1 seule courbe C1
1391 Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
1392 Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1393 Precision::Confusion());
1394 ArrayOfConcatenated->SetValue(0,Curve2);
1398 for (i=0;i<=nb_group-1;i++){ //boucle principale sur chaque groupe de
1399 nb_vertexG1=0; //continuite interne G1
1401 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1404 if ((!ClosedFlag)||(nb_group==1)){ //remplissage du tableau des indices conserves
1406 ArrayOfIndices->SetValue(k-1,index);
1408 ArrayOfIndices->SetValue(k,0);
1412 ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1);
1414 ArrayOfIndices->SetValue(k,nb_vertex_group0+1);
1417 for (j=index;j<=index+nb_vertexG1;j++){ //boucle secondaire a l'interieur de chaque groupe
1418 if (NeedToBeTreated(ArrayOfCurves(j)))
1419 Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1421 Curve1=ArrayOfCurves(j);
1423 if (index==j) //initialisation en debut de groupe
1424 ArrayOfConcatenated->SetValue(i,Curve1);
1426 Geom2dConvert_CompCurveToBSplineCurve C(Handle(Geom2d_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(i)));
1427 fusion=C.Add(Curve1,ArrayOfToler(j-1)); //fusion de deux courbes adjacentes
1428 if (fusion==Standard_False)
1429 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1430 ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1433 index=index+1+nb_vertexG1;
1437 //=======================================================================
1438 //function : C0BSplineToC1BSplineCurve
1440 //=======================================================================
1442 void Geom2dConvert::C0BSplineToC1BSplineCurve(Handle(Geom2d_BSplineCurve)& BS,
1443 const Standard_Real tolerance)
1446 TColStd_Array1OfInteger BSMults(1,BS->NbKnots());
1447 TColStd_Array1OfReal BSKnots(1,BS->NbKnots());
1448 Standard_Integer i,j,nbcurveC1=1;
1449 Standard_Real U1,U2;
1450 Standard_Boolean closed_flag = Standard_False ;
1453 Standard_Boolean fusion;
1456 BS->Multiplicities(BSMults);
1457 for (i=BS->FirstUKnotIndex() + 1;i<=(BS->LastUKnotIndex()-1);i++){
1458 if (BSMults(i)==BS->Degree())
1462 nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1);
1465 TColGeom2d_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1);
1466 TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2);
1468 for (i=0;i<=nbcurveC1-2;i++)
1469 ArrayOfToler(i)=tolerance;
1470 U2=BS->FirstParameter() ;
1471 j=BS->FirstUKnotIndex() + 1 ;
1472 for (i=0;i<nbcurveC1;i++){
1475 while (j < BS->LastUKnotIndex() && BSMults(j) < BS->Degree())
1480 Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve::DownCast(BS->Copy()));
1481 BSbis->Segment(U1,U2);
1482 ArrayOfCurves(i)=BSbis;
1484 Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1485 Handle(TColGeom2d_HArray1OfBSplineCurve) ArrayOfConcatenated;
1487 BS->D1(BS->FirstParameter(),point,V1); //a verifier
1488 BS->D1(BS->LastParameter(),point,V2);
1490 if ((BS->IsClosed())&&(V1.IsParallel(V2,Precision::Confusion())))
1491 closed_flag = Standard_True ;
1493 Geom2dConvert::ConcatC1(ArrayOfCurves,
1496 ArrayOfConcatenated,
1500 Geom2dConvert_CompCurveToBSplineCurve
1501 C(Handle(Geom2d_BSplineCurve)::DownCast(ArrayOfConcatenated->Value(0)));
1502 if (ArrayOfConcatenated->Length()>=2){
1503 for (i=1;i<ArrayOfConcatenated->Length();i++){
1504 fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance);
1505 if (fusion==Standard_False)
1506 Standard_ConstructionError::Raise("Geom2dConvert Concatenation Error") ;
1509 BS=C.BSplineCurve();
1512 //=======================================================================
1513 //function : C0BSplineToArrayOfC1BSplineCurve
1515 //=======================================================================
1517 void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) & BS,
1518 Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1519 const Standard_Real tolerance)
1521 C0BSplineToArrayOfC1BSplineCurve(BS,
1524 Precision::Angular());
1526 //=======================================================================
1527 //function : C0BSplineToArrayOfC1BSplineCurve
1529 //=======================================================================
1531 void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) & BS,
1532 Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS,
1533 const Standard_Real AngularTolerance,
1534 const Standard_Real Tolerance)
1537 TColStd_Array1OfInteger BSMults(1,BS->NbKnots());
1538 TColStd_Array1OfReal BSKnots(1,BS->NbKnots());
1539 Standard_Integer i,j,nbcurveC1=1;
1540 Standard_Real U1,U2;
1541 Standard_Boolean closed_flag = Standard_False ;
1544 // Standard_Boolean fusion;
1547 BS->Multiplicities(BSMults);
1548 for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){
1549 if (BSMults(i)==BS->Degree())
1553 nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1);
1556 TColGeom2d_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1);
1557 TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2);
1559 for (i=0;i<=nbcurveC1-2;i++)
1560 ArrayOfToler(i)=Tolerance;
1561 U2=BS->FirstParameter() ;
1562 j=BS->FirstUKnotIndex()+ 1 ;
1563 for (i=0;i<nbcurveC1;i++){
1565 while (j < BS->LastUKnotIndex() && BSMults(j)<BS->Degree())
1569 Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve::DownCast(BS->Copy()));
1570 BSbis->Segment(U1,U2);
1571 ArrayOfCurves(i)=BSbis;
1574 Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1576 BS->D1(BS->FirstParameter(),point,V1);
1577 BS->D1(BS->LastParameter(),point,V2);
1579 if ((BS->IsClosed())&&(V1.IsParallel(V2,AngularTolerance)))
1580 closed_flag = Standard_True ;
1582 Geom2dConvert::ConcatC1(ArrayOfCurves,
1591 tabBS = new TColGeom2d_HArray1OfBSplineCurve(0,0);
1592 tabBS->SetValue(0,BS);