基于已知的抛射角在两点之间绘制抛物线弧

时间:2018-02-03 21:16:02

标签: c# wpf math geometry coordinates

我试图在两个代表射弹路径的点之间画一条弧。射弹离开A点的角度是已知的,两点的X / Y坐标都是已知的。

enter image description here

我试图弄清楚这背后的数学,以及如何在c#中绘制它。

根据我找到的一些路径示例,这是我失败的尝试

var g = new StreamGeometry();
var xDistance = Math.Abs(pointA.X - pointB.X);
var yDistance = Math.Abs(pointA.Y - pointB.Y);
var angle = 60;
var radiusX = xDistance / angle;
var radiusY = yDistance / angle;

using (var gc = g.Open())
{
    gc.BeginFigure(
        startPoint: pointA,
        isFilled: false,
        isClosed: false);

    gc.ArcTo(
        point: pointB,
        size: new Size(radiusX, radiusY),
        rotationAngle: 0d,
        isLargeArc: false,
        sweepDirection: SweepDirection.Clockwise,
        isStroked: true,
        isSmoothJoin: false);
}

非常感谢任何帮助!

编辑#2(增加清晰度):对于这个问题,假设物理不起作用(没有重力,速度或任何外力)。保证射弹落在B点并沿着抛物线路径移动。顶点将位于水平轴上的点A和点B之间。它发射的角度是离地面的角度(水平)。

所以A点(Ax,Ay)是众所周知的。 B点(Bx,By)是已知的。 出发的角度是已知的。 顶点的X半部分是已知的(Vx = Abs(Ax-Bx))。

这真的归结为需要弄清楚顶点的Y坐标吗?

2 个答案:

答案 0 :(得分:4)

在评论之后,我们需要一个二次贝塞尔曲线。这由3个点,开始,结束和控制点定义:

enter image description here

由以下等式定义:

enter image description here

因此,我们需要使用给定的条件找到P1(请注意,重力强度是隐式确定的)。对于2D坐标,我们需要两个约束/边界条件。它们由:

给出
  1. P0处的切线向量:

    enter image description here

    我们需要将角度与水平线匹配:

    enter image description here

  2. 曲线的顶点必须直接位于控制点P1下方:

    enter image description here

  3. 因此垂直坐标由下式给出:

    enter image description here

    [如果您想要上面的示例代码,请告诉我们]

    现在如何添加二次贝塞尔曲线;谢天谢地,一旦你完成了上述工作,它就是not too difficult

    以下方法为简单对称情况创建抛物线几何。角度是从水平方向逆时针测量的度数。

    public Geometry CreateParabola(double x1, double x2, double y, double angle)
    {
        var startPoint = new Point(x1, y);
        var endPoint = new Point(x2, y);
    
        var controlPoint = new Point(
            0.5 * (x1 + x2),
            y - 0.5 * (x2 - x1) * Math.Tan(angle * Math.PI / 180));
    
        var geometry = new StreamGeometry();
    
        using (var context = geometry.Open())
        {
            context.BeginFigure(startPoint, false, false);
            context.QuadraticBezierTo(controlPoint, endPoint, true, false);
        }
    
        return geometry;
    }
    

答案 1 :(得分:2)

可以通过以下等式评估仅受重力影响的身体运动(忽略空气阻力):

DistanceX(t) = dx0 + Vx0·t
DistanceY(t) = dy0 + Vy0·t - g/2·t^2

其中

g      : gravity acceleration (9.8 m/s^2)
dx0    : initial position in the X axis
dy0    : initial position in the Y axis
Vy0    : initial X velocity component (muzzle speed)
Vy0    : initial Y velocity component (muzzle speed)

嗯,这似乎没有什么帮助,但让我们进一步调查。你的大炮的枪口速度V我们可以认为是恒定的,所以Vx0Vy0可以写成:

Vx0 = V·cos(X)
Vy0 = V·sin(X)

X是你射击的角度。好吧,这似乎很有趣,我们终于有一个输入对任何射击大炮的人都有用:X。让我们回到我们的方程并重写它们:

DistanceX(t) = dx0 + V·cos(X)·t
DistanceY(t) = dy0 + V·sin(X)·t - g/2·t^2

现在,让我们思考一下我们要做的事情。我们想找到一种方法来达到特定点P。让我们给它坐标:(A, B)。为了做到这一点,射弹必须同时在两个投影中达到这一点。我们打电话给那个时间T。好的,让我们再次重写我们的方程式:

A = dx0 + V·cos(X)·T
B = dy0 + V·sin(X)·T - g/2·T^2

让我们摆脱一些不必要的常数;如果我们的大炮位于(0, 0)我们的方程现在是:

A = V·cos(X)·T [1]
B = V·sin(X)·T - g/2·T^2 [2]

从[1]我们知道:T = A/(V·cos(X)),所以我们在[2]中使用它:

B = V·sin(X)·A/(V·cos(X)) - g/2·A^2/(V^2·cos^2(X))

或者

B = A·tan(X) - g/2·A^2/(V^2*cos^2(X))

现在一些三角函数会告诉你1/cos^2 = 1 + tan^2所以:

B = A·tan(X) - g/2·A^2/V^2·(1+tan^2(X)) [3]

现在你可以解决tan(X)中的二次方程式。

免责声明:输入数学有点困难,我可能会在某处出错,但你应该明白这一点。

更新上一种方法可以让您在给定枪口速度X时解决达到目标P的角度V。根据你的评论,给出角度X,所以你需要弄清楚的是枪口速度会使射弹以指定的炮角击中目标。如果它让你更舒服,不要将V视为枪口速度,可以把它想象成你试图找到的抛物线的一个形状因素。

在[3]中解决V

B = A·tan(X) - g/2·A^2/V^2·(1+tan^2(X))

这是一个简单的二次方程式,只是孤立V并取平方根。显然负根没有物理意义,但它也可以,你可以采取任何两种解决方案。如果V没有实数解,那就意味着没有可能的射击(或抛物线)达到P(角度X太大;想象你直接射击起来,你会打击自己,别的什么。)

现在简单地消除参数化方程中的t

x = V·cos(X)·t [4]
y = V·sin(X)·t - g/2·t^2 [5]

从[4]你有t = x/(V·cos(X))。替代[5]:

y = tan(X)·x - g·x^2 /(2·V^2*cos^2(X))

还有你的抛物线方程式。画出它,然后看到你的镜头达到了标记。

我已经给它一个物理解释因为我觉得它更容易理解,但是你可以将我在这里写的所有名字改为纯粹的数学术语,它并不重要,一天结束时,它的所有数学和抛物线都是一样的,你想要考虑它的任何方式。