【问题标题】:Algorithm to Calculate the path of a parabola utilizing a 2 axis movement利用 2 轴运动计算抛物线路径的算法
【发布时间】:2016-03-21 16:11:00
【问题描述】:

关于附图,我需要一个计算算法来将轴 A 向下移动 n 英寸,并将轴 B 从左向右移动 m 英寸,以便组件圆 D 遵循抛物线的曲线;圆 D 并不总是 10 英寸,可以更小。我不是数学专业的,所以这对我来说有点复杂。我知道我在 A 轴上有一个必须计算的弧长(我不知道如何做到这一点。),然后我在 B 轴上也有一个弧长,并且弧相对于位置移动轴 A,与圆 D 的直径相关联的弧长将确定圆 D 和抛物线之间的交点在抛物线上的哪个位置。为了遵循从左到右的抛物线曲线,反之亦然 - 我需要一个公式来遵循抛物线。考虑 D 变化的大小。有人可以提供一些关于如何做到这一点的答案吗?一个很好的公式,带有一些解释性信息 - 至少足够详细,我可以对这些部分和位进行搜索以了解要做什么。

I have looked and found some information that may be helpful to me but does not answer my question at all: https://stackoverflow.com/questions/4039039/fastest-way-to-fit-a-parabola-to-set-of-points

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    看来你需要计算得到的曲线作为抛物线的偏移量。

    在下面的 C++ 程序中,我将展示如何首先找到抛物线的公式,然后如何计算与该曲线的偏移量,最后如何找到两个轴彼此形成的角度。

    我将点 (0,0) 视为抛物线的左极点,该点(顶点)的底部将位于坐标 (12,-8.75) 处,而右极点位于 (24,0) 处。以这张图为参考(抛物线为蓝色,圆心轨迹为橙色):

    请注意,如果圆太大,当它在一侧相切时,它可能与另一侧的抛物线相交。我不确定 12" 是抛物线的总宽度还是只有一半,但在后一种情况下,10" 工具会太大:

    程序会打印出代表刀具的圆与抛物线相切的点坐标的一些样本(25),相应的圆心坐标(刀具的位置)和角度两个轴(alpha 和 beta)。

    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <cmath>
    
    using std::cout;
    using std::setw;
    using std::vector;
    
    int main() {
    
        // set number of steps or points of approximation
        int n_steps = 25;
    
        // declare vectors to store coordinates into
        vector<double> x2(n_steps), y2(n_steps);
    
        // calculate the parameters of the parabola expressed by the formula 
        // y = ax^2 + bx + c
        // Knowing 2 points, one of which is the vertex.
        // xv = -b/2a               | b = -2axv   
        // y0 = ax0^2 + bx0 + c  => | yv - y0 = a(xv^2 - x0^2) + b(xv - x0)
        // yv = axv^2 + bxv + c     | yv - y0 = a(xv - x0)(xv + x0) + b(xv - x0)
        // 
        // a ((xv - x0)*(xv + x0) - 2xv(xv - x0)) = yv - y0
        // a (xv - x0)*(xv + x0 - 2xv) = yv - y0
    
        // Known coordinates
        double  xv = 12.0,
                yv = -8.75,
                x0 = 0.0,
                y0 = 0.0; 
    
        double  dx = xv - x0,
                a = (y0 - yv) / ( dx * dx ),
                b = - 2.0 * a * xv,
                c = y0 - x0 * ( a * x0 + b );
    
        cout << "Parabola formula:\n" 
             << "y = " << a << "x^2 + " << b << "x + " << c << "\n\n"
             << "max acceptable diameter: " << 1.0 / a << "\n\n";
    
        // Coordinates of rotating axes, extrapolated from your drawing
        double  r1 = 13,
                r2 = 9,
                x1 = xv - r1,
                y1 = r2;
        // some helper values (constant) I'll use later
        double  rad_to_deg = 180.0 / M_PI,
                r1quad = r1 * r1,
                r2quad = r2 * r2,
                rdif = r1quad - r2quad,
                rsum = r1quad + r2quad,
                rden = 1.0 / ( 2.0 * r1 * r2 );
    
        // radius of the circle (tool)
        double  diameter = 10,
                radius = diameter / 2.0;
        cout << "Diameter of tool (circle): " << diameter << "\n\n";
    
    
        // calculate parabola points
        cout << "\t\t\tTangent\t\t\t\tCenter of circle\t\t  alpha\t\tbeta\n";
        // xt[0] = x0    xt[n_steps] = x0 + 2*(xv - x0)
        double step = 2.0 * dx / ( n_steps - 1 );
        for ( int i = 0; i < n_steps; ++i ) {
            // calculate the tangent points which lies on the parabola
            double  xt = x0 + i * step,
                    yt = xt * ( a * xt + b ) + c;
    
            // calculate the offset points, coordinates of the center of the circle
            // first derivative of the parabola
            double delta = 2.0 * a * xt + b;
    
            // point perpendicular to the tangent at distance equal to radius
            double k = radius / sqrt(delta * delta + 1.0);
            x2[i] = xt - k * delta;
            y2[i] = yt + k;
    
            // distance from x,y to x1,y1
            double  dx1 = x2[i] - x1,
                    dy1 = y2[i] - y1,
                    r3quad = dx1 * dx1 + dy1 * dy1,
                    r3 = sqrt(r3quad);
    
            // Now that I know the coordinates of the vertices of the triangle 
            // and the lengths of its sides I can calculate the inner angles
            // using Carnot teorem, for example: a^2 = b^2 + c^2 - 2bc*cos(alpha)
            double alpha_Carnot = acos((rdif + r3quad) / (2.0 * r1 * r3)),
                    beta_Carnot = acos((rsum - r3quad) * rden);
    
            // angle to the orizzontal of line from x1,y1 to x,y in radians
            double  gamma = atan2(dy1,dx1);
            // angle of Axis A to the orizzontal in degrees
            double  alpha = (gamma + alpha_Carnot) * rad_to_deg;
            // angle of Axis B to Axis A. beta = 0 if parallel
            double  beta = beta_Carnot * rad_to_deg - 180.0;
    
            // output the coordinates
            cout << std::fixed << setw(4) << i << setw(10) << xt << setw(10) << yt
                 << setw(15) << x2[i] << setw(10) << y2[i]
                 << setw(15) << alpha << setw(12) << beta << '\n';
        }
    
        return 0;
    }
    

    这是输出:

    Parabola formula:
    y = 0.0607639x^2 + -1.45833x + 0
    
    max acceptable diameter: 16.4571
    
    Diameter of tool (circle): 10
    
                Tangent             Center of circle          alpha     beta
       0  0.000000  0.000000       4.123644  2.827642      -7.228866 -142.502245
       1  1.000000 -1.397569       5.003741  1.597437      -7.151211 -132.856051
       2  2.000000 -2.673611       5.860925  0.503378      -7.962144 -123.965745
       3  3.000000 -3.828125       6.690144 -0.454279      -9.159057 -115.700562
       4  4.000000 -4.861111       7.485392 -1.276137     -10.496232 -108.022957
       5  5.000000 -5.772569       8.239777 -1.964178     -11.833367 -100.941141
       6  6.000000 -6.562500       8.945861 -2.522462     -13.081185  -94.488527
       7  7.000000 -7.230903       9.596439 -2.957906     -14.180211  -88.708034
       8  8.000000 -7.777778      10.185964 -3.280939     -15.093523  -83.633631
       9  9.000000 -8.203125      10.712644 -3.505588     -15.805504  -79.267662
      10 10.000000 -8.506944      11.180897 -3.648397     -16.321003  -75.558850
      11 11.000000 -8.689236      11.603201 -3.725755     -16.659970  -72.392050
      12 12.000000 -8.750000      12.000000 -3.750000     -16.845543  -69.600878
      13 13.000000 -8.689236      12.396799 -3.725755     -16.889440  -67.003199
      14 14.000000 -8.506944      12.819103 -3.648397     -16.782985  -64.443028
      15 15.000000 -8.203125      13.287356 -3.505588     -16.499460  -61.816277
      16 16.000000 -7.777778      13.814036 -3.280939     -16.005878  -59.069041
      17 17.000000 -7.230903      14.403561 -2.957906     -15.277444  -56.174060
      18 18.000000 -6.562500      15.054139 -2.522462     -14.309495  -53.098717
      19 19.000000 -5.772569      15.760223 -1.964178     -13.126180  -49.773973
      20 20.000000 -4.861111      16.514608 -1.276137     -11.788732  -46.064496
      21 21.000000 -3.828125      17.309856 -0.454279     -10.409278  -41.729113
      22 22.000000 -2.673611      18.139075  0.503378      -9.184425  -36.337384
      23 23.000000 -1.397569      18.996259  1.597437      -8.503984  -29.006402
      24 24.000000  0.000000      19.876356  2.827642      -9.577076  -16.878208
    

    这些是不同位置的一些图片(感谢excell):

    【讨论】:

    • 你的点 left {0,0} , vertex , right {24,0} 也符合我的做法。 12 英寸是抛物线的最大宽度,我需要将 A 轴向下旋转,然后将 B 轴旋转以跟随抛物线的路径。鉴于圆直径可以从最大 10 英寸变为最小 7 英寸。 delta[Axis A], delta[Axis B] + (10 - delta[Circle Diameter]) = 抛物线路径上的点。请参阅第二个回复,因为这里没有足够的空间来完成。
    • 圆心的两个数字我不确定代表是什么;沿切线以英寸为单位的直线上的点?在您的方程式中,看起来我应该做的是将圆心定位在距切点 1/2 圆直径的位置;您的回答正在帮助我更好地解决问题,并更好地定义如何达到预期的结果;即旋转 A 轴和 B 轴以将圆的中心定位到圆的 1/2 直径。这对我来说不再是漆黑,更像是满月;也许我可以在这里开始看到太阳升起。 :-)
    • @StixO 角度计算已添加,并带有一些描述性图片。告诉我是否可以。
    • @Bob__ 您使用哪个软件或工具来创建和说明数学绘图;)顺便说一句,不错的答案得到了我的投票
    • @maytham-ɯɐɥʇʎɐɯ Excell ;).
    【解决方案2】:

    抛物线ax^2+bx+c的斜率为2ax+b

    要找到圆具有特定斜率值的位置 (s),您有 y/x = s。结合方程x^2+y^2=r^2(您可能想要圆的下半部分,顺便说一句),您可以看到相对于圆心,圆的边缘将与抛物线接触的位置。

    所以如果圆心到抛物线点的距离和圆心到切点的距离不同,就需要移动轴了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-16
      • 2021-12-10
      • 2016-06-02
      • 2010-11-11
      相关资源
      最近更新 更多