// File: GeomFill_CircularBlendFunc.cxx // Created: Fri Jul 11 15:54:00 1997 // Author: Philippe MANGIN // #include #include #include #include #include #include #include #if DRAW #include #include #include static Standard_Integer NbSections = 0; #endif GeomAbs_Shape GeomFillNextShape(const GeomAbs_Shape S) { switch (S) { case GeomAbs_C0 : return GeomAbs_C1; case GeomAbs_C1 : return GeomAbs_C2; case GeomAbs_C2 : return GeomAbs_C3; case GeomAbs_C3 : return GeomAbs_CN; default : return GeomAbs_CN; } } void GeomFillFusInt(const TColStd_Array1OfReal& I1, const TColStd_Array1OfReal& I2, TColStd_SequenceOfReal& Seq) { Standard_Integer ind1=1, ind2=1; Standard_Real Epspar = Precision::PConfusion()*0.99; // en suposant que le positionement fonctionne a PConfusion()/2 Standard_Real v1, v2; // Initialisations : les IND1 et IND2 pointent sur le 1er element // de chacune des 2 tables a traiter. //--- On remplit TABSOR en parcourant TABLE1 et TABLE2 simultanement --- //------------------ en eliminant les occurrences multiples ------------ while ((ind1<=I1.Upper()) && (ind2<=I2.Upper())) { v1 = I1(ind1); v2 = I2(ind2); if (Abs(v1-v2)<= Epspar) { // Ici les elements de I1 et I2 conviennent . Seq.Append((v1+v2)/2); ind1++; ind2++; } else if (v1 < v2) { // Ici l' element de I1 convient. Seq.Append(v1); ind1++; } else { // Ici l' element de TABLE2 convient. Seq.Append(v2); ind2++; } } if (ind1>I1.Upper()) { //----- Ici I1 est epuise, on complete avec la fin de TABLE2 ------- for (; ind2<=I2.Upper(); ind2++) { Seq.Append(I2(ind2)); } } if (ind2>I2.Upper()) { //----- Ici I2 est epuise, on complete avec la fin de I1 ------- for (; ind1<=I1.Upper(); ind1++) { Seq.Append(I1(ind1)); } } } GeomFill_CircularBlendFunc:: GeomFill_CircularBlendFunc(const Handle(Adaptor3d_HCurve)& Path, const Handle(Adaptor3d_HCurve)& Curve1, const Handle(Adaptor3d_HCurve)& Curve2, const Standard_Real Radius, const Standard_Boolean Polynomial) : maxang(RealFirst()), minang(RealLast()), distmin(RealLast()) { // Recopie des arguments myPath = myTPath = Path; myCurve1 = myTCurve1 = Curve1; myCurve2 = myTCurve2 = Curve2; myRadius = Radius; // Estimations numeriques Discret(); // Type de convertion ? if (Polynomial) myTConv=Convert_Polynomial; else if(maxang > 0.65*PI) myTConv=Convert_QuasiAngular; //car c'est Continue else myTConv = Convert_TgtThetaOver2; //car c'est le plus performant // On en deduit la structure GeomFill::GetShape(maxang, myNbPoles, myNbKnots, myDegree, myTConv); } void GeomFill_CircularBlendFunc::Discret() { Standard_Real TFirst = myPath->FirstParameter(); Standard_Real TLast = myPath->LastParameter(), T; Standard_Integer ii; Standard_Real L1, L2, L; Handle(Adaptor3d_HCurve) C; gp_Pnt P1, P2, P3, Center; gp_Vec DCenter; P1 = myCurve1->Value(TFirst); P2 = myCurve1->Value((TFirst+TLast)/2.); P3 = myCurve1->Value(TLast); L1 = P1.Distance(P2) + P2.Distance(P3); P1 = myCurve2->Value(TFirst); P2 = myCurve2->Value((TFirst+TLast)/2.); P3 = myCurve2->Value(TLast); L2 = P1.Distance(P2) + P2.Distance(P3); if (L1>L2) { L = L1; C = myCurve1; } else { L = L2; C = myCurve2; } Standard_Real Fleche = 1.e-2 * L; Standard_Real Angle, Cosa, Percent; GCPnts_QuasiUniformDeflection Samp; Samp.Initialize(C->GetCurve(), Fleche); myBary.SetCoord(0.,0.,0.); gp_Vec ns1, ns2; if (Samp.IsDone()) { Percent = ((Standard_Real)1)/(2*Samp.NbPoints()); // char name[100]; for (ii=1; ii<=Samp.NbPoints(); ii++) { T = Samp.Parameter(ii); myCurve1->D0(T, P1); myCurve2->D0(T, P2); /* sprintf(name,"PNT_%d",NbSections++); DrawTrSurf::Set(name, P1); sprintf(name,"PNT_%d",NbSections++); DrawTrSurf::Set(name, P2);*/ myPath->D0(T, Center); ns1.SetXYZ( Center.XYZ() - P1.XYZ()); ns2.SetXYZ( Center.XYZ() - P2.XYZ()); ns1.Normalize(); ns2.Normalize(); Cosa = ns1.Dot(ns2); if(Cosa > 1.) {Cosa = 1.;} Angle = Abs(ACos(Cosa)); if (Angle>maxang) maxang = Angle; if (AngleD0(T, P1); myCurve2->D0(T, P2); myPath->D0(T, Center); ns1.SetXYZ( Center.XYZ() - P1.XYZ()); ns2.SetXYZ( Center.XYZ() - P2.XYZ()); ns1.Normalize(); ns2.Normalize(); Cosa = ns1.Dot(ns2); if(Cosa > 1.) Cosa = 1.; Angle = Abs(ACos(Cosa)); if (Angle>maxang) maxang = Angle; if (AngleD0(T, P1); myCurve2->D0(T, P2); myPath->D1(T, Center, DCenter); ns1.SetXYZ( Center.XYZ() - P1.XYZ()); ns2.SetXYZ( Center.XYZ() - P2.XYZ()); myreverse = (DCenter.Dot(ns1.Crossed(ns2)) < 0); } Standard_Boolean GeomFill_CircularBlendFunc::D0(const Standard_Real Param, const Standard_Real, const Standard_Real, TColgp_Array1OfPnt& Poles, TColgp_Array1OfPnt2d&, TColStd_Array1OfReal& Weigths) { gp_Pnt P1, P2, Center; gp_Vec ns1, ns2, nplan; gp_XYZ temp; // Positionnement myTPath->D0(Param, Center); myTCurve1->D0(Param, P1); myTCurve2->D0(Param, P2); ns1.SetXYZ( Center.XYZ() - P1.XYZ()); ns2.SetXYZ( Center.XYZ() - P2.XYZ()); if (!ns1.IsParallel(ns2,1.e-9)) nplan = ns1.Crossed(ns2); else { myTPath->D1(Param, Center, nplan); if (myreverse) nplan.Reverse(); } // Normalisation ns1.Normalize(); ns2.Normalize(); nplan.Normalize(); temp.SetLinearForm(myRadius, ns1.XYZ(), myRadius, ns2.XYZ(), 1, P1.XYZ(), P2.XYZ()); Center.ChangeCoord() = 0.5*temp; // Section GeomFill::GetCircle(myTConv, ns1, ns2, nplan, P1, P2, myRadius, Center, Poles, Weigths); #if DRAW // Handle(Geom_BSplineCurve) BS = // new Geom_BSplineCurve(Poles,Weights,Knots,Mults,Degree); // sprintf(name,"SECT_%d",NbSections++); // DrawTrSurf::Set(name,BS); #endif return Standard_True; } Standard_Boolean GeomFill_CircularBlendFunc::D1(const Standard_Real Param, // const Standard_Real First, const Standard_Real , // const Standard_Real Last, const Standard_Real , TColgp_Array1OfPnt& Poles, TColgp_Array1OfVec& DPoles, // TColgp_Array1OfPnt2d& Poles2d, TColgp_Array1OfPnt2d& , // TColgp_Array1OfVec2d& DPoles2d, TColgp_Array1OfVec2d& , TColStd_Array1OfReal& Weigths, TColStd_Array1OfReal& DWeigths) { gp_Pnt P1, P2, Center; Standard_Real invnorm1, invnorm2, invnormp; // gp_Vec DCenter, D2Center, nplan, dnplan, DP1, DP2; gp_Vec DCenter, nplan, dnplan, DP1, DP2; // gp_Vec ns1, ns2, Dns1, Dns2, vtmp; gp_Vec ns1, ns2, Dns1, Dns2; gp_XYZ temp; // Positionemment myTPath ->D1(Param, Center, DCenter); myTCurve1->D1(Param, P1, DP1); myTCurve2->D1(Param, P2, DP2); ns1.SetXYZ( Center.XYZ() - P1.XYZ()); ns2.SetXYZ( Center.XYZ() - P2.XYZ()); Dns1 = DCenter - DP1; Dns2 = DCenter - DP2; if (!ns1.IsParallel(ns2,1.e-9)) { nplan = ns1.Crossed(ns2); dnplan = Dns1.Crossed(ns2).Added( ns1.Crossed(Dns2)); } else { myTPath->D2(Param, Center, nplan, dnplan); if (myreverse) { nplan.Reverse(); dnplan.Reverse(); } } // Normalisation invnorm1 = ((Standard_Real) 1) / ns1.Magnitude(); invnorm2 = ((Standard_Real) 1) / ns2.Magnitude(); ns1 *= invnorm1; Dns1.SetLinearForm( -Dns1.Dot(ns1), ns1, Dns1); Dns1 *= invnorm1; ns2 *= invnorm2; Dns2.SetLinearForm(-Dns2.Dot(ns2), ns2, Dns2); Dns2 *= invnorm2; temp.SetLinearForm(myRadius, ns1.XYZ(), myRadius, ns2.XYZ(), 1, P1.XYZ(), P2.XYZ()); Center.ChangeCoord() = 0.5*temp; DCenter.SetLinearForm(myRadius, Dns1, myRadius, Dns2, 1, DP1, DP2); DCenter *= 0.5; invnormp = ((Standard_Real)1) / nplan.Magnitude(); nplan *= invnormp; dnplan.SetLinearForm(-dnplan.Dot(nplan), nplan, dnplan); dnplan *= invnormp; GeomFill::GetCircle(myTConv, ns1, ns2, Dns1, Dns2, nplan, dnplan, P1, P2, DP1, DP2, myRadius, 0, Center, DCenter, Poles, DPoles, Weigths, DWeigths); return Standard_True; } Standard_Boolean GeomFill_CircularBlendFunc::D2(const Standard_Real Param, // const Standard_Real First, const Standard_Real , // const Standard_Real Last, const Standard_Real , TColgp_Array1OfPnt& Poles, TColgp_Array1OfVec& DPoles, TColgp_Array1OfVec& D2Poles, // TColgp_Array1OfPnt2d& Poles2d, TColgp_Array1OfPnt2d& , // TColgp_Array1OfVec2d& DPoles2d, TColgp_Array1OfVec2d& , // TColgp_Array1OfVec2d& D2Poles2d, TColgp_Array1OfVec2d& , TColStd_Array1OfReal& Weigths, TColStd_Array1OfReal& DWeigths, TColStd_Array1OfReal& D2Weigths) { gp_Pnt P1, P2, Center; Standard_Real invnorm1, invnorm2, invnormp, sc; gp_Vec DCenter, D2Center, DP1, DP2, D2P1, D2P2; gp_Vec nplan, dnplan, d2nplan; gp_Vec ns1, ns2, Dns1, Dns2, D2ns1, D2ns2; gp_XYZ temp; // Positionement myTPath ->D2(Param, Center, DCenter, D2Center); myTCurve1->D2(Param, P1, DP1, D2P1); myTCurve2->D2(Param, P2, DP2, D2P2); ns1.SetXYZ( Center.XYZ() - P1.XYZ()); Dns1 = DCenter - DP1; D2ns1 = D2Center - D2P1; ns2.SetXYZ( Center.XYZ() - P2.XYZ()); Dns2 = DCenter - DP2; D2ns2 = D2Center - D2P2; if (!ns1.IsParallel(ns2,1.e-9)) { nplan = ns1.Crossed(ns2); dnplan = Dns1.Crossed(ns2).Added( ns1.Crossed(Dns2)); d2nplan.SetLinearForm(1, D2ns1.Crossed(ns2), 2, Dns1.Crossed(Dns2), ns1.Crossed(D2ns2)); } else { myTPath->D3(Param, Center, nplan, dnplan, d2nplan); if (myreverse) { nplan.Reverse(); dnplan.Reverse(); d2nplan.Reverse(); } } // Normalisation invnorm1 = ((Standard_Real) 1) / ns1.Magnitude(); invnorm2 = ((Standard_Real) 1) / ns2.Magnitude(); ns1 *= invnorm1; sc = Dns1.Dot(ns1); D2ns1.SetLinearForm( 3*sc*sc*invnorm1 - D2ns1.Dot(ns1) - invnorm1*Dns1.SquareMagnitude(), ns1, -2*sc*invnorm1 , Dns1, D2ns1); Dns1.SetLinearForm( -Dns1.Dot(ns1), ns1, Dns1); D2ns1 *= invnorm1; Dns1 *= invnorm1; ns2 *= invnorm2; sc = Dns2.Dot(ns2); D2ns2.SetLinearForm( 3*sc*sc*invnorm2 - D2ns2.Dot(ns2) - invnorm2*Dns2.SquareMagnitude(), ns2, -2*sc*invnorm2 , Dns2, D2ns2); Dns2.SetLinearForm(-sc, ns2, Dns2); D2ns2 *= invnorm2; Dns2 *= invnorm2; temp.SetLinearForm(myRadius, ns1.XYZ(), myRadius, ns2.XYZ(), 1, P1.XYZ(), P2.XYZ()); Center.ChangeCoord() = 0.5*temp; DCenter.SetLinearForm(myRadius, Dns1, myRadius, Dns2, 1, DP1, DP2); DCenter *= 0.5; D2Center.SetLinearForm(myRadius, D2ns1, myRadius, D2ns2, 1, D2P1, D2P2); D2Center *= 0.5; invnormp = ((Standard_Real)1) / nplan.Magnitude(); nplan *= invnormp; sc = dnplan.Dot(nplan); d2nplan.SetLinearForm( 3*sc*sc*invnormp - d2nplan.Dot(nplan) - invnormp*dnplan.SquareMagnitude(), nplan, -2*sc*invnormp , dnplan, d2nplan); dnplan.SetLinearForm(-sc, nplan, dnplan); dnplan *= invnormp; d2nplan *= invnormp; GeomFill::GetCircle(myTConv, ns1, ns2, Dns1, Dns2, D2ns1, D2ns2, nplan, dnplan, d2nplan, P1, P2, DP1, DP2, D2P1, D2P2, myRadius, 0, 0, Center, DCenter, D2Center, Poles, DPoles, D2Poles, Weigths, DWeigths, D2Weigths); return Standard_True; } Standard_Integer GeomFill_CircularBlendFunc::Nb2dCurves() const { return 0; } void GeomFill_CircularBlendFunc::SectionShape(Standard_Integer& NbPoles, Standard_Integer& NbKnots, Standard_Integer& Degree) const { NbPoles = myNbPoles; NbKnots = myNbKnots; Degree = myDegree; } void GeomFill_CircularBlendFunc::Knots(TColStd_Array1OfReal& TKnots) const { GeomFill::Knots(myTConv, TKnots); } void GeomFill_CircularBlendFunc::Mults(TColStd_Array1OfInteger& TMults) const { GeomFill::Mults(myTConv, TMults); } Standard_Boolean GeomFill_CircularBlendFunc::IsRational() const { return (myTConv != Convert_Polynomial); } Standard_Integer GeomFill_CircularBlendFunc:: NbIntervals(const GeomAbs_Shape S) const { Standard_Integer NbI_Center, NbI_Cb1, NbI_Cb2, ii; NbI_Center = myPath->NbIntervals(GeomFillNextShape(S)); NbI_Cb1 = myCurve1->NbIntervals(S); NbI_Cb2 = myCurve2->NbIntervals(S); TColStd_Array1OfReal ICenter(1, NbI_Center+1); TColStd_Array1OfReal ICb1(1, NbI_Cb1+1); TColStd_Array1OfReal ICb2(1, NbI_Cb2+1); TColStd_SequenceOfReal Inter; myPath->Intervals(ICenter, GeomFillNextShape(S)); myCurve1->Intervals(ICb1, S); myCurve2->Intervals(ICb2, S); /* cout << "Intervals : " << S << endl; cout << "-- Center-> " << endl; for (ii=1; ii<=ICenter.Length(); ii++) cout << " , "<< ICenter(ii); cout << endl; cout << endl; cout << "-- Cb1-> " << endl; for (ii=1; ii<=ICb1.Length(); ii++) cout << " , "<< ICb1(ii); cout << endl; cout << endl; cout << "-- Cb2-> " << endl; for (ii=1; ii<=ICb2.Length(); ii++) cout << " , "<< ICb1(ii); cout << endl; cout << endl;*/ GeomFillFusInt(ICb1, ICb2, Inter); TColStd_Array1OfReal ICbs (1, Inter.Length()); for (ii=1; ii<=ICbs.Length(); ii++) ICbs(ii) = Inter(ii); Inter.Clear(); GeomFillFusInt(ICenter, ICbs, Inter); return Inter.Length()-1; } void GeomFill_CircularBlendFunc:: Intervals(TColStd_Array1OfReal& T, const GeomAbs_Shape S) const { Standard_Integer NbI_Center, NbI_Cb1, NbI_Cb2, ii; NbI_Center = myPath->NbIntervals(GeomFillNextShape(S)); NbI_Cb1 = myCurve1->NbIntervals(S); NbI_Cb2 = myCurve2->NbIntervals(S); TColStd_Array1OfReal ICenter(1, NbI_Center+1); TColStd_Array1OfReal ICb1(1, NbI_Cb1+1); TColStd_Array1OfReal ICb2(1, NbI_Cb2+1); TColStd_SequenceOfReal Inter; myPath->Intervals(ICenter, GeomFillNextShape(S)); myCurve1->Intervals(ICb1, S); myCurve2->Intervals(ICb2, S); GeomFillFusInt(ICb1, ICb2, Inter); TColStd_Array1OfReal ICbs (1, Inter.Length()); for (ii=1; ii<=ICbs.Length(); ii++) ICbs(ii) = Inter(ii); Inter.Clear(); GeomFillFusInt(ICenter, ICbs, Inter); // Recopie du resultat for (ii=1; ii<=Inter.Length(); ii++) T(ii) = Inter(ii); } void GeomFill_CircularBlendFunc::SetInterval(const Standard_Real First, const Standard_Real Last) { Standard_Real Eps = Precision::PConfusion(); myTPath = myPath->Trim(First, Last, Eps); myTCurve1 = myCurve1->Trim(First, Last, Eps); myTCurve2 = myCurve2->Trim(First, Last, Eps); } void GeomFill_CircularBlendFunc::GetTolerance(const Standard_Real BoundTol, const Standard_Real SurfTol, const Standard_Real AngleTol, TColStd_Array1OfReal& Tol3d) const { Standard_Integer low = Tol3d.Lower() , up=Tol3d.Upper(); Standard_Real Tol; Tol= GeomFill::GetTolerance(myTConv, minang, myRadius, AngleTol, SurfTol); Tol3d.Init(SurfTol); Tol3d(low+1) = Tol3d(up-1) = Min(Tol, SurfTol); Tol3d(low) = Tol3d(up) = Min(Tol, BoundTol); } void GeomFill_CircularBlendFunc::SetTolerance(const Standard_Real, const Standard_Real) { // y rien a faire ! } gp_Pnt GeomFill_CircularBlendFunc::BarycentreOfSurf() const { return myBary; } Standard_Real GeomFill_CircularBlendFunc::MaximalSection() const { return maxang*myRadius; } void GeomFill_CircularBlendFunc:: GetMinimalWeight(TColStd_Array1OfReal& Weigths) const { GeomFill::GetMinimalWeights(myTConv, minang, maxang, Weigths); }