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

C# 基于已知抛射角在两点之间绘制抛物线弧,c#,wpf,math,geometry,coordinates,C#,Wpf,Math,Geometry,Coordinates,我试着在两个点之间画一条弧线,代表一个投射物的路径。弹丸离开点A的角度已知,两个点的X/Y坐标已知 我正试图弄明白这背后的数学原理,以及如何用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 radiu

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

我正试图弄明白这背后的数学原理,以及如何用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坐标吗

仅受重力影响的身体运动(忽略空气阻力)可通过以下方程式进行计算:

DistanceX(t) = dx0 + Vx0·t
DistanceY(t) = dy0 + Vy0·t - g/2·t^2
x = V·cos(X)·t [4]
y = V·sin(X)·t - g/2·t^2 [5]
在哪里

这似乎不是很有帮助,但让我们进一步调查。你的大炮有炮口速度<代码> V <代码>我们可以考虑常量,所以<代码> Vx0和<代码> VY0可以写成:

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

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

B = A·tan(X) - g/2·A^2/V^2·(1+tan^2(X)) [3]
现在你们有了,tan(X)中的二次方程,你们可以解

免责声明:输入数学有点难,我可能在某个地方有错误,但你应该明白

更新之前的方法将允许您在给定初速
V
的情况下求解击中目标
p
的角度
X
。根据您的评论,给出了角度
X
,因此您需要计算出炮弹以指定的加农炮角度击中目标的初速。如果它让你感觉更舒服,不要把
V
看作是枪口的初速,把它看作是你试图找到的抛物线的形状因子

求解[3]中的
V

B = A·tan(X) - g/2·A^2/V^2·(1+tan^2(X))
这是一个平凡的二次方程,只需隔离
V
并取平方根。显然,负根没有物理意义,但它也有物理意义,你可以取两个解中的任何一个。如果对
V
没有实数解,那就意味着根本没有可能达到
P
的射程(或抛物线)(角度
X
太大;想象你直接向上射程,你会击中自己,其他什么都不会)

现在只需在参数化方程中消除
t

DistanceX(t) = dx0 + Vx0·t
DistanceY(t) = dy0 + Vy0·t - g/2·t^2
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))
这是你的抛物线方程。画出来,看你的投篮命中目标


我给了它一个物理解释,因为我发现它更容易理解,但你可以把我在这里写的所有名字都改成纯数学术语,这其实并不重要,一天结束时,所有的数学和抛物线都是一样的,不管你想怎么想。

下面是评论,我们需要一条二次贝塞尔曲线。这由3个点定义,即起点、终点和控制点:

它由以下等式定义:

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

  • P0处的切线向量:

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

  • 曲线的顶点必须在控制点P1的正下方:

  • 因此,垂直坐标由下式给出:

    [如果您需要上述示例代码,请告知我]


    现在学习如何添加二次贝塞尔;谢天谢地,一旦你完成了上面的工作,它就是


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

    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;
    }
    

    重力能被假定为垂直且恒定的吗?此外,与水平方向的角度还是垂直方向的角度
    ArcTo
    绘制一条圆弧,而自由下落的粒子在均匀重力下会沿着抛物线路径。是的,重力可以假定为垂直且恒定的。角度将从水平面向上。根据我失败的尝试,ArcTo是一个圆弧,而不是我所需要的,这是有道理的。我不知道如何得到抛物线路径。我没有检查你的方程,但无论如何,这似乎是正确的方法。嗯,我现在意识到我最初的问题没有我想的那么清楚。通过提到恒定的重力,我试图传达,确实没有外力影响抛射体。为了解决这个问题,可以认为只需要找出顶点的Y坐标