我试图在两个代表射弹路径的点之间画一条弧。射弹离开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坐标吗?
答案 0 :(得分:4)
在评论之后,我们需要一个二次贝塞尔曲线。这由3个点,开始,结束和控制点定义:
由以下等式定义:
因此,我们需要使用给定的条件找到P1
(请注意,重力强度是隐式确定的)。对于2D坐标,我们需要两个约束/边界条件。它们由:
P0
处的切线向量:
我们需要将角度与水平线匹配:
曲线的顶点必须直接位于控制点P1
下方:
因此垂直坐标由下式给出:
[如果您想要上面的示例代码,请告诉我们]
现在如何添加二次贝塞尔曲线;谢天谢地,一旦你完成了上述工作,它就是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
我们可以认为是恒定的,所以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))
或者
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))
还有你的抛物线方程式。画出它,然后看到你的镜头达到了标记。
我已经给它一个物理解释因为我觉得它更容易理解,但是你可以将我在这里写的所有名字改为纯粹的数学术语,它并不重要,一天结束时,它的所有数学和抛物线都是一样的,你想要考虑它的任何方式。