给定:
时间0,目标在点A,拦截器在点B。在未来的某个时间点,它们将在点C相交。
线段a位于点A的对面,同理b和B,c和C。
我们已知A和B的位置。我们可以从目标的航向推导出角度CAB。我们知道线段a和线段b的长度比为(拦截器速度/目标速度)。
首先,找到角度CAB。
让向量B ^等于目标的速度。
让向量C ^等于(拦截器位置.x-目标位置.x,拦截器位置.y-目标位置.y)。
使用点积公式确定它们之间的角度。
B dot C = ||B|| * ||C|| * cos(angle)
cos(angle) = (B dot C) / (||B|| * ||C||)
angle = arccos((B dot C) / (||B|| * ||C||))
在这里,“dot”是点积,||B||是向量B的标量大小。角度angle
为CAB角。
现在我们来找到角度ABC。
使用正弦定律,我们知道sin(ABC) / b == sin(CAB) / a
。
将方程重排成ABC = arcsin( sin(CAB) * (b/a) )
。
我们在上一步找到了CAB,我们知道b/a为target.speed/interceptor.speed,所以将这些值代入并找到ABC。
现在你知道了两个角度和两个点,应该能够推导出C的位置。如果你使用度数,则角度ACB等于180 -(CAB + ABC),如果你使用弧度,则等于Pi -(CAB + ABC)。使用正弦定律确定边b和c的长度。现在可以用T = b / target.speed
找到T,并用C = target.position + (target.velocity * T)
找到C。
我的C#有点生疏,因此这里提供了一个Python示例实现。让我们插入你的样本值,结果是:
Collision pos: Point(163.065368246, 57.2261472985)
Time: 8.61307364926
Angle A: 113.198590514
Angle B: 29.6680851288
Angle C: 37.1333243575
a: 86.1307364926
b: 46.3828210973
c: 56.5685424949
位置和时间与gdir发现的相同,因此我非常有信心,我们两种方法都有效。
编辑:MikeT:C#版本
public static double Dot(Vector a, Vector b)
{
return a.X * b.X + a.Y * b.Y;
}
public static double Magnitude(Vector vec)
{
return Math.Sqrt(vec.X * vec.X + vec.Y * vec.Y);
}
public static double AngleBetween(Vector b, Vector c)
{
return Math.Acos(Dot(b, c) / (Magnitude(b) * Magnitude(c)));
}
public static Vector? Find_collision_point(Point target_pos, Vector target_vel, Point interceptor_pos, double interceptor_speed)
{
var k = Magnitude(target_vel) / interceptor_speed;
var distance_to_target = Magnitude(interceptor_pos - target_pos);
var b_hat = target_vel;
var c_hat = interceptor_pos - target_pos;
var CAB = AngleBetween(b_hat, c_hat);
var ABC = Math.Asin(Math.Sin(CAB) * k);
var ACB = (Math.PI) - (CAB + ABC);
var j = distance_to_target / Math.Sin(ACB);
var a = j * Math.Sin(CAB);
var b = j * Math.Sin(ABC);
var time_to_collision = b / Magnitude(target_vel);
var collision_pos = target_pos + (target_vel * time_to_collision);
return interceptor_pos - collision_pos;
}