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 <BSplCLib.hxx>
20 #include <Convert_CircleToBSplineCurve.hxx>
21 #include <Convert_ConicToBSplineCurve.hxx>
22 #include <Convert_EllipseToBSplineCurve.hxx>
23 #include <Convert_HyperbolaToBSplineCurve.hxx>
24 #include <Convert_ParabolaToBSplineCurve.hxx>
26 #include <Geom2d_BSplineCurve.hxx>
27 #include <Geom_BezierCurve.hxx>
28 #include <Geom_BSplineCurve.hxx>
29 #include <Geom_BSplineSurface.hxx>
30 #include <Geom_Circle.hxx>
31 #include <Geom_Conic.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_Ellipse.hxx>
34 #include <Geom_Geometry.hxx>
35 #include <Geom_Hyperbola.hxx>
36 #include <Geom_Line.hxx>
37 #include <Geom_OffsetCurve.hxx>
38 #include <Geom_Parabola.hxx>
39 #include <Geom_Surface.hxx>
40 #include <Geom_TrimmedCurve.hxx>
41 #include <GeomConvert.hxx>
42 #include <GeomConvert_ApproxCurve.hxx>
43 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
44 #include <GeomLProp.hxx>
47 #include <gp_Circ2d.hxx>
48 #include <gp_Elips2d.hxx>
49 #include <gp_Hypr2d.hxx>
51 #include <gp_Parab2d.hxx>
53 #include <gp_Pnt2d.hxx>
54 #include <gp_Trsf.hxx>
58 #include <Precision.hxx>
59 #include <Standard_ConstructionError.hxx>
60 #include <Standard_DomainError.hxx>
61 #include <TColGeom_Array1OfCurve.hxx>
62 #include <TColgp_Array1OfPnt.hxx>
63 #include <TColgp_Array1OfPnt2d.hxx>
64 #include <TColStd_Array1OfBoolean.hxx>
65 #include <TColStd_Array1OfInteger.hxx>
66 #include <TColStd_Array1OfReal.hxx>
67 #include <TColStd_HArray1OfInteger.hxx>
68 #include <TColStd_HArray1OfReal.hxx>
70 //=======================================================================
71 //function : BSplineCurveBuilder
73 //=======================================================================
74 static Handle(Geom_BSplineCurve) BSplineCurveBuilder
75 (const Handle(Geom_Conic)& TheConic,
76 const Convert_ConicToBSplineCurve& Convert)
79 Handle(Geom_BSplineCurve) TheCurve;
80 Standard_Integer NbPoles = Convert.NbPoles();
81 Standard_Integer NbKnots = Convert.NbKnots();
82 TColgp_Array1OfPnt Poles (1, NbPoles);
83 TColStd_Array1OfReal Weights (1, NbPoles);
84 TColStd_Array1OfReal Knots (1, NbKnots);
85 TColStd_Array1OfInteger Mults (1, NbKnots);
89 for (i = 1; i <= NbPoles; i++) {
90 P2d = Convert.Pole (i);
91 P3d.SetCoord (P2d.X(), P2d.Y(), 0.0);
93 Weights (i) = Convert.Weight (i);
95 for (i = 1; i <= NbKnots; i++) {
96 Knots (i) = Convert.Knot (i);
97 Mults (i) = Convert.Multiplicity (i);
100 new Geom_BSplineCurve (Poles, Weights, Knots, Mults,
101 Convert.Degree(), Convert.IsPeriodic());
103 T.SetTransformation (TheConic->Position(), gp::XOY());
104 Handle(Geom_BSplineCurve) Cres;
105 Cres = Handle(Geom_BSplineCurve)::DownCast(TheCurve->Transformed (T));
111 //=======================================================================
112 //function : SplitBSplineCurve
114 //=======================================================================
116 Handle(Geom_BSplineCurve) GeomConvert::SplitBSplineCurve
117 (const Handle(Geom_BSplineCurve)& C,
118 const Standard_Integer FromK1,
119 const Standard_Integer ToK2,
120 const Standard_Boolean SameOrientation)
122 Standard_Integer TheFirst = C->FirstUKnotIndex ();
123 Standard_Integer TheLast = C->LastUKnotIndex ();
124 if (FromK1 == ToK2) throw Standard_DomainError();
125 Standard_Integer FirstK = Min (FromK1, ToK2);
126 Standard_Integer LastK = Max (FromK1, ToK2);
127 if (FirstK < TheFirst || LastK > TheLast) throw Standard_DomainError();
129 Handle(Geom_BSplineCurve) C1
130 = Handle(Geom_BSplineCurve)::DownCast(C->Copy ());
132 C1->Segment( C->Knot(FirstK),C->Knot(LastK));
134 if (C->IsPeriodic()) {
135 if (!SameOrientation) C1->Reverse();
138 if (FromK1 > ToK2) C1->Reverse();
144 //=======================================================================
145 //function : SplitBSplineCurve
147 //=======================================================================
149 Handle(Geom_BSplineCurve) GeomConvert::SplitBSplineCurve
150 (const Handle(Geom_BSplineCurve)& C,
151 const Standard_Real FromU1,
152 const Standard_Real ToU2,
153 const Standard_Real , //ParametricTolerance,
154 const Standard_Boolean SameOrientation )
156 Standard_Real FirstU = Min( FromU1, ToU2);
157 Standard_Real LastU = Max( FromU1, ToU2);
159 Handle (Geom_BSplineCurve) C1
160 = Handle(Geom_BSplineCurve)::DownCast(C->Copy());
162 C1->Segment(FirstU, LastU);
164 if (C->IsPeriodic()) {
165 if (!SameOrientation) C1->Reverse();
168 if (FromU1 > ToU2) C1->Reverse();
177 //=======================================================================
178 //function : CurveToBSplineCurve
180 //=======================================================================
182 Handle(Geom_BSplineCurve) GeomConvert::CurveToBSplineCurve
183 (const Handle(Geom_Curve)& C,
184 const Convert_ParameterisationType Parameterisation)
186 Handle (Geom_BSplineCurve) TheCurve;
188 if (C->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
189 Handle(Geom_Curve) Curv;
190 Handle(Geom_TrimmedCurve) Ctrim = Handle(Geom_TrimmedCurve)::DownCast(C);
191 Curv = Ctrim->BasisCurve();
192 Standard_Real U1 = Ctrim->FirstParameter();
193 Standard_Real U2 = Ctrim->LastParameter();
195 // Si la courbe n'est pas vraiment restreinte, on ne risque pas
196 // le Raise dans le BS->Segment.
197 if (!Curv->IsPeriodic()) {
198 if (U1 < Curv->FirstParameter())
199 U1 = Curv->FirstParameter();
200 if (U2 > Curv->LastParameter())
201 U2 = Curv->LastParameter();
204 if (Curv->IsKind(STANDARD_TYPE(Geom_Line))) {
205 gp_Pnt Pdeb = Ctrim->StartPoint();
206 gp_Pnt Pfin = Ctrim->EndPoint();
207 TColgp_Array1OfPnt Poles (1, 2);
210 TColStd_Array1OfReal Knots (1, 2);
211 Knots (1) = Ctrim->FirstParameter ();
212 Knots (2) = Ctrim->LastParameter ();
213 TColStd_Array1OfInteger Mults (1, 2);
216 Standard_Integer Degree = 1;
217 TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
220 else if (Curv->IsKind(STANDARD_TYPE(Geom_Circle))) {
221 Handle(Geom_Circle) TheConic = Handle(Geom_Circle)::DownCast(Curv);
222 gp_Circ2d C2d (gp::OX2d(), TheConic->Radius());
223 if(Parameterisation != Convert_RationalC1) {
224 Convert_CircleToBSplineCurve Convert (C2d,
228 TheCurve = BSplineCurveBuilder (TheConic, Convert);
232 Convert_CircleToBSplineCurve Convert (C2d,
236 TheCurve = BSplineCurveBuilder (TheConic, Convert);
238 else { // split circle to avoide numerical
239 // overflow when U2 - U1 =~ 2*PI
241 Standard_Real Umed = (U1 + U2) * .5;
242 Convert_CircleToBSplineCurve Convert1 (C2d,
247 Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
249 Convert_CircleToBSplineCurve Convert2 (C2d,
254 Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
256 GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
259 CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
262 TheCurve = CCTBSpl.BSplineCurve();
268 else if (Curv->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
269 Handle(Geom_Ellipse) TheConic = Handle(Geom_Ellipse)::DownCast(Curv);
270 gp_Elips2d E2d (gp::OX2d(),
271 TheConic->MajorRadius(),
272 TheConic->MinorRadius());
273 if(Parameterisation != Convert_RationalC1) {
274 Convert_EllipseToBSplineCurve Convert (E2d,
278 TheCurve = BSplineCurveBuilder (TheConic, Convert);
282 Convert_EllipseToBSplineCurve Convert (E2d,
286 TheCurve = BSplineCurveBuilder (TheConic, Convert);
288 else { // split ellipse to avoide numerical
289 // overflow when U2 - U1 =~ 2*PI
291 Standard_Real Umed = (U1 + U2) * .5;
292 Convert_EllipseToBSplineCurve Convert1 (E2d,
297 Handle (Geom_BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1);
299 Convert_EllipseToBSplineCurve Convert2 (E2d,
304 Handle (Geom_BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2);
306 GeomConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1,
309 CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True);
312 TheCurve = CCTBSpl.BSplineCurve();
317 else if (Curv->IsKind(STANDARD_TYPE(Geom_Hyperbola))) {
318 Handle(Geom_Hyperbola) TheConic = Handle(Geom_Hyperbola)::DownCast(Curv);
319 gp_Hypr2d H2d (gp::OX2d(),
320 TheConic->MajorRadius(), TheConic->MinorRadius());
321 Convert_HyperbolaToBSplineCurve Convert (H2d, U1, U2);
322 TheCurve = BSplineCurveBuilder (TheConic, Convert);
325 else if (Curv->IsKind(STANDARD_TYPE(Geom_Parabola))) {
326 Handle(Geom_Parabola) TheConic = Handle(Geom_Parabola)::DownCast(Curv);
327 gp_Parab2d Prb2d (gp::OX2d(), TheConic->Focal());
328 Convert_ParabolaToBSplineCurve Convert (Prb2d, U1, U2);
329 TheCurve = BSplineCurveBuilder (TheConic, Convert);
332 else if (Curv->IsKind (STANDARD_TYPE(Geom_BezierCurve))) {
334 Handle(Geom_BezierCurve) CBez
335 = Handle(Geom_BezierCurve)::DownCast(Curv->Copy());
336 CBez->Segment (U1, U2);
337 Standard_Integer NbPoles = CBez->NbPoles();
338 Standard_Integer Degree = CBez->Degree();
339 TColgp_Array1OfPnt Poles (1, NbPoles);
340 TColStd_Array1OfReal Knots (1, 2);
341 TColStd_Array1OfInteger Mults (1, 2);
344 Mults (1) = Degree + 1;
345 Mults (2) = Degree + 1;
347 if (CBez->IsRational()) {
348 TColStd_Array1OfReal Weights (1, NbPoles);
349 CBez->Weights (Weights);
351 new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree);
355 new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
358 else if (Curv->IsKind (STANDARD_TYPE(Geom_BSplineCurve))) {
359 TheCurve = Handle(Geom_BSplineCurve)::DownCast(Curv->Copy());
360 //// modified by jgv, 14.01.05 for OCC7355 ////
361 if (TheCurve->IsPeriodic())
363 Standard_Real Uf = TheCurve->FirstParameter();
364 Standard_Real Ul = TheCurve->LastParameter();
365 ElCLib::AdjustPeriodic( Uf, Ul, Precision::Confusion(), U1, U2 );
366 if (Abs(U1 - Uf) <= Precision::Confusion() &&
367 Abs(U2 - Ul) <= Precision::Confusion())
368 TheCurve->SetNotPeriodic();
370 ///////////////////////////////////////////////
371 TheCurve->Segment(U1,U2);
373 else if (Curv->IsKind (STANDARD_TYPE(Geom_OffsetCurve))) {
374 Standard_Real Tol3d = 1.e-4;
375 GeomAbs_Shape Order = GeomAbs_C2;
376 Standard_Integer MaxSegments = 16, MaxDegree = 14;
377 GeomConvert_ApproxCurve ApprCOffs(C, Tol3d, Order,
378 MaxSegments, MaxDegree);
379 if (ApprCOffs.HasResult())
380 TheCurve = ApprCOffs.Curve();
381 else throw Standard_ConstructionError();
383 else { throw Standard_DomainError("No such curve"); }
387 if (C->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
388 Handle(Geom_Ellipse) TheConic= Handle(Geom_Ellipse)::DownCast(C);
389 gp_Elips2d E2d (gp::OX2d(),
390 TheConic->MajorRadius(), TheConic->MinorRadius());
391 /* if (Parameterisation == Convert_TgtThetaOver2_1 ||
392 Parameterisation == Convert_TgtThetaOver2_2) {
393 throw Standard_DomainError(); }
395 else if ( Parameterisation == Convert_QuasiAngular) {
396 Convert_EllipseToBSplineCurve Convert (E2d,
401 TheCurve = BSplineCurveBuilder (TheConic, Convert);
402 TheCurve->SetPeriodic();
405 Convert_EllipseToBSplineCurve Convert (E2d,
407 TheCurve = BSplineCurveBuilder (TheConic, Convert);
408 TheCurve->SetPeriodic(); // pour polynomial et quasi angular
412 else if (C->IsKind(STANDARD_TYPE(Geom_Circle))) {
413 Handle(Geom_Circle) TheConic = Handle(Geom_Circle)::DownCast(C);
414 gp_Circ2d C2d (gp::OX2d(), TheConic->Radius());
415 /* if (Parameterisation == Convert_TgtThetaOver2_1 ||
416 Parameterisation == Convert_TgtThetaOver2_2) {
417 throw Standard_DomainError(); }
419 else if ( Parameterisation == Convert_QuasiAngular) {
420 Convert_CircleToBSplineCurve Convert (C2d,
425 TheCurve = BSplineCurveBuilder (TheConic, Convert);
428 Convert_CircleToBSplineCurve Convert (C2d,
430 TheCurve = BSplineCurveBuilder (TheConic, Convert);
431 TheCurve->SetPeriodic();
435 else if (C->IsKind (STANDARD_TYPE(Geom_BezierCurve))) {
436 Handle(Geom_BezierCurve) CBez= Handle(Geom_BezierCurve)::DownCast(C);
437 Standard_Integer NbPoles = CBez->NbPoles();
438 Standard_Integer Degree = CBez->Degree();
439 TColgp_Array1OfPnt Poles (1, NbPoles);
440 TColStd_Array1OfReal Knots (1, 2);
441 TColStd_Array1OfInteger Mults (1, 2);
444 Mults (1) = Degree + 1;
445 Mults (2) = Degree + 1;
447 if (CBez->IsRational()) {
448 TColStd_Array1OfReal Weights (1, NbPoles);
449 CBez->Weights (Weights);
451 new Geom_BSplineCurve (Poles, Weights, Knots, Mults, Degree);
454 TheCurve = new Geom_BSplineCurve (Poles, Knots, Mults, Degree);
458 else if (C->IsKind (STANDARD_TYPE(Geom_BSplineCurve))) {
459 TheCurve = Handle(Geom_BSplineCurve)::DownCast(C->Copy());
462 else if (C->IsKind (STANDARD_TYPE(Geom_OffsetCurve))) {
463 Standard_Real Tol3d = 1.e-4;
464 GeomAbs_Shape Order = GeomAbs_C2;
465 Standard_Integer MaxSegments = 16, MaxDegree = 14;
466 GeomConvert_ApproxCurve ApprCOffs(C, Tol3d, Order,
467 MaxSegments, MaxDegree);
468 if (ApprCOffs.HasResult())
469 TheCurve = ApprCOffs.Curve();
470 else throw Standard_ConstructionError();
472 else { throw Standard_DomainError("No such curve"); }
479 //=======================================================================
480 //class : law_evaluator
481 //purpose : usefull to estimate the value of a function
482 //=======================================================================
484 class GeomConvert_law_evaluator : public BSplCLib_EvaluatorFunction
489 GeomConvert_law_evaluator (const Handle(Geom2d_BSplineCurve)& theAncore)
490 : myAncore (theAncore) {}
492 virtual void Evaluate (const Standard_Integer theDerivativeRequest,
493 const Standard_Real* theStartEnd,
494 const Standard_Real theParameter,
495 Standard_Real& theResult,
496 Standard_Integer& theErrorCode) const
499 if (!myAncore.IsNull() &&
500 theParameter >= theStartEnd[0] &&
501 theParameter <= theStartEnd[1] &&
502 theDerivativeRequest == 0)
505 myAncore->D0 (theParameter, aPoint);
506 theResult = aPoint.Coord(2);
514 Handle(Geom2d_BSplineCurve) myAncore;
518 //=======================================================================
519 //function : MultNumandDenom
520 //purpose : Multiply two BSpline curves to make one
521 //=======================================================================
524 static Handle(Geom_BSplineCurve) MultNumandDenom(const Handle(Geom2d_BSplineCurve)& a ,
525 const Handle(Geom_BSplineCurve)& BS )
527 { TColStd_Array1OfReal aKnots(1,a->NbKnots());
528 TColStd_Array1OfReal BSKnots(1,BS->NbKnots());
529 TColStd_Array1OfReal BSFlatKnots(1,BS->NbPoles()+BS->Degree()+1);
530 TColStd_Array1OfReal BSWeights(1,BS->NbPoles());
531 TColStd_Array1OfInteger aMults(1,a->NbKnots());
532 TColStd_Array1OfInteger BSMults(1,BS->NbKnots());
533 TColgp_Array1OfPnt2d aPoles(1,a->NbPoles());
534 TColgp_Array1OfPnt BSPoles(1,BS->NbPoles());
535 Handle(Geom_BSplineCurve) res;
536 Handle(TColStd_HArray1OfReal) resKnots;
537 Handle(TColStd_HArray1OfInteger) resMults;
538 Standard_Real start_value,end_value;
539 Standard_Real tolerance=Precision::PConfusion();
540 Standard_Integer resNbPoles,degree,
544 BS->Knots(BSKnots); //storage of the two BSpline
545 BS->Multiplicities(BSMults); //features
547 BS->Weights(BSWeights);
548 BS->KnotSequence(BSFlatKnots);
549 start_value = BSKnots(1);
550 end_value = BSKnots(BS->NbKnots());
551 if ((end_value - start_value)/5 < tolerance)
552 tolerance = (end_value - start_value)/5;
556 a->Multiplicities(aMults);
557 BSplCLib::Reparametrize(BS->FirstParameter(),BS->LastParameter(),aKnots);
558 Handle(Geom2d_BSplineCurve) anAncore = new Geom2d_BSplineCurve (aPoles, aKnots, aMults, a->Degree());
560 BSplCLib::MergeBSplineKnots(tolerance,start_value,end_value, //merge of the knots
561 a->Degree(),aKnots,aMults,
562 BS->Degree(),BSKnots,BSMults,
563 resNbPoles,resKnots,resMults);
564 degree=BS->Degree()+a->Degree();
565 TColgp_Array1OfPnt resNumPoles(1,resNbPoles);
566 TColStd_Array1OfReal resDenPoles(1,resNbPoles);
567 TColgp_Array1OfPnt resPoles(1,resNbPoles);
568 TColStd_Array1OfReal resFlatKnots(1,resNbPoles+degree+1);
569 BSplCLib::KnotSequence(resKnots->Array1(),resMults->Array1(),resFlatKnots);
570 for (ii=1;ii<=BS->NbPoles();ii++)
571 for (jj=1;jj<=3;jj++)
572 BSPoles(ii).SetCoord(jj,BSPoles(ii).Coord(jj)*BSWeights(ii));
574 GeomConvert_law_evaluator ev (anAncore);
576 BSplCLib::FunctionMultiply(ev,
585 BSplCLib::FunctionMultiply(ev,
593 for (ii=1;ii<=resNbPoles;ii++)
595 resPoles(ii).SetCoord(jj,resNumPoles(ii).Coord(jj)/resDenPoles(ii));
596 res = new Geom_BSplineCurve(resPoles,resDenPoles,resKnots->Array1(),resMults->Array1(),degree);
600 //=======================================================================
601 //function : Pretreatment
602 //purpose : Put the two first and two last weigths at one if they are
604 //=======================================================================
606 static void Pretreatment(TColGeom_Array1OfBSplineCurve& tab)
608 {Standard_Integer i,j;
611 for (i=0;i<=(tab.Length()-1);i++){
612 if (tab(i)->IsRational()) {
614 if ((tab(i)->Weight(2)==a)&&
615 (tab(i)->Weight(tab(i)->NbPoles()-1)==a)&&
616 (tab(i)->Weight(tab(i)->NbPoles())==a))
618 for (j=1;j<=tab(i)->NbPoles();j++)
619 tab(i)->SetWeight(j,tab(i)->Weight(j)/a);
624 //=======================================================================
625 //function : NeedToBeTreated
626 //purpose : Say if the BSpline is rationnal and if the two first and two
627 // last weigths are different
628 //=======================================================================
630 static Standard_Boolean NeedToBeTreated(const Handle(Geom_BSplineCurve)& BS)
633 TColStd_Array1OfReal tabWeights(1,BS->NbPoles());
634 if (BS->IsRational()) {
635 BS->Weights(tabWeights);
636 if ((BSplCLib::IsRational(tabWeights,1,BS->NbPoles()))&&
637 ((BS->Weight(1)<(1-Precision::Confusion()))||
638 (BS->Weight(1)>(1+Precision::Confusion()))||
639 (BS->Weight(2)<(1-Precision::Confusion()))||
640 (BS->Weight(2)>(1+Precision::Confusion()))||
641 (BS->Weight(BS->NbPoles()-1)<(1-Precision::Confusion()))||
642 (BS->Weight(BS->NbPoles()-1)>(1+Precision::Confusion()))||
643 (BS->Weight(BS->NbPoles())<(1-Precision::Confusion()))||
644 (BS->Weight(BS->NbPoles())>(1+Precision::Confusion()))))
645 return Standard_True;
647 return Standard_False;
650 return Standard_False ;
654 //=======================================================================
655 //function : Need2DegRepara
656 //purpose : in the case of wire closed G1 it says if you will to use a
657 // two degree reparametrisation to close it C1
658 //=======================================================================
660 static Standard_Boolean Need2DegRepara(const TColGeom_Array1OfBSplineCurve& tab)
665 Standard_Real Rapport=1.0e0;
667 for (i=0;i<=tab.Length()-2;i++){
668 tab(i+1)->D1(tab(i+1)->FirstParameter(),Pint,Vec1);
669 tab(i)->D1(tab(i)->LastParameter(),Pint,Vec2);
670 Rapport=Rapport*Vec2.Magnitude()/Vec1.Magnitude();
672 if ((Rapport<=(1.0e0+Precision::Confusion()))&&(Rapport>=(1.0e0-Precision::Confusion())))
673 return Standard_False;
675 return Standard_True;
678 //=======================================================================
679 //function : Indexmin
680 //purpose : Give the index of the curve which has the lowest degree
681 //=======================================================================
683 static Standard_Integer Indexmin(const TColGeom_Array1OfBSplineCurve& tab)
685 Standard_Integer i = 0, index = 0, degree = 0;
687 degree=tab(0)->Degree();
688 for (i=0;i<=tab.Length()-1;i++)
689 if (tab(i)->Degree()<=degree){
690 degree=tab(i)->Degree();
696 //=======================================================================
697 //function : NewTabClosedG1
698 //purpose : Sort the array of BSplines to start at the nb_vertex_group0 index
699 //=======================================================================
701 static void ReorderArrayOfG1Curves(TColGeom_Array1OfBSplineCurve& ArrayOfCurves,
702 TColStd_Array1OfReal& ArrayOfToler,
703 TColStd_Array1OfBoolean& tabG1,
704 const Standard_Integer StartIndex,
705 const Standard_Real ClosedTolerance)
708 TColGeom_Array1OfBSplineCurve ArraybisOfCurves(0,ArrayOfCurves.Length()-1); //temporary
709 TColStd_Array1OfReal ArraybisOfToler(0,ArrayOfToler.Length()-1); //arrays
710 TColStd_Array1OfBoolean tabbisG1(0,tabG1.Length()-1);
712 for (i=0;i<=ArrayOfCurves.Length()-1;i++){
713 if (i!=ArrayOfCurves.Length()-1){
714 ArraybisOfCurves(i)=ArrayOfCurves(i);
715 ArraybisOfToler(i)=ArrayOfToler(i);
716 tabbisG1(i)=tabG1(i);
719 ArraybisOfCurves(i)=ArrayOfCurves(i);
722 for (i=0;i<=(ArrayOfCurves.Length()-(StartIndex+2));i++){
723 ArrayOfCurves(i)=ArraybisOfCurves(i+StartIndex+1);
724 if (i!=(ArrayOfCurves.Length()-(StartIndex+2))){
725 ArrayOfToler(i)=ArraybisOfToler(i+StartIndex+1);
726 tabG1(i)=tabbisG1(i+StartIndex+1);
730 ArrayOfToler(ArrayOfCurves.Length()-(StartIndex+2))=ClosedTolerance;
731 tabG1(ArrayOfCurves.Length()-(StartIndex+2))=Standard_True;
733 for (i=(ArrayOfCurves.Length()-(StartIndex+1));i<=(ArrayOfCurves.Length()-1);i++){
734 if (i!=ArrayOfCurves.Length()-1){
735 ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
736 ArrayOfToler(i)=ArraybisOfToler(i-(ArrayOfCurves.Length()-(StartIndex+1)));
737 tabG1(i)=tabbisG1(i-(ArrayOfCurves.Length()-(StartIndex+1)));
740 ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1)));
744 //=======================================================================
745 //class : reparameterise_evaluator
747 //=======================================================================
749 class GeomConvert_reparameterise_evaluator : public BSplCLib_EvaluatorFunction
754 GeomConvert_reparameterise_evaluator (const Standard_Real thePolynomialCoefficient[3])
756 memcpy (myPolynomialCoefficient, thePolynomialCoefficient, sizeof(myPolynomialCoefficient));
759 virtual void Evaluate (const Standard_Integer theDerivativeRequest,
760 const Standard_Real* /*theStartEnd*/,
761 const Standard_Real theParameter,
762 Standard_Real& theResult,
763 Standard_Integer& theErrorCode) const
766 PLib::EvalPolynomial (theParameter,
767 theDerivativeRequest,
770 *((Standard_Real* )myPolynomialCoefficient), // function really only read values from this array
776 Standard_Real myPolynomialCoefficient[3];
780 //=======================================================================
781 //function : ConcatG1
783 //=======================================================================
785 void GeomConvert::ConcatG1(TColGeom_Array1OfBSplineCurve& ArrayOfCurves,
786 const TColStd_Array1OfReal& ArrayOfToler,
787 Handle(TColGeom_HArray1OfBSplineCurve) & ArrayOfConcatenated,
788 Standard_Boolean& ClosedG1Flag,
789 const Standard_Real ClosedTolerance)
791 {Standard_Integer nb_curve=ArrayOfCurves.Length(),
797 Standard_Real lambda, //G1 coefficient
799 Standard_Real PreLast = 0.;
801 gp_Vec Vec1,Vec2; //concecutive tangential vectors
803 Handle(Geom_BSplineCurve) Curve1,Curve2;
804 TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //array of the G1 continuity at the intersections
805 TColStd_Array1OfReal local_tolerance(0,
806 ArrayOfToler.Length()-1) ;
808 for (i=0 ; i < ArrayOfToler.Length() ; i++) {
809 local_tolerance(i) = ArrayOfToler(i) ;
811 for (i=0 ;i<nb_curve; i++){
813 First=ArrayOfCurves(i)->FirstParameter();
814 Cont = GeomLProp::Continuity(ArrayOfCurves(i-1),
817 Standard_True,Standard_True);
819 throw Standard_ConstructionError("GeomConvert curves not C0") ;
821 if (Cont>=GeomAbs_G1)
822 tabG1(i-1)=Standard_True; //True=G1 continuity
824 tabG1(i-1)=Standard_False;
827 PreLast=ArrayOfCurves(i)->LastParameter();
831 while (index<=nb_curve-1){ //determination of the Wire features
833 while(((index+nb_vertexG1)<=nb_curve-2)&&
834 (tabG1(index+nb_vertexG1)==Standard_True))
838 nb_vertex_group0=nb_vertexG1;
839 index=index+1+nb_vertexG1;
842 if ((ClosedG1Flag)&&(nb_group!=1)){ //sort of the array
844 ReorderArrayOfG1Curves(ArrayOfCurves,
851 ArrayOfConcatenated = new TColGeom_HArray1OfBSplineCurve(0,nb_group-1);
852 Standard_Boolean fusion;
855 Pretreatment(ArrayOfCurves);
856 Standard_Real aPolynomialCoefficient[3];
858 Standard_Boolean NeedDoubleDegRepara = Need2DegRepara(ArrayOfCurves);
859 if (nb_group==1 && ClosedG1Flag && NeedDoubleDegRepara)
861 Curve1 = ArrayOfCurves(nb_curve-1);
862 if (Curve1->Degree() > Geom2d_BSplineCurve::MaxDegree()/2)
863 ClosedG1Flag = Standard_False;
866 if ((nb_group==1) && (ClosedG1Flag)){ //treatment of a particular case
867 indexmin=Indexmin(ArrayOfCurves);
868 if (indexmin!=(ArrayOfCurves.Length()-1))
869 ReorderArrayOfG1Curves(ArrayOfCurves,
874 Curve2=ArrayOfCurves(0);
875 for (j=1;j<=nb_curve-1;j++){ //secondary loop inside each group
876 Curve1=ArrayOfCurves(j);
877 if ( (j==(nb_curve-1)) && (NeedDoubleDegRepara)){
878 Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
879 Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
880 lambda=Vec2.Magnitude()/Vec1.Magnitude();
881 TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
882 Curve1->Knots(KnotC1);
883 Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
884 ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
885 Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
886 Standard_Real tmax,a,b,c,
887 umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
888 tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
889 a=(lambda*lambda2-1)/(2*lambda*tmax);
890 aPolynomialCoefficient[2] = a;
892 aPolynomialCoefficient[1] = b;
894 aPolynomialCoefficient[0] = c;
895 TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
896 TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots());
897 Curve1->Multiplicities(KnotC1Mults);
898 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
900 for (ii=2;ii<=KnotC1.Length();ii++) {
901 // KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
902 KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); // ifv 17.05.00 buc60667
904 TColgp_Array1OfPnt Curve1Poles(1,Curve1->NbPoles());
905 Curve1->Poles(Curve1Poles);
907 for (ii=1;ii<=Curve1->NbKnots();ii++)
908 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
910 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
912 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
913 TColgp_Array1OfPnt NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
914 Standard_Integer aStatus;
915 TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
916 Curve1->Weights(Curve1Weights);
917 for (ii=1;ii<=Curve1->NbPoles();ii++)
918 for (jj=1;jj<=3;jj++)
919 Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
921 GeomConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
922 // BSplCLib::FunctionReparameterise(reparameterise_evaluator,
923 BSplCLib::FunctionReparameterise(ev,
932 TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
933 // BSplCLib::FunctionReparameterise(reparameterise_evaluator,
934 BSplCLib::FunctionReparameterise(ev,
943 for (ii=1;ii<=NewPoles.Length();ii++)
944 for (jj=1;jj<=3;jj++)
945 NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
946 Curve1= new Geom_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
948 GeomConvert_CompCurveToBSplineCurve C (Curve2);
950 local_tolerance(j-1)); //merge of two consecutive curves
951 if (fusion==Standard_False)
952 throw Standard_ConstructionError("GeomConvert Concatenation Error") ;
953 Curve2=C.BSplineCurve();
955 Curve2->SetPeriodic();
956 Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
957 Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
958 Precision::Confusion());
959 ArrayOfConcatenated->SetValue(0,Curve2);
963 for (i=0;i<=nb_group-1;i++){ //principal loop on each G1 continuity
964 nb_vertexG1=0; //group
966 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
969 for (j=index;j<=index+nb_vertexG1;j++){ //secondary loop inside each group
970 Curve1=ArrayOfCurves(j);
972 if (index==j) //initialisation at the begining of the loop
973 ArrayOfConcatenated->SetValue(i,Curve1);
975 GeomConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(i));
976 fusion=C.Add(Curve1,ArrayOfToler(j-1)); //merge of two consecutive curves
977 if (fusion==Standard_False)
978 throw Standard_ConstructionError("GeomConvert Concatenation Error") ;
979 ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
982 index=index+1+nb_vertexG1;
985 //=======================================================================
986 //function : ConcatC1
988 //=======================================================================
990 void GeomConvert::ConcatC1(TColGeom_Array1OfBSplineCurve& ArrayOfCurves,
991 const TColStd_Array1OfReal& ArrayOfToler,
992 Handle(TColStd_HArray1OfInteger)& ArrayOfIndices,
993 Handle(TColGeom_HArray1OfBSplineCurve)& ArrayOfConcatenated,
994 Standard_Boolean& ClosedG1Flag,
995 const Standard_Real ClosedTolerance)
997 ConcatC1(ArrayOfCurves,
1000 ArrayOfConcatenated,
1003 Precision::Angular()) ;
1005 //=======================================================================
1006 //function : ConcatC1
1008 //=======================================================================
1010 void GeomConvert::ConcatC1(TColGeom_Array1OfBSplineCurve& ArrayOfCurves,
1011 const TColStd_Array1OfReal& ArrayOfToler,
1012 Handle(TColStd_HArray1OfInteger)& ArrayOfIndices,
1013 Handle(TColGeom_HArray1OfBSplineCurve)& ArrayOfConcatenated,
1014 Standard_Boolean& ClosedG1Flag,
1015 const Standard_Real ClosedTolerance,
1016 const Standard_Real AngularTolerance)
1018 {Standard_Integer nb_curve=ArrayOfCurves.Length(),
1024 Standard_Real lambda, //G1 coefficient
1026 Standard_Real PreLast = 0.;
1029 gp_Vec Vec1,Vec2; //concecutive tangential vectors
1031 Handle(Geom_BSplineCurve) Curve1,Curve2;
1032 TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //array of the G1 continuity at the intersections
1033 TColStd_Array1OfReal local_tolerance(0,
1034 ArrayOfToler.Length()-1) ;
1036 for (i=0 ; i < ArrayOfToler.Length() ; i++) {
1037 local_tolerance(i) = ArrayOfToler(i) ;
1039 for (i=0 ;i<nb_curve; i++){
1041 First=ArrayOfCurves(i)->FirstParameter();
1042 Cont = GeomLProp::Continuity(ArrayOfCurves(i-1),
1048 local_tolerance(i-1),
1050 if (Cont<GeomAbs_C0)
1051 throw Standard_ConstructionError("GeomConvert curves not C0");
1053 if (Cont>=GeomAbs_G1)
1054 tabG1(i-1)=Standard_True; //True=G1 continuity
1056 tabG1(i-1)=Standard_False;
1059 PreLast=ArrayOfCurves(i)->LastParameter();
1063 while (index<=nb_curve-1){ //determination of the Wire features
1065 while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1069 nb_vertex_group0=nb_vertexG1;
1070 index=index+1+nb_vertexG1;
1073 if ((ClosedG1Flag)&&(nb_group!=1)){ //sort of the array
1075 ReorderArrayOfG1Curves(ArrayOfCurves,
1083 new TColStd_HArray1OfInteger(0,nb_group);
1084 ArrayOfConcatenated =
1085 new TColGeom_HArray1OfBSplineCurve(0,nb_group-1);
1087 Standard_Boolean fusion;
1088 Standard_Integer k=0;
1090 Pretreatment(ArrayOfCurves);
1091 Standard_Real aPolynomialCoefficient[3];
1093 Standard_Boolean NeedDoubleDegRepara = Need2DegRepara(ArrayOfCurves);
1094 if (nb_group==1 && ClosedG1Flag && NeedDoubleDegRepara)
1096 Curve1 = ArrayOfCurves(nb_curve-1);
1097 if (Curve1->Degree() > Geom2d_BSplineCurve::MaxDegree()/2)
1098 ClosedG1Flag = Standard_False;
1101 if ((nb_group==1) && (ClosedG1Flag)){ //treatment of a particular case
1102 ArrayOfIndices->SetValue(0,0);
1103 ArrayOfIndices->SetValue(1,0);
1104 indexmin=Indexmin(ArrayOfCurves);
1105 if (indexmin!=(ArrayOfCurves.Length()-1))
1106 ReorderArrayOfG1Curves(ArrayOfCurves,
1111 for (j=0;j<=nb_curve-1;j++){ //secondary loop inside each group
1112 if (NeedToBeTreated(ArrayOfCurves(j)))
1113 Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1115 Curve1=ArrayOfCurves(j);
1117 if (j==0) //initialisation at the begining of the loop
1120 if ( (j==(nb_curve-1)) && (NeedDoubleDegRepara)){
1121 Curve2->D1(Curve2->LastParameter(),Pint,Vec1);
1122 Curve1->D1(Curve1->FirstParameter(),Pint,Vec2);
1123 lambda=Vec2.Magnitude()/Vec1.Magnitude();
1124 TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots());
1125 Curve1->Knots(KnotC1);
1126 Curve1->D1(Curve1->LastParameter(),Pint,Vec2);
1127 ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1);
1128 Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude();
1129 Standard_Real tmax,a,b,c,
1130 umin=Curve1->FirstParameter(),umax=Curve1->LastParameter();
1131 tmax=2*lambda*(umax-umin)/(1+lambda*lambda2);
1132 a=(lambda*lambda2-1)/(2*lambda*tmax);
1133 aPolynomialCoefficient[2] = a;
1135 aPolynomialCoefficient[1] = b;
1137 aPolynomialCoefficient[0] = c;
1138 TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1);
1139 TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots());
1140 Curve1->Multiplicities(KnotC1Mults);
1141 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots);
1143 for (ii=2;ii<=KnotC1.Length();ii++) {
1144 // KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a);
1145 KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); // ifv 17.05.00 buc60667
1147 TColgp_Array1OfPnt Curve1Poles(1,Curve1->NbPoles());
1148 Curve1->Poles(Curve1Poles);
1150 for (ii=1;ii<=Curve1->NbKnots();ii++)
1151 KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii));
1153 TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots()));
1155 BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots);
1156 TColgp_Array1OfPnt NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1157 Standard_Integer aStatus;
1158 TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles());
1159 Curve1->Weights(Curve1Weights);
1160 for (ii=1;ii<=Curve1->NbPoles();ii++)
1161 for (jj=1;jj<=3;jj++)
1162 Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii));
1164 GeomConvert_reparameterise_evaluator ev (aPolynomialCoefficient);
1166 BSplCLib::FunctionReparameterise(ev,
1175 TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1));
1177 BSplCLib::FunctionReparameterise(ev,
1186 for (ii=1;ii<=NewPoles.Length();ii++)
1187 for (jj=1;jj<=3;jj++)
1188 NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii));
1189 Curve1= new Geom_BSplineCurve(NewPoles,NewWeights,KnotC1,KnotC1Mults,2*Curve1->Degree());
1191 GeomConvert_CompCurveToBSplineCurve C (Curve2);
1192 fusion=C.Add(Curve1,
1193 local_tolerance(j-1)); //merge of two consecutive curves
1194 if (fusion==Standard_False)
1195 throw Standard_ConstructionError("GeomConvert Concatenation Error") ;
1196 Curve2=C.BSplineCurve();
1199 Curve2->SetPeriodic(); //only one C1 curve
1200 Curve2->RemoveKnot(Curve2->LastUKnotIndex(),
1201 Curve2->Multiplicity(Curve2->LastUKnotIndex())-1,
1202 Precision::Confusion());
1203 ArrayOfConcatenated->SetValue(0,Curve2);
1207 for (i=0;i<=nb_group-1;i++){ //principal loop on each G1 continuity
1208 nb_vertexG1=0; //group
1210 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True))
1213 if ((!ClosedG1Flag)||(nb_group==1)){ //filling of the array of index which are kept
1215 ArrayOfIndices->SetValue(k-1,index);
1217 ArrayOfIndices->SetValue(k,0);
1221 ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1);
1223 ArrayOfIndices->SetValue(k,nb_vertex_group0+1);
1226 for (j=index;j<=index+nb_vertexG1;j++){ //secondary loop inside each group
1227 if (NeedToBeTreated(ArrayOfCurves(j)))
1228 Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j));
1230 Curve1=ArrayOfCurves(j);
1232 if (index==j) //initialisation at the begining of the loop
1233 ArrayOfConcatenated->SetValue(i,Curve1);
1236 // Merge of two consecutive curves.
1237 GeomConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(i));
1238 fusion=C.Add(Curve1, local_tolerance(j-1), Standard_True);
1239 if (fusion==Standard_False)
1240 throw Standard_ConstructionError("GeomConvert Concatenation Error");
1241 ArrayOfConcatenated->SetValue(i,C.BSplineCurve());
1244 index=index+1+nb_vertexG1;
1248 //=======================================================================
1249 //function : C0BSplineToC1BSplineCurve
1251 //=======================================================================
1253 void GeomConvert::C0BSplineToC1BSplineCurve(Handle(Geom_BSplineCurve)& BS,
1254 const Standard_Real tolerance,
1255 const Standard_Real AngularTol)
1258 Standard_Boolean fusion;
1259 Handle(TColGeom_HArray1OfBSplineCurve) ArrayOfConcatenated;
1260 //the array with the resulting curves
1262 GeomConvert::C0BSplineToArrayOfC1BSplineCurve(BS, ArrayOfConcatenated,
1263 AngularTol, tolerance);
1265 GeomConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(0));
1266 if (ArrayOfConcatenated->Length()>=2){
1268 for (i=1;i<ArrayOfConcatenated->Length();i++){
1269 fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance);
1270 if (fusion==Standard_False)
1271 throw Standard_ConstructionError("GeomConvert Concatenation Error") ;
1274 BS=C.BSplineCurve();
1277 //=======================================================================
1278 //function : C0BSplineToArrayOfC1BSplineCurve
1280 //=======================================================================
1282 void GeomConvert::C0BSplineToArrayOfC1BSplineCurve(
1283 const Handle(Geom_BSplineCurve) & BS,
1284 Handle(TColGeom_HArray1OfBSplineCurve) & tabBS,
1285 const Standard_Real tolerance)
1287 C0BSplineToArrayOfC1BSplineCurve(BS,
1289 Precision::Angular(),
1293 //=======================================================================
1294 //function : C0BSplineToArrayOfC1BSplineCurve
1296 //=======================================================================
1298 void GeomConvert::C0BSplineToArrayOfC1BSplineCurve(
1299 const Handle(Geom_BSplineCurve) & BS,
1300 Handle(TColGeom_HArray1OfBSplineCurve) & tabBS,
1301 const Standard_Real AngularTolerance,
1302 const Standard_Real tolerance)
1304 {TColStd_Array1OfInteger BSMults(1,BS->NbKnots());
1305 TColStd_Array1OfReal BSKnots(1,BS->NbKnots());
1306 Standard_Integer i,j,nbcurveC1=1;
1307 Standard_Real U1,U2;
1308 Standard_Boolean closed_flag= Standard_False ;
1311 // Standard_Boolean fusion;
1314 BS->Multiplicities(BSMults);
1315 for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){ //give the number of C1 curves
1316 if (BSMults(i)==BS->Degree())
1321 TColGeom_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1);
1322 TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2);
1324 for (i=0;i<=nbcurveC1-2;i++)
1325 //filling of the array of tolerances
1326 ArrayOfToler(i)=tolerance;
1327 //with the variable tolerance
1328 U2=BS->FirstParameter() ;
1329 j=BS->FirstUKnotIndex() + 1;
1330 for (i=0;i<nbcurveC1;i++){
1331 //filling of the array of curves
1333 //with the curves C1 segmented
1334 while (BSMults(j)<BS->Degree() && j < BS->LastUKnotIndex())
1338 Handle(Geom_BSplineCurve)
1339 BSbis=Handle(Geom_BSplineCurve)::DownCast(BS->Copy());
1340 BSbis->Segment(U1,U2);
1341 ArrayOfCurves(i)=BSbis;
1344 Handle(TColStd_HArray1OfInteger) ArrayOfIndices;
1346 BS->D1(BS->FirstParameter(),point,V1);
1347 BS->D1(BS->LastParameter(),point,V2);
1349 if ((BS->IsClosed())&&(V1.IsParallel(V2,AngularTolerance))){
1350 //check if the BSpline is closed G1
1351 closed_flag = Standard_True ;
1354 GeomConvert::ConcatC1(ArrayOfCurves,
1363 tabBS = new TColGeom_HArray1OfBSplineCurve(0,0);
1364 tabBS->SetValue(0,BS);