我想计算射线和线段之间的交点.为此,我形成了线性方程并寻找一个交点.现在,我遇到一个数值问题的例子.我的代码的缩写:
public class Test {
public static void main(String[] args) {
double rayAX = 443.19661703858895d;
double rayAY = 666.3485960845833d;
double rayBX = 443.196744279195d;
double rayBY = 103.21654864924565d;
double segAX = 450.0d;
double segAY = 114.42801992127828d;
double segBX = 443.196744279195d;
double segBY = 103.21654864924565d;
double a1 = (rayBY - rayAY) / (rayBX - rayAX);
double t1 = rayAY - rayAX * a1;
double a2 = (segBY - segAY) / (segBX - segAX);
double t2 = segAY - segAX * a2;
double x = (t2 - t1) / (a1 - a2);
double y = a1 * x + t1;
System.out.println(x);
System.out.println(y);
}
}
显然,返回值应为(443.196744279195,103.21654864924565),因为射线和线段上的这一点相同.
但实际回报率以我为例(443.19674427919506,103.21654844284058)
在第二个数字中,小数点后第六位已经有一个错误.
我猜错是因为值rayAX和rayBX彼此非常接近.我的问题是:计算交点时可以得到更精确的结果吗?
解决方法:
这是一种在数值上更稳定的相交方式(请注意,它实际上是两条线的相交……似乎您的原始代码也没有检查相交是否也在线段内):
double rX = rayBX - rayAX;
double rY = rayBY - rayAY;
double sAX = segAX - rayAX;
double sAY = segAY - rayAY;
double areaA = sAX * rY - sAY * rX;
double sBX = segBX - rayAX;
double sBY = segBY - rayAY;
double areaB = sBX * rY - sBY * rX;
double t = areaA / (areaA - areaB);
// if t is not between 0 and 1, intersection is not in segment
double x = (1 - t) * segAX + t * segBX;
double y = (1 - t) * segAY + t * segBY;
粗略的解释:假设A和B为射线的端点,让X和Y为线段的端点.令P为我们要寻找的交点.然后,PX与PY之比等于ABX面积与ABY面积之比.您可以使用叉积计算面积,即上面的代码正在执行的操作.请注意,此过程如何仅使用一个除法,这有助于最小化数值的不稳定性.