using System; using CaeKnowledge.Data; using ToolPathParser; namespace CaeCuttingForce.FlatendCutter { public class LineForce { private const double PI = Math.PI; private const double AngularIncrement = 0.006; // h1 private const double AxialIncrement = 0.006; // da public void CalculateCuttingForce(int direction, ToolPosition position, CuttingForceCoefficients coefficients, ToolParameters toolParams) { // 刀具参数 int N = toolParams.NumberOfTeeth; // 刀齿数 N double RAD = toolParams.ToolRadius; // 刀具半径 RAD double beta = toolParams.HelixAngle; // 刀具螺旋角 beta double Ap = position.AxialDepth; // 轴向切削深度 Ap double Ae = position.RadialDepth; // 径向切削深度 Ae double nrot = position.SpindleSpeed; // 主轴转速 n double fd = position.FeedRate; // 进给速度 fd // 计算中间变量 double thetaPit = 2.0 * PI / N; // 齿间角 double kb = Math.Tan(beta * PI / 180.0) / RAD; // 刀具常数 double c = fd / (nrot * N); // 每齿进给量 // 计算切入角和切出角 double thetaSt = Math.Asin(1 - Ae / RAD); // 切入角 double thetaEx = 0.5 * PI; // 切出角 // 计算角向和轴向积分数目 int K = (int)Math.Floor(2.0 * PI / AngularIncrement); // 角向积分步数 int L = (int)Math.Floor(Ap / AxialIncrement); // 轴向积分步数 // 初始化结果数组 double[] Fx = new double[K]; double[] Fy = new double[K]; double[] Fz = new double[K]; double[] Fx_global = new double[K]; double[] Fy_global = new double[K]; double[] Fz_global = new double[K]; int M = L * N * K; double[] Px = new double[M]; double[] Qx = new double[M]; double[] h = new double[M]; double[] R1 = new double[N * K]; int m = 0; int n = 0; // 主计算循环 for (int i = 0; i < K; i++) { double R_val = i * AngularIncrement; // 螺旋槽底部切削刃的接触角 for (int k = 0; k < N; k++) { R1[n] = R_val + k * thetaPit; // 第k个齿当前角度的位置 double R2 = R1[n]; for (int j = 0; j < L; j++) { double alph = (j + 1) * AxialIncrement; R2 = R1[n] - kb * alph; // 角度规范化到 [0, 2π] while (R2 > 2.0 * PI) R2 -= 2.0 * PI; while (R2 < 0) R2 += 2.0 * PI; //R3[m] = R2; // 计算Px和Qx Px[m] = (RAD - Ae) / Math.Tan(R2); double Ox = RAD * Math.Cos(thetaSt) - c; Qx[m] = (RAD - c * Math.Cos(R2)) * Math.Cos(R2); if (R2 >= thetaSt && R2 <= thetaEx) { // 切削厚度计算 if (Px[m] >= Ox) { h[m] = RAD - (RAD - Ae) / Math.Sin(R2); } else if (Qx[m] < Ox) { h[m] = c * Math.Cos(R2); } // 计算微分切削力 double dft = (coefficients.ktc * h[m] + coefficients.kte) * AxialIncrement; double dfr = (coefficients.krc * h[m] + coefficients.kre) * AxialIncrement; double dfu = (coefficients.kuc * h[m] + coefficients.kue) * AxialIncrement; if (direction == 1) { // 坐标变换矩阵 double[,] T = { { Math.Sin(R2), -Math.Cos(R2), 0 }, { Math.Cos(R2), Math.Sin(R2), 0 }, { 0, 0, 1 } }; double fxComponent = T[0, 0] * dft + T[0, 1] * dfr + T[0, 2] * dfu; double fyComponent = T[1, 0] * dft + T[1, 1] * dfr + T[1, 2] * dfu; double fzComponent = T[2, 0] * dft + T[2, 1] * dfr + T[2, 2] * dfu; Fx[i] += fxComponent; Fy[i] += fyComponent; Fz[i] += fzComponent; } else if (direction == 2) { // 坐标变换矩阵 double[,] T = { { Math.Sin(R2), -Math.Cos(R2), 0 }, { Math.Cos(R2), Math.Sin(R2), 0 }, { 0, 0, -1 } }; double fxComponent = T[0, 0] * dft + T[0, 1] * dfr + T[0, 2] * dfu; double fyComponent = T[1, 0] * dft + T[1, 1] * dfr + T[1, 2] * dfu; double fzComponent = T[2, 0] * dft + T[2, 1] * dfr + T[2, 2] * dfu; Fx[i] += fxComponent; Fy[i] += fyComponent; Fz[i] += fzComponent; } m++; } } n++; } if (direction == 1) { // 坐标转换到工件坐标系 Fx_global[i] = Fy[i]; Fy_global[i] = -Fx[i]; Fz_global[i] = Fz[i]; } else if (direction == 2) { // 坐标转换到工件坐标系 Fx_global[i] = Fy[i]; Fy_global[i] = Fx[i]; Fz_global[i] = -Fz[i]; } } // 计算并设置结果 SetResults(position, Fx_global, Fy_global, Fz_global, K); } private void SetResults(ToolPosition position, double[] Fx_global, double[] Fy_global, double[] Fz_global, int K) { // 计算平均值 double sumFx = 0, sumFy = 0, sumFz = 0; for (int i = 0; i < K; i++) { sumFx += Fx_global[i]; sumFy += Fy_global[i]; sumFz += Fz_global[i]; } double aFx = sumFx / K; double aFy = sumFy / K; double aFz = sumFz / K; // 设置结果到position对象 position.AverageFx = aFx; position.AverageFy = aFy; position.AverageFz = aFz; // 计算最大值 double maxFx = 0, maxFy = 0, maxFz = 0; for (int i = 0; i < K; i++) { if (Math.Abs(Fx_global[i]) > Math.Abs(maxFx)) maxFx = Fx_global[i]; if (Math.Abs(Fy_global[i]) > Math.Abs(maxFy)) maxFy = Fy_global[i]; if (Math.Abs(Fz_global[i]) > Math.Abs(maxFz)) maxFz = Fz_global[i]; } position.MaxFx = maxFx; position.MaxFy = maxFy; position.MaxFz = maxFz; } } }