利用2轴运动计算抛物线路径的算法

时间:2016-03-21 16:11:01

标签: algorithm

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

2 Axis With Circle to follow Path of Parabola

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

2 个答案:

答案 0 :(得分:2)

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

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

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

enter image description here

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

enter image description here

程序将打印出一些样本(25)的坐标,其中代表工具的圆与抛物线相切,圆心的相应坐标(工具的位置)和角度两轴(α和β)。

#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):

enter image description here enter image description here enter image description here

答案 1 :(得分:0)

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

要查找圆圈具有特定斜率值(s)的位置,您需要y/x = s。连同等式x^2+y^2=r^2(您可能想要圆的下半部分,顺便说一句),您可以看到相对于圆心的位置,圆的边缘将触及抛物线。

因此,如果圆心和抛物线点之间的距离与圆心和切点之间的距离不同,则需要移动轴。