// Copyright (c) 1995-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. //Jean-Claude Vauthier Novembre 1991 //Passage sur C1 Aout 1992 et ajout transformation Bezier->BSpline #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef gp_Circ2d Circ2d; typedef gp_Elips2d Elips2d; typedef gp_Hypr2d Hypr2d; typedef gp_Parab2d Parab2d; typedef gp_Pnt2d Pnt2d; typedef gp_Trsf2d Trsf2d; typedef Geom2d_Curve Curve; typedef Geom2d_BSplineCurve BSplineCurve; typedef TColStd_Array1OfReal Array1OfReal; typedef TColStd_Array1OfInteger Array1OfInteger; typedef TColgp_Array1OfPnt2d Array1OfPnt2d; //======================================================================= //function : BSplineCurveBuilder //purpose : //======================================================================= static Handle(Geom2d_BSplineCurve) BSplineCurveBuilder ( const Handle(Geom2d_Conic)& TheConic, const Convert_ConicToBSplineCurve& Convert ) { Handle(Geom2d_BSplineCurve) TheCurve; Standard_Integer NbPoles = Convert.NbPoles(); Standard_Integer NbKnots = Convert.NbKnots(); Array1OfPnt2d Poles (1, NbPoles); Array1OfReal Weights (1, NbPoles); Array1OfReal Knots (1, NbKnots); Array1OfInteger Mults (1, NbKnots); Standard_Integer i; for (i = 1; i <= NbPoles; i++) { Poles (i) = Convert.Pole (i); Weights (i) = Convert.Weight (i); } for (i = 1; i <= NbKnots; i++) { Knots (i) = Convert.Knot (i); Mults (i) = Convert.Multiplicity (i); } TheCurve = new BSplineCurve ( Poles, Weights, Knots, Mults, Convert.Degree(), Convert.IsPeriodic()); gp_Ax22d Axis = TheConic->Position(); if ( ( Axis.XDirection() ^ Axis.YDirection()) < 0.) { // Then the axis is left-handed, apply a symmetry to the curve. gp_Trsf2d Sym; Sym.SetMirror(gp::OX2d()); TheCurve->Transform(Sym); } Trsf2d T; T.SetTransformation (TheConic->XAxis(), gp::OX2d()); Handle(Geom2d_BSplineCurve) Cres = Handle(Geom2d_BSplineCurve)::DownCast(TheCurve->Transformed (T)); return Cres; } //======================================================================= //function : SplitBSplineCurve //purpose : //======================================================================= Handle(Geom2d_BSplineCurve) Geom2dConvert::SplitBSplineCurve ( const Handle(Geom2d_BSplineCurve)& C, const Standard_Integer FromK1, const Standard_Integer ToK2, const Standard_Boolean SameOrientation ) { Standard_Integer TheFirst = C->FirstUKnotIndex (); Standard_Integer TheLast = C->LastUKnotIndex (); if (FromK1 == ToK2) throw Standard_DomainError(); Standard_Integer FirstK = Min (FromK1, ToK2); Standard_Integer LastK = Max (FromK1, ToK2); if (FirstK < TheFirst || LastK > TheLast) throw Standard_OutOfRange(); Handle(Geom2d_BSplineCurve) NewCurve = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy()); NewCurve->Segment(C->Knot(FirstK),C->Knot(LastK)); if (C->IsPeriodic()) { if (!SameOrientation) NewCurve->Reverse(); } else { if (FromK1 > ToK2) NewCurve->Reverse(); } return NewCurve; } //======================================================================= //function : SplitBSplineCurve //purpose : //======================================================================= Handle(Geom2d_BSplineCurve) Geom2dConvert::SplitBSplineCurve ( const Handle(Geom2d_BSplineCurve)& C, const Standard_Real FromU1, const Standard_Real ToU2, const Standard_Real, // ParametricTolerance, const Standard_Boolean SameOrientation ) { Standard_Real FirstU = Min( FromU1, ToU2); Standard_Real LastU = Max( FromU1, ToU2); Handle (Geom2d_BSplineCurve) C1 = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy()); C1->Segment(FirstU, LastU); if (C->IsPeriodic()) { if (!SameOrientation) C1->Reverse(); } else { if (FromU1 > ToU2) C1->Reverse(); } return C1; } //======================================================================= //function : CurveToBSplineCurve //purpose : //======================================================================= Handle(Geom2d_BSplineCurve) Geom2dConvert::CurveToBSplineCurve ( const Handle(Geom2d_Curve)& C, const Convert_ParameterisationType Parameterisation) { Handle (BSplineCurve) TheCurve; if (C->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { Handle (Curve) Curv; Handle(Geom2d_TrimmedCurve) Ctrim = Handle(Geom2d_TrimmedCurve)::DownCast(C); Curv = Ctrim->BasisCurve(); Standard_Real U1 = Ctrim->FirstParameter(); Standard_Real U2 = Ctrim->LastParameter(); // Si la courbe n'est pas vraiment restreinte, on ne risque pas // le Raise dans le BS->Segment. if (!Curv->IsPeriodic()) { if (U1 < Curv->FirstParameter()) U1 = Curv->FirstParameter(); if (U2 > Curv->LastParameter()) U2 = Curv->LastParameter(); } if (Curv->IsKind(STANDARD_TYPE(Geom2d_Line))) { gp_Pnt2d Pdeb = Ctrim->StartPoint(); gp_Pnt2d Pfin = Ctrim->EndPoint(); Array1OfPnt2d Poles (1, 2); Poles (1) = Pdeb; Poles (2) = Pfin; Array1OfReal Knots (1, 2); Knots (1) = Ctrim->FirstParameter (); Knots (2) = Ctrim->LastParameter(); Array1OfInteger Mults (1, 2); Mults (1) = 2; Mults (2) = 2; Standard_Integer Degree = 1; TheCurve = new Geom2d_BSplineCurve (Poles, Knots, Mults, Degree); } else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Circle))) { Handle(Geom2d_Circle) TheConic= Handle(Geom2d_Circle)::DownCast(Curv); Circ2d C2d (gp::OX2d(), TheConic->Radius()); if(Parameterisation != Convert_RationalC1) { Convert_CircleToBSplineCurve Convert (C2d, U1, U2, Parameterisation); TheCurve = BSplineCurveBuilder (TheConic, Convert); } else { if(U2 - U1 < 6.) { Convert_CircleToBSplineCurve Convert (C2d, U1, U2, Parameterisation); TheCurve = BSplineCurveBuilder (TheConic, Convert); } else { // split circle to avoide numerical // overflow when U2 - U1 =~ 2*PI Standard_Real Umed = (U1 + U2) * .5; Convert_CircleToBSplineCurve Convert1 (C2d, U1, Umed, Parameterisation); Handle (BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1); Convert_CircleToBSplineCurve Convert2 (C2d, Umed, U2, Parameterisation); Handle (BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2); Geom2dConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1, Parameterisation); CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True); TheCurve = CCTBSpl.BSplineCurve(); } } } else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) { Handle(Geom2d_Ellipse) TheConic = Handle(Geom2d_Ellipse)::DownCast(Curv); Elips2d E2d (gp::OX2d(), TheConic->MajorRadius(), TheConic->MinorRadius()); if(Parameterisation != Convert_RationalC1) { Convert_EllipseToBSplineCurve Convert (E2d, U1, U2, Parameterisation); TheCurve = BSplineCurveBuilder (TheConic, Convert); } else { if(U2 - U1 < 6.) { Convert_EllipseToBSplineCurve Convert (E2d, U1, U2, Parameterisation); TheCurve = BSplineCurveBuilder (TheConic, Convert); } else { // split ellipse to avoide numerical // overflow when U2 - U1 =~ 2*PI Standard_Real Umed = (U1 + U2) * .5; Convert_EllipseToBSplineCurve Convert1 (E2d, U1, Umed, Parameterisation); Handle (BSplineCurve) TheCurve1 = BSplineCurveBuilder (TheConic, Convert1); Convert_EllipseToBSplineCurve Convert2 (E2d, Umed, U2, Parameterisation); Handle (BSplineCurve) TheCurve2 = BSplineCurveBuilder (TheConic, Convert2); Geom2dConvert_CompCurveToBSplineCurve CCTBSpl(TheCurve1, Parameterisation); CCTBSpl.Add(TheCurve2, Precision::PConfusion(), Standard_True); TheCurve = CCTBSpl.BSplineCurve(); } } } else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) { Handle(Geom2d_Hyperbola) TheConic = Handle(Geom2d_Hyperbola)::DownCast(Curv); Hypr2d H2d (gp::OX2d(), TheConic->MajorRadius(), TheConic->MinorRadius()); Convert_HyperbolaToBSplineCurve Convert (H2d, U1, U2); TheCurve = BSplineCurveBuilder (TheConic, Convert); } else if (Curv->IsKind(STANDARD_TYPE(Geom2d_Parabola))) { Handle(Geom2d_Parabola) TheConic = Handle(Geom2d_Parabola)::DownCast(Curv); Parab2d Prb2d (gp::OX2d(), TheConic->Focal()); Convert_ParabolaToBSplineCurve Convert (Prb2d, U1, U2); TheCurve = BSplineCurveBuilder (TheConic, Convert); } else if (Curv->IsKind (STANDARD_TYPE(Geom2d_BezierCurve))) { Handle(Geom2d_BezierCurve) CBez = Handle(Geom2d_BezierCurve)::DownCast(Curv->Copy()); CBez->Segment (U1, U2); Standard_Integer NbPoles = CBez->NbPoles(); Standard_Integer Degree = CBez->Degree(); Array1OfPnt2d Poles (1, NbPoles); Array1OfReal Knots (1, 2); Array1OfInteger Mults (1, 2); Knots (1) = 0.0; Knots (2) = 1.0; Mults (1) = Degree + 1; Mults (2) = Degree + 1; CBez->Poles (Poles); if (CBez->IsRational()) { Array1OfReal Weights (1, NbPoles); CBez->Weights (Weights); TheCurve = new BSplineCurve (Poles, Weights, Knots, Mults, Degree); } else { TheCurve = new BSplineCurve (Poles, Knots, Mults, Degree); } } else if (Curv->IsKind (STANDARD_TYPE(Geom2d_BSplineCurve))) { TheCurve = Handle(Geom2d_BSplineCurve)::DownCast(Curv->Copy()); TheCurve->Segment(U1,U2); } else if (Curv->IsKind (STANDARD_TYPE(Geom2d_OffsetCurve))) { Standard_Real Tol2d = 1.e-4; GeomAbs_Shape Order = GeomAbs_C2; Standard_Integer MaxSegments = 16, MaxDegree = 14; Geom2dConvert_ApproxCurve ApprCOffs(C, Tol2d, Order, MaxSegments, MaxDegree); if (ApprCOffs.HasResult()) TheCurve = ApprCOffs.Curve(); else throw Standard_ConstructionError(); } else { throw Standard_DomainError("No such curve"); } } else { if (C->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) { Handle(Geom2d_Ellipse) TheConic = Handle(Geom2d_Ellipse)::DownCast(C); Elips2d E2d (gp::OX2d(), TheConic->MajorRadius(), TheConic->MinorRadius()); Convert_EllipseToBSplineCurve Convert (E2d, Parameterisation); TheCurve = BSplineCurveBuilder (TheConic, Convert); TheCurve->SetPeriodic(); } else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) { Handle(Geom2d_Circle) TheConic = Handle(Geom2d_Circle)::DownCast(C); Circ2d C2d (gp::OX2d(), TheConic->Radius()); Convert_CircleToBSplineCurve Convert (C2d, Parameterisation); TheCurve = BSplineCurveBuilder (TheConic, Convert); TheCurve->SetPeriodic(); } else if (C->IsKind (STANDARD_TYPE(Geom2d_BezierCurve))) { Handle(Geom2d_BezierCurve) CBez = Handle(Geom2d_BezierCurve)::DownCast(C); Standard_Integer NbPoles = CBez->NbPoles(); Standard_Integer Degree = CBez->Degree(); Array1OfPnt2d Poles (1, NbPoles); Array1OfReal Knots (1, 2); Array1OfInteger Mults (1, 2); Knots (1) = 0.0; Knots (2) = 1.0; Mults (1) = Degree + 1; Mults (2) = Degree + 1; CBez->Poles (Poles); if (CBez->IsRational()) { Array1OfReal Weights (1, NbPoles); CBez->Weights (Weights); TheCurve = new BSplineCurve (Poles, Weights, Knots, Mults, Degree); } else { TheCurve = new BSplineCurve (Poles, Knots, Mults, Degree); } } else if (C->IsKind (STANDARD_TYPE(Geom2d_BSplineCurve))) { TheCurve = Handle(Geom2d_BSplineCurve)::DownCast(C->Copy()); } else if (C->IsKind (STANDARD_TYPE(Geom2d_OffsetCurve))) { Standard_Real Tol2d = 1.e-4; GeomAbs_Shape Order = GeomAbs_C2; Standard_Integer MaxSegments = 16, MaxDegree = 14; Geom2dConvert_ApproxCurve ApprCOffs(C, Tol2d, Order, MaxSegments, MaxDegree); if (ApprCOffs.HasResult()) TheCurve = ApprCOffs.Curve(); else throw Standard_ConstructionError(); } else { throw Standard_DomainError(); } } return TheCurve; } //======================================================================= //class : law_evaluator //purpose : //======================================================================= class Geom2dConvert_law_evaluator : public BSplCLib_EvaluatorFunction { public: Geom2dConvert_law_evaluator (const Handle(Geom2d_BSplineCurve)& theAncore) : myAncore (theAncore) {} virtual void Evaluate (const Standard_Integer theDerivativeRequest, const Standard_Real* theStartEnd, const Standard_Real theParameter, Standard_Real& theResult, Standard_Integer& theErrorCode) const { theErrorCode = 0; if (!myAncore.IsNull() && theParameter >= theStartEnd[0] && theParameter <= theStartEnd[1] && theDerivativeRequest == 0) { gp_Pnt2d aPoint; myAncore->D0 (theParameter, aPoint); theResult = aPoint.Coord (2); } else theErrorCode = 1; } private: Handle(Geom2d_BSplineCurve) myAncore; }; //======================================================================= //function : MultNumandDenom //purpose : Multiply two BSpline curves to make one //======================================================================= static Handle(Geom2d_BSplineCurve) MultNumandDenom(const Handle(Geom2d_BSplineCurve)& a , const Handle(Geom2d_BSplineCurve)& BS ) { TColStd_Array1OfReal aKnots(1,a->NbKnots()); TColStd_Array1OfReal BSKnots(1,BS->NbKnots()); TColStd_Array1OfReal BSFlatKnots(1,BS->NbPoles()+BS->Degree()+1); TColStd_Array1OfReal BSWeights(1,BS->NbPoles()); TColStd_Array1OfInteger aMults(1,a->NbKnots()); TColStd_Array1OfInteger BSMults(1,BS->NbKnots()); TColgp_Array1OfPnt2d aPoles(1,a->NbPoles()); TColgp_Array1OfPnt2d BSPoles(1,BS->NbPoles()); Handle(Geom2d_BSplineCurve) res; Handle(TColStd_HArray1OfReal) resKnots; Handle(TColStd_HArray1OfInteger) resMults; Standard_Real start_value,end_value; Standard_Real tolerance=Precision::Confusion(); Standard_Integer resNbPoles,degree, ii,jj, aStatus; BS->Knots(BSKnots); BS->Multiplicities(BSMults); BS->Poles(BSPoles); BS->Weights(BSWeights); BS->KnotSequence(BSFlatKnots); start_value = BSKnots(1); end_value = BSKnots(BS->NbKnots()); a->Knots(aKnots); a->Poles(aPoles); a->Multiplicities(aMults); BSplCLib::Reparametrize(BS->FirstParameter(),BS->LastParameter(),aKnots); Handle(Geom2d_BSplineCurve) anAncore = new Geom2d_BSplineCurve (aPoles, aKnots, aMults, a->Degree()); BSplCLib::MergeBSplineKnots(tolerance,start_value,end_value, a->Degree(),aKnots,aMults, BS->Degree(),BSKnots,BSMults, resNbPoles,resKnots,resMults); degree=BS->Degree()+a->Degree(); TColgp_Array1OfPnt2d resNumPoles(1,resNbPoles); TColStd_Array1OfReal resDenPoles(1,resNbPoles); TColgp_Array1OfPnt2d resPoles(1,resNbPoles); TColStd_Array1OfReal resFlatKnots(1,resNbPoles+degree+1); BSplCLib::KnotSequence(resKnots->Array1(),resMults->Array1(),resFlatKnots); for (ii=1;ii<=BS->NbPoles();ii++) for (jj=1;jj<=2;jj++) BSPoles(ii).SetCoord(jj,BSPoles(ii).Coord(jj)*BSWeights(ii)); //POP pour NT Geom2dConvert_law_evaluator ev (anAncore); BSplCLib::FunctionMultiply(ev, BS->Degree(), BSFlatKnots, BSPoles, resFlatKnots, degree, resNumPoles, aStatus); BSplCLib::FunctionMultiply(ev, BS->Degree(), BSFlatKnots, BSWeights, resFlatKnots, degree, resDenPoles, aStatus); // BSplCLib::FunctionMultiply(law_evaluator, // BS->Degree(), // BSFlatKnots, // BSPoles, // resFlatKnots, // degree, // resNumPoles, // aStatus); // BSplCLib::FunctionMultiply(law_evaluator, // BS->Degree(), // BSFlatKnots, // BSWeights, // resFlatKnots, // degree, // resDenPoles, // aStatus); for (ii=1;ii<=resNbPoles;ii++) for(jj=1;jj<=2;jj++) resPoles(ii).SetCoord(jj,resNumPoles(ii).Coord(jj)/resDenPoles(ii)); res = new Geom2d_BSplineCurve(resPoles,resDenPoles,resKnots->Array1(),resMults->Array1(),degree); return res; } //======================================================================= //function : Pretreatment //purpose : Put the two first and two last weigths at one if they are // equal //======================================================================= static void Pretreatment(TColGeom2d_Array1OfBSplineCurve& tab) {Standard_Integer i,j; Standard_Real a; for (i=0;i<=(tab.Length()-1);i++){ if (tab(i)->IsRational()) { a=tab(i)->Weight(1) ; if ((tab(i)->Weight(2)==a)&& (tab(i)->Weight(tab(i)->NbPoles()-1)==a) && (tab(i)->Weight(tab(i)->NbPoles())==a)) for (j=1;j<=tab(i)->NbPoles();j++) tab(i)->SetWeight(j,tab(i)->Weight(j)/a) ; } } } //======================================================================= //function : NeedToBeTreated //purpose : Say if the BSpline is rationnal and if the two first and two // last weigths are different //======================================================================= static Standard_Boolean NeedToBeTreated(const Handle(Geom2d_BSplineCurve)& BS) { TColStd_Array1OfReal tabWeights(1,BS->NbPoles()); if (BS->IsRational()) { BS->Weights(tabWeights); if ((BSplCLib::IsRational(tabWeights,1,BS->NbPoles()))&& ((BS->Weight(1)<(1-Precision::Confusion()))|| (BS->Weight(1)>(1+Precision::Confusion()))|| (BS->Weight(2)<(1-Precision::Confusion()))|| (BS->Weight(2)>(1+Precision::Confusion()))|| (BS->Weight(BS->NbPoles()-1)<(1-Precision::Confusion()))|| (BS->Weight(BS->NbPoles()-1)>(1+Precision::Confusion()))|| (BS->Weight(BS->NbPoles())<(1-Precision::Confusion()))|| (BS->Weight(BS->NbPoles())>(1+Precision::Confusion())))) return Standard_True; else return Standard_False; } else return Standard_False ; } //======================================================================= //function : Need2DegRepara //purpose : in the case of wire closed G1 it says if you will to use a // two degree reparametrisation to close it C1 //======================================================================= static Standard_Boolean Need2DegRepara(const TColGeom2d_Array1OfBSplineCurve& tab) {Standard_Integer i; gp_Vec2d Vec1,Vec2; gp_Pnt2d Pint; Standard_Real Rapport=1.0e0; for (i=0;i<=tab.Length()-2;i++){ tab(i+1)->D1(tab(i+1)->FirstParameter(),Pint,Vec1); tab(i)->D1(tab(i)->LastParameter(),Pint,Vec2); Rapport=Rapport*Vec2.Magnitude()/Vec1.Magnitude(); } if ((Rapport<=(1.0e0 +Precision::Confusion()))&&(Rapport>=(1.0e0-Precision::Confusion()))) return Standard_False; else return Standard_True; } //======================================================================= //function : Indexmin //purpose : Give the index of the curve which has the lowest degree //======================================================================= static Standard_Integer Indexmin(const TColGeom2d_Array1OfBSplineCurve& tab) { Standard_Integer i,index=0,degree; degree=tab(0)->Degree(); for (i=0;i<=tab.Length()-1;i++) if (tab(i)->Degree()<=degree){ degree=tab(i)->Degree(); index=i; } return index; } //======================================================================= //function : NewTabClosedG1 //purpose : //======================================================================= static void ReorderArrayOfG1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves, TColStd_Array1OfReal& ArrayOfToler, TColStd_Array1OfBoolean& tabG1, const Standard_Integer StartIndex, const Standard_Real ClosedTolerance) {Standard_Integer i; TColGeom2d_Array1OfBSplineCurve ArraybisOfCurves(0,ArrayOfCurves.Length()-1); TColStd_Array1OfReal ArraybisOfToler(0,ArrayOfToler.Length()-1); TColStd_Array1OfBoolean tabbisG1(0,tabG1.Length()-1); for (i=0;i<=ArrayOfCurves.Length()-1;i++){ if (i!=ArrayOfCurves.Length()-1){ ArraybisOfCurves(i)=ArrayOfCurves(i); ArraybisOfToler(i)=ArrayOfToler(i); tabbisG1(i)=tabG1(i); } else ArraybisOfCurves(i)=ArrayOfCurves(i); } for (i=0;i<=(ArrayOfCurves.Length()-(StartIndex+2));i++){ ArrayOfCurves(i)=ArraybisOfCurves(i+StartIndex+1); if (i!=(ArrayOfCurves.Length()-(StartIndex+2))){ ArrayOfToler(i)=ArraybisOfToler(i+StartIndex+1); tabG1(i)=tabbisG1(i+StartIndex+1); } } ArrayOfToler(ArrayOfCurves.Length()-(StartIndex+2))=ClosedTolerance; tabG1(ArrayOfCurves.Length()-(StartIndex+2))=Standard_True; for (i=(ArrayOfCurves.Length()-(StartIndex+1));i<=(ArrayOfCurves.Length()-1);i++){ if (i!=ArrayOfCurves.Length()-1){ ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1))); ArrayOfToler(i)=ArraybisOfToler(i-(ArrayOfCurves.Length()-(StartIndex+1))); tabG1(i)=tabbisG1(i-(ArrayOfCurves.Length()-(StartIndex+1))); } else ArrayOfCurves(i)=ArraybisOfCurves(i-(ArrayOfCurves.Length()-(StartIndex+1))); } } //======================================================================= //function : GeomAbsToInteger //purpose : //======================================================================= static Standard_Integer GeomAbsToInteger(const GeomAbs_Shape gcont) { Standard_Integer cont=0 ; switch (gcont) { case GeomAbs_C0 : cont = 0 ; break ; case GeomAbs_G1 : cont = 1 ; break ; case GeomAbs_C1 : cont = 2 ; break ; case GeomAbs_G2 : cont = 3 ; break ; case GeomAbs_C2 : cont = 4 ; break ; case GeomAbs_C3 : cont = 5 ; break ; case GeomAbs_CN : cont = 6 ; break ; } return cont ; } //======================================================================= //function : Continuity //purpose : //======================================================================= static GeomAbs_Shape Continuity(const Handle(Geom2d_Curve)& C1, const Handle(Geom2d_Curve)& C2, const Standard_Real u1, const Standard_Real u2, const Standard_Boolean r1, const Standard_Boolean r2, const Standard_Real tl, const Standard_Real ta) { GeomAbs_Shape cont = GeomAbs_C0; Standard_Integer index1, index2 ; Standard_Real tolerance,value ; // Standard_Boolean fini = Standard_False; gp_Vec2d d1,d2; // gp_Dir2d dir1,dir2; gp_Pnt2d point1, point2 ; Standard_Integer cont1, cont2 ; GeomAbs_Shape gcont1 = C1->Continuity(), gcont2 = C2->Continuity(); cont1 = GeomAbsToInteger(gcont1) ; cont2 = GeomAbsToInteger(gcont2) ; Handle(Geom2d_Curve) aCurve1 = C1 ; Handle(Geom2d_Curve) aCurve2 = C2 ; if (C1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))){ Handle(Geom2d_TrimmedCurve) aTrimmed = Handle(Geom2d_TrimmedCurve) ::DownCast(aCurve1) ; aCurve1 = aTrimmed->BasisCurve() ; } if (C2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))){ Handle(Geom2d_TrimmedCurve) aTrimmed = Handle(Geom2d_TrimmedCurve) ::DownCast(aCurve2) ; aCurve2 = aTrimmed->BasisCurve() ; } if (aCurve1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))){ Handle(Geom2d_BSplineCurve) BSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(aCurve1) ; BSplineCurve->Resolution(tl, tolerance) ; BSplineCurve->LocateU(u1, tolerance, index1, index2) ; if (index1 > 1 && index2 < BSplineCurve->NbKnots() && index1 == index2) { cont1 = BSplineCurve->Degree() - BSplineCurve->Multiplicity(index1) ; } else { cont1 = 5 ; } } if (aCurve2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))){ Handle(Geom2d_BSplineCurve) BSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(aCurve2) ; BSplineCurve->Resolution(tl, tolerance) ; BSplineCurve->LocateU(u2, tolerance, index1, index2) ; if (index1 > 1 && index2 < BSplineCurve->NbKnots() && index1 == index2) { cont2 = BSplineCurve->Degree() - BSplineCurve->Multiplicity(index1) ; } else { cont2 = 5 ; } } aCurve1->D1(u1, point1, d1) ; aCurve2->D1(u2, point2, d2) ; if (point1.SquareDistance(point2) <= tl * tl) { if (cont1 != 0 && cont2 != 0) { if (d1.SquareMagnitude() >= tl * tl && d2.SquareMagnitude() >= tl * tl) { if (r1) { d1.SetCoord(-d1.X(),-d1.Y()) ; } if (r2) { d2.SetCoord(-d2.X(),-d2.Y()) ; } value = d1.Dot(d2) ; if ((d1.Magnitude()<=(d2.Magnitude()+tl))&& (d1.Magnitude()>=(d2.Magnitude()-tl))&& (value/(d1.Magnitude()*d2.Magnitude()) >= 1.0e0 - ta * ta)) { cont = GeomAbs_C1 ; } else { d1.Normalize() ; d2.Normalize() ; value = Abs(d1.Dot(d2)) ; if (value >= 1.0e0 - ta * ta) { cont = GeomAbs_G1 ; } } } } } else throw Standard_Failure("Courbes non jointives"); return cont ; } //======================================================================= //function : Continuity //purpose : //======================================================================= static GeomAbs_Shape Continuity(const Handle(Geom2d_Curve)& C1, const Handle(Geom2d_Curve)& C2, const Standard_Real u1, const Standard_Real u2, const Standard_Boolean r1, const Standard_Boolean r2) { return Continuity(C1,C2,u1,u2,r1,r2, Precision::Confusion(),Precision::Angular()); } //======================================================================= //class :reparameterise_evaluator //purpose : //======================================================================= class Geom2dConvert_reparameterise_evaluator : public BSplCLib_EvaluatorFunction { public: Geom2dConvert_reparameterise_evaluator (const Standard_Real thePolynomialCoefficient[3]) { memcpy(myPolynomialCoefficient, thePolynomialCoefficient, sizeof(myPolynomialCoefficient)); } virtual void Evaluate (const Standard_Integer theDerivativeRequest, const Standard_Real* /*theStartEnd*/, const Standard_Real theParameter, Standard_Real& theResult, Standard_Integer& theErrorCode) const { theErrorCode = 0; PLib::EvalPolynomial (theParameter, theDerivativeRequest, 2, 1, *((Standard_Real* )myPolynomialCoefficient), // function really only read values from this array theResult); } private: Standard_Real myPolynomialCoefficient[3]; }; //======================================================================= //function : ConcatG1 //purpose : //======================================================================= void Geom2dConvert::ConcatG1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves, const TColStd_Array1OfReal& ArrayOfToler, Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated, Standard_Boolean& ClosedFlag, const Standard_Real ClosedTolerance) {Standard_Integer nb_curve=ArrayOfCurves.Length(), nb_vertexG1, nb_group=0, index=0,i,ii,j,jj, indexmin, nb_vertex_group0=0; Standard_Real lambda, //coeff de raccord G1 First,PreLast=0; gp_Vec2d Vec1,Vec2; //vecteurs tangents consecutifs gp_Pnt2d Pint; Handle(Geom2d_BSplineCurve) Curve1,Curve2; TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //tableau de continuite G1 aux raccords TColStd_Array1OfReal local_tolerance(0, ArrayOfToler.Length()-1) ; for (i= 0; i < ArrayOfToler.Length() ; i++) { local_tolerance(i) = ArrayOfToler(i) ; } for (i=0 ;i= 1){ First=ArrayOfCurves(i)->FirstParameter(); if (Continuity(ArrayOfCurves(i-1), ArrayOfCurves(i), PreLast,First, Standard_True, Standard_True)=GeomAbs_G1) tabG1(i-1)=Standard_True; //True=Continuite G1 else tabG1(i-1)=Standard_False; } } PreLast=ArrayOfCurves(i)->LastParameter(); } while (index<=nb_curve-1){ //determination des caracteristiques du Wire nb_vertexG1=0; while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True)) nb_vertexG1++; nb_group++; if (index==0) nb_vertex_group0=nb_vertexG1; index=index+1+nb_vertexG1; } if ((ClosedFlag)&&(nb_group!=1)){ //rearrangement du tableau nb_group--; ReorderArrayOfG1(ArrayOfCurves, local_tolerance, tabG1, nb_vertex_group0, ClosedTolerance); } ArrayOfConcatenated = new TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1); Standard_Boolean fusion; // Standard_Integer k=0; index=0; Pretreatment(ArrayOfCurves); Standard_Real aPolynomialCoefficient[3]; Standard_Boolean NeedDoubleDegRepara = Need2DegRepara(ArrayOfCurves); if (nb_group==1 && ClosedFlag && NeedDoubleDegRepara) { Curve1 = ArrayOfCurves(nb_curve-1); if (Curve1->Degree() > Geom2d_BSplineCurve::MaxDegree()/2) ClosedFlag = Standard_False; } if ((nb_group==1) && (ClosedFlag)){ //traitement d'un cas particulier indexmin=Indexmin(ArrayOfCurves); if (indexmin!=(ArrayOfCurves.Length()-1)) ReorderArrayOfG1(ArrayOfCurves, local_tolerance, tabG1, indexmin, ClosedTolerance); Curve2=ArrayOfCurves(0); for (j=1;j<=nb_curve-1;j++){ //boucle secondaire a l'interieur de chaque groupe Curve1=ArrayOfCurves(j); if ( (j==(nb_curve-1)) && (NeedDoubleDegRepara)){ const Standard_Integer aNewCurveDegree = 2 * Curve1->Degree(); Curve2->D1(Curve2->LastParameter(),Pint,Vec1); Curve1->D1(Curve1->FirstParameter(),Pint,Vec2); lambda=Vec2.Magnitude()/Vec1.Magnitude(); TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots()); Curve1->Knots(KnotC1); Curve1->D1(Curve1->LastParameter(),Pint,Vec2); ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1); Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude(); Standard_Real tmax,a,b,c, umin=Curve1->FirstParameter(),umax=Curve1->LastParameter(); tmax=2*lambda*(umax-umin)/(1+lambda*lambda2); a=(lambda*lambda2-1)/(2*lambda*tmax); aPolynomialCoefficient[2] = a; b=(1/lambda); aPolynomialCoefficient[1] = b; c=umin; aPolynomialCoefficient[0] = c; TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1); TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots()); Curve1->Multiplicities(KnotC1Mults); BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots); KnotC1(1)=0.0; for (ii=2;ii<=KnotC1.Length();ii++) { // KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667 } TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles()); Curve1->Poles(Curve1Poles); for (ii=1;ii<=Curve1->NbKnots();ii++) KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii)); TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots())); BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots); TColgp_Array1OfPnt2d NewPoles(1,FlatKnots.Length()-(2*Curve1->Degree()+1)); Standard_Integer aStatus; TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles()); Curve1->Weights(Curve1Weights); for (ii=1;ii<=Curve1->NbPoles();ii++) for (jj=1;jj<=2;jj++) Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii)); //POP pour NT Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient); BSplCLib::FunctionReparameterise(ev, Curve1->Degree(), Curve1FlatKnots, Curve1Poles, FlatKnots, aNewCurveDegree, NewPoles, aStatus ); TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1)); BSplCLib::FunctionReparameterise(ev, Curve1->Degree(), Curve1FlatKnots, Curve1Weights, FlatKnots, aNewCurveDegree, NewWeights, aStatus ); // BSplCLib::FunctionReparameterise(reparameterise_evaluator, // Curve1->Degree(), // Curve1FlatKnots, // Curve1Poles, // FlatKnots, // 2*Curve1->Degree(), // NewPoles, // aStatus // ); // TColStd_Array1OfReal NewWeights(1,FlatKnots.Length()-(2*Curve1->Degree()+1)); // BSplCLib::FunctionReparameterise(reparameterise_evaluator, // Curve1->Degree(), // Curve1FlatKnots, // Curve1Weights, // FlatKnots, // 2*Curve1->Degree(), // NewWeights, // aStatus // ); for (ii=1;ii<=NewPoles.Length();ii++) for (jj=1;jj<=2;jj++) NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii)); Curve1 = new Geom2d_BSplineCurve(NewPoles, NewWeights, KnotC1, KnotC1Mults, aNewCurveDegree); } Geom2dConvert_CompCurveToBSplineCurve C(Curve2); fusion=C.Add(Curve1, local_tolerance(j-1)); //fusion de deux courbes adjacentes if (fusion==Standard_False) throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ; Curve2=C.BSplineCurve(); } Curve2->SetPeriodic(); //1 seule courbe C1 Curve2->RemoveKnot(Curve2->LastUKnotIndex(), Curve2->Multiplicity(Curve2->LastUKnotIndex())-1, Precision::Confusion()); ArrayOfConcatenated->SetValue(0,Curve2); } else for (i=0;i<=nb_group-1;i++){ //boucle principale sur chaque groupe de nb_vertexG1=0; //continuite interne G1 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True)) nb_vertexG1++; for (j=index;j<=index+nb_vertexG1;j++){ //boucle secondaire a l'interieur de chaque groupe Curve1=ArrayOfCurves(j); if (index==j) //initialisation en debut de groupe ArrayOfConcatenated->SetValue(i,Curve1); else{ Geom2dConvert_CompCurveToBSplineCurve C(ArrayOfConcatenated->Value(i)); fusion=C.Add(Curve1,ArrayOfToler(j-1)); //fusion de deux courbes adjacentes if (fusion==Standard_False) throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ; ArrayOfConcatenated->SetValue(i,C.BSplineCurve()); } } index=index+1+nb_vertexG1; } } //======================================================================= //function : ConcatC1 //purpose : //======================================================================= void Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves, const TColStd_Array1OfReal& ArrayOfToler, Handle(TColStd_HArray1OfInteger)& ArrayOfIndices, Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated, Standard_Boolean& ClosedFlag, const Standard_Real ClosedTolerance) { ConcatC1(ArrayOfCurves, ArrayOfToler, ArrayOfIndices, ArrayOfConcatenated, ClosedFlag, ClosedTolerance, Precision::Angular()) ; } //======================================================================= //function : ConcatC1 //purpose : //======================================================================= void Geom2dConvert::ConcatC1(TColGeom2d_Array1OfBSplineCurve& ArrayOfCurves, const TColStd_Array1OfReal& ArrayOfToler, Handle(TColStd_HArray1OfInteger)& ArrayOfIndices, Handle(TColGeom2d_HArray1OfBSplineCurve) & ArrayOfConcatenated, Standard_Boolean& ClosedFlag, const Standard_Real ClosedTolerance, const Standard_Real AngularTolerance) {Standard_Integer nb_curve=ArrayOfCurves.Length(), nb_vertexG1, nb_group=0, index=0,i,ii,j,jj, indexmin, nb_vertex_group0=0; Standard_Real lambda, //coeff de raccord G1 First,PreLast=0; gp_Vec2d Vec1,Vec2; //vecteurs tangents consecutifs gp_Pnt2d Pint; Handle(Geom2d_BSplineCurve) Curve1,Curve2; TColStd_Array1OfBoolean tabG1(0,nb_curve-2); //tableau de continuite G1 aux raccords TColStd_Array1OfReal local_tolerance(0, ArrayOfToler.Length()-1) ; for (i=0 ; i < ArrayOfToler.Length() ; i++) { local_tolerance(i) = ArrayOfToler(i) ; } for (i=0 ;i= 1){ First=ArrayOfCurves(i)->FirstParameter(); if (Continuity(ArrayOfCurves(i-1), ArrayOfCurves(i), PreLast,First, Standard_True, Standard_True, ArrayOfToler(i-1), AngularTolerance)=GeomAbs_G1) tabG1(i-1)=Standard_True; //True=Continuite G1 else tabG1(i-1)=Standard_False; } } PreLast=ArrayOfCurves(i)->LastParameter(); } while (index<=nb_curve-1){ //determination des caracteristiques du Wire nb_vertexG1=0; while(((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True)) nb_vertexG1++; nb_group++; if (index==0) nb_vertex_group0=nb_vertexG1; index=index+1+nb_vertexG1; } if ((ClosedFlag)&&(nb_group!=1)){ //rearrangement du tableau nb_group--; ReorderArrayOfG1(ArrayOfCurves, local_tolerance, tabG1, nb_vertex_group0, ClosedTolerance); } ArrayOfIndices = new TColStd_HArray1OfInteger(0,nb_group); ArrayOfConcatenated = new TColGeom2d_HArray1OfBSplineCurve(0,nb_group-1); Standard_Boolean fusion; Standard_Integer k=0; index=0; Pretreatment(ArrayOfCurves); Standard_Real aPolynomialCoefficient[3]; Standard_Boolean NeedDoubleDegRepara = Need2DegRepara(ArrayOfCurves); if (nb_group==1 && ClosedFlag && NeedDoubleDegRepara) { Curve1 = ArrayOfCurves(nb_curve-1); if (Curve1->Degree() > Geom2d_BSplineCurve::MaxDegree()/2) ClosedFlag = Standard_False; } if ((nb_group==1) && (ClosedFlag)){ //traitement d'un cas particulier ArrayOfIndices->SetValue(0,0); ArrayOfIndices->SetValue(1,0); indexmin=Indexmin(ArrayOfCurves); if (indexmin!=(ArrayOfCurves.Length()-1)) ReorderArrayOfG1(ArrayOfCurves, local_tolerance, tabG1, indexmin, ClosedTolerance); for (j=0;j<=nb_curve-1;j++){ //boucle secondaire a l'interieur de chaque groupe if (NeedToBeTreated(ArrayOfCurves(j))) { Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j)); } else Curve1=ArrayOfCurves(j); const Standard_Integer aNewCurveDegree = 2 * Curve1->Degree(); if (j==0) //initialisation en debut de groupe Curve2=Curve1; else{ if ( (j==(nb_curve-1)) && (NeedDoubleDegRepara)){ Curve2->D1(Curve2->LastParameter(),Pint,Vec1); Curve1->D1(Curve1->FirstParameter(),Pint,Vec2); lambda=Vec2.Magnitude()/Vec1.Magnitude(); TColStd_Array1OfReal KnotC1 (1, Curve1->NbKnots()); Curve1->Knots(KnotC1); Curve1->D1(Curve1->LastParameter(),Pint,Vec2); ArrayOfCurves(0)->D1(ArrayOfCurves(0)->FirstParameter(),Pint,Vec1); Standard_Real lambda2=Vec1.Magnitude()/Vec2.Magnitude(); Standard_Real tmax,a,b,c, umin=Curve1->FirstParameter(),umax=Curve1->LastParameter(); tmax=2*lambda*(umax-umin)/(1+lambda*lambda2); a=(lambda*lambda2-1)/(2*lambda*tmax); aPolynomialCoefficient[2] = a; b=(1/lambda); aPolynomialCoefficient[1] = b; c=umin; aPolynomialCoefficient[0] = c; TColStd_Array1OfReal Curve1FlatKnots(1,Curve1->NbPoles()+Curve1->Degree()+1); TColStd_Array1OfInteger KnotC1Mults(1,Curve1->NbKnots()); Curve1->Multiplicities(KnotC1Mults); BSplCLib::KnotSequence(KnotC1,KnotC1Mults,Curve1FlatKnots); KnotC1(1)=0.0; for (ii=2;ii<=KnotC1.Length();ii++) { // KnotC1(ii)=(-b+Abs(a)/a*Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); KnotC1(ii)=(-b+Sqrt(b*b-4*a*(c-KnotC1(ii))))/(2*a); //ifv 17.05.00 buc60667 } TColgp_Array1OfPnt2d Curve1Poles(1,Curve1->NbPoles()); Curve1->Poles(Curve1Poles); for (ii=1;ii<=Curve1->NbKnots();ii++) KnotC1Mults(ii)=(Curve1->Degree()+KnotC1Mults(ii)); TColStd_Array1OfReal FlatKnots(1,Curve1FlatKnots.Length()+(Curve1->Degree()*Curve1->NbKnots())); BSplCLib::KnotSequence(KnotC1,KnotC1Mults,FlatKnots); TColgp_Array1OfPnt2d NewPoles(1, FlatKnots.Length() - (aNewCurveDegree + 1)); Standard_Integer aStatus; TColStd_Array1OfReal Curve1Weights(1,Curve1->NbPoles()); Curve1->Weights(Curve1Weights); for (ii=1;ii<=Curve1->NbPoles();ii++) for (jj=1;jj<=2;jj++) Curve1Poles(ii).SetCoord(jj,Curve1Poles(ii).Coord(jj)*Curve1Weights(ii)); //POP pour NT Geom2dConvert_reparameterise_evaluator ev (aPolynomialCoefficient); // BSplCLib::FunctionReparameterise(reparameterise_evaluator, BSplCLib::FunctionReparameterise(ev, Curve1->Degree(), Curve1FlatKnots, Curve1Poles, FlatKnots, aNewCurveDegree, NewPoles, aStatus ); TColStd_Array1OfReal NewWeights(1, FlatKnots.Length() - (aNewCurveDegree + 1)); // BSplCLib::FunctionReparameterise(reparameterise_evaluator, BSplCLib::FunctionReparameterise(ev, Curve1->Degree(), Curve1FlatKnots, Curve1Weights, FlatKnots, aNewCurveDegree, NewWeights, aStatus ); for (ii=1;ii<=NewPoles.Length();ii++) { for (jj=1;jj<=2;jj++) NewPoles(ii).SetCoord(jj,NewPoles(ii).Coord(jj)/NewWeights(ii)); } Curve1 = new Geom2d_BSplineCurve(NewPoles, NewWeights, KnotC1, KnotC1Mults, aNewCurveDegree); } Geom2dConvert_CompCurveToBSplineCurve C(Curve2); fusion=C.Add(Curve1, local_tolerance(j-1)); //fusion de deux courbes adjacentes if (fusion==Standard_False) throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ; Curve2=C.BSplineCurve(); } } Curve2->SetPeriodic(); //1 seule courbe C1 Curve2->RemoveKnot(Curve2->LastUKnotIndex(), Curve2->Multiplicity(Curve2->LastUKnotIndex())-1, Precision::Confusion()); ArrayOfConcatenated->SetValue(0,Curve2); } else for (i=0;i<=nb_group-1;i++){ //boucle principale sur chaque groupe de nb_vertexG1=0; //continuite interne G1 while (((index+nb_vertexG1)<=nb_curve-2)&&(tabG1(index+nb_vertexG1)==Standard_True)) nb_vertexG1++; if ((!ClosedFlag)||(nb_group==1)){ //remplissage du tableau des indices conserves k++; ArrayOfIndices->SetValue(k-1,index); if (k==nb_group) ArrayOfIndices->SetValue(k,0); } else{ k++; ArrayOfIndices->SetValue(k-1,index+nb_vertex_group0+1); if (k==nb_group) ArrayOfIndices->SetValue(k,nb_vertex_group0+1); } for (j=index;j<=index+nb_vertexG1;j++){ //boucle secondaire a l'interieur de chaque groupe if (NeedToBeTreated(ArrayOfCurves(j))) Curve1=MultNumandDenom(Hermit::Solution(ArrayOfCurves(j)),ArrayOfCurves(j)); else Curve1=ArrayOfCurves(j); if (index==j) //initialisation en debut de groupe ArrayOfConcatenated->SetValue(i,Curve1); else{ Geom2dConvert_CompCurveToBSplineCurve C (ArrayOfConcatenated->Value(i)); fusion=C.Add(Curve1,ArrayOfToler(j-1)); //fusion de deux courbes adjacentes if (fusion==Standard_False) throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ; ArrayOfConcatenated->SetValue(i,C.BSplineCurve()); } } index=index+1+nb_vertexG1; } } //======================================================================= //function : C0BSplineToC1BSplineCurve //purpose : //======================================================================= void Geom2dConvert::C0BSplineToC1BSplineCurve(Handle(Geom2d_BSplineCurve)& BS, const Standard_Real tolerance) { TColStd_Array1OfInteger BSMults(1,BS->NbKnots()); TColStd_Array1OfReal BSKnots(1,BS->NbKnots()); Standard_Integer i,j,nbcurveC1=1; Standard_Real U1,U2; Standard_Boolean closed_flag = Standard_False ; gp_Pnt2d point1, point2; gp_Vec2d V1,V2; Standard_Boolean fusion; BS->Knots(BSKnots); BS->Multiplicities(BSMults); for (i=BS->FirstUKnotIndex() + 1;i<=(BS->LastUKnotIndex()-1);i++){ if (BSMults(i)==BS->Degree()) nbcurveC1++; } nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1); if (nbcurveC1>1){ TColGeom2d_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1); TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2); for (i=0;i<=nbcurveC1-2;i++) ArrayOfToler(i)=tolerance; U2=BS->FirstParameter() ; j=BS->FirstUKnotIndex() + 1 ; for (i=0;iLastUKnotIndex() && BSMults(j) < BS->Degree()) j++; U2=BSKnots(j); j++; Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy()); BSbis->Segment(U1,U2); ArrayOfCurves(i)=BSbis; } const Standard_Real anAngularToler = 1.0e-7; Handle(TColStd_HArray1OfInteger) ArrayOfIndices; Handle(TColGeom2d_HArray1OfBSplineCurve) ArrayOfConcatenated; BS->D1(BS->FirstParameter(),point1,V1); //a verifier BS->D1(BS->LastParameter(),point2,V2); if ((point1.SquareDistance(point2) < tolerance * tolerance) && (V1.IsParallel(V2, anAngularToler))) { closed_flag = Standard_True; } Geom2dConvert::ConcatC1(ArrayOfCurves, ArrayOfToler, ArrayOfIndices, ArrayOfConcatenated, closed_flag, tolerance); Geom2dConvert_CompCurveToBSplineCurve C(ArrayOfConcatenated->Value(0)); if (ArrayOfConcatenated->Length()>=2){ for (i=1;iLength();i++){ fusion=C.Add(ArrayOfConcatenated->Value(i),tolerance, Standard_True); if (fusion==Standard_False) throw Standard_ConstructionError("Geom2dConvert Concatenation Error") ; } } BS=C.BSplineCurve(); } } //======================================================================= //function : C0BSplineToArrayOfC1BSplineCurve //purpose : //======================================================================= void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) & BS, Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS, const Standard_Real tolerance) { C0BSplineToArrayOfC1BSplineCurve(BS, tabBS, tolerance, Precision::Angular()); } //======================================================================= //function : C0BSplineToArrayOfC1BSplineCurve //purpose : //======================================================================= void Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve) & BS, Handle(TColGeom2d_HArray1OfBSplineCurve) & tabBS, const Standard_Real AngularTolerance, const Standard_Real Tolerance) { TColStd_Array1OfInteger BSMults(1,BS->NbKnots()); TColStd_Array1OfReal BSKnots(1,BS->NbKnots()); Standard_Integer i,j,nbcurveC1=1; Standard_Real U1,U2; Standard_Boolean closed_flag = Standard_False ; gp_Pnt2d point1, point2; gp_Vec2d V1,V2; // Standard_Boolean fusion; BS->Knots(BSKnots); BS->Multiplicities(BSMults); for (i=BS->FirstUKnotIndex() ;i<=(BS->LastUKnotIndex()-1);i++){ if (BSMults(i)==BS->Degree()) nbcurveC1++; } nbcurveC1 = Min(nbcurveC1, BS->NbKnots() - 1); if (nbcurveC1>1){ TColGeom2d_Array1OfBSplineCurve ArrayOfCurves(0,nbcurveC1-1); TColStd_Array1OfReal ArrayOfToler(0,nbcurveC1-2); for (i=0;i<=nbcurveC1-2;i++) ArrayOfToler(i)=Tolerance; U2=BS->FirstParameter() ; j=BS->FirstUKnotIndex()+ 1 ; for (i=0;iLastUKnotIndex() && BSMults(j)Degree()) j++; U2=BSKnots(j); j++; Handle(Geom2d_BSplineCurve) BSbis=Handle(Geom2d_BSplineCurve)::DownCast(BS->Copy()); BSbis->Segment(U1,U2); ArrayOfCurves(i)=BSbis; } Handle(TColStd_HArray1OfInteger) ArrayOfIndices; BS->D1(BS->FirstParameter(),point1,V1); BS->D1(BS->LastParameter(),point2,V2); if (((point1.SquareDistance(point2) < Tolerance)) && (V1.IsParallel(V2, AngularTolerance))) { closed_flag = Standard_True; } Geom2dConvert::ConcatC1(ArrayOfCurves, ArrayOfToler, ArrayOfIndices, tabBS, closed_flag, Tolerance, AngularTolerance) ; } else{ tabBS = new TColGeom2d_HArray1OfBSplineCurve(0,0); tabBS->SetValue(0,BS); } }