Java 直线与垂线相交的精度
我使用以下函数计算两条直线的交点:Java 直线与垂线相交的精度,java,line-intersection,Java,Line Intersection,我使用以下函数计算两条直线的交点: // Functions of lines as per requested: // f(y1) = starty1 + x * d1 // f(y2) = starty2 + x * d2 // x1 and y1 are the coordinates of the first point // x2 and y2 are the coordinates of the second point // d1 and d2 are the deltas of
// Functions of lines as per requested:
// f(y1) = starty1 + x * d1
// f(y2) = starty2 + x * d2
// x1 and y1 are the coordinates of the first point
// x2 and y2 are the coordinates of the second point
// d1 and d2 are the deltas of the corresponding lines
private static double[] intersect(double x1, double y1, double d1, double x2, double y2, double d2) {
double starty1 = y1 - x1 * d1;
double starty2 = y2 - x2 * d2;
double rx = (starty2 - starty1) / (d1 - d2);
double ry = starty1 + d1 * rx;
tmpRes[0] = rx;
tmpRes[1] = ry;
return tmpRes;
}
// This is the same function, but takes 4 points to make two lines,
// instead of two points and two deltas.
private static double[] tmpRes = new double[2];
private static double[] intersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
double d1 = (y1 - y2) / (x1 - x2);
double d2 = (y3 - y4) / (x3 - x4);
double starty1 = y1 - x1 * d1;
double starty2 = y3 - x3 * d2;
double rx = (starty2 - starty1) / (d1 - d2);
double ry = starty1 + d1 * rx;
tmpRes[0] = rx;
tmpRes[1] = ry;
return tmpRes;
}
然而,随着d1或d2变得更大(对于垂直线),结果变得更不准确。我怎样才能防止这种情况发生
对于我的例子,我有两条相互垂直的线。如果线旋转45度,我会得到准确的结果。如果直线处于0或90度,我会得到不准确的结果(交点的一个轴是正确的,另一个轴到处都是)
编辑
使用叉积:
private static double[] crTmp = new double[3];
public static double[] cross(double a, double b, double c, double a2, double b2, double c2){
double newA = b*c2 - c*b2;
double newB = c*a2 - a*c2;
double newC = a*b2 - b*a2;
crTmp[0] = newA;
crTmp[1] = newB;
crTmp[2] = newC;
return crTmp;
}
public static double[] linesIntersect(double x1, double y1, double d1, double x2, double y2, double d2)
{
double dd1 = 1.0 / d1;
double dd2 = 1.0 / d2;
double a1, b1, a2, b2, c1, c2;
if (Math.abs(d1) < Math.abs(dd1)) {
a1 = d1;
b1 = -1.0;
c1 = y1 - x1 * d1;
} else {
a1 = 1.0;
b1 = dd1;
c1 = -x1 - y1 * dd1;
}
if (Math.abs(d2) < Math.abs(dd2)) {
a2 = d2;
b2 = -1.0;
c2 = y2 - x2 * d2;
} else {
a2 = 1.0;
b2 = dd2;
c2 = -x2 - y2 * dd2;
}
double[] v1 = {a1, b1, c1};
double[] v2 = {a2, b2, c2};
double[] res = cross(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2]);
tmpRes[0] = res[0] / res[2];
tmpRes[1] = res[1] / res[2];
return tmpRes;
}
private static double[]crTmp=new double[3];
公共静态双[]交叉(双a、双b、双c、双a2、双b2、双c2){
双newA=b*c2-c*b2;
双纽=c*a2-a*c2;
双新c=a*b2-b*a2;
crTmp[0]=newA;
crTmp[1]=新的;
crTmp[2]=newC;
返回crTmp;
}
公共静态双[]线接口(双x1、双y1、双d1、双x2、双y2、双d2)
{
双dd1=1.0/d1;
双dd2=1.0/d2;
双a1、b1、a2、b2、c1、c2;
if(数学绝对值(d1)<数学绝对值(dd1)){
a1=d1;
b1=-1.0;
c1=y1-x1*d1;
}否则{
a1=1.0;
b1=dd1;
c1=-x1-y1*dd1;
}
if(数学abs(d2)
如果使用同构表示法,则最简单:
- 将线条表示法从
更改为y=d*x+c
(其中d*x - y + c = 0 = [d -1 c] . [x y 1]
表示内积) - 使用此符号,您可以将行写成两个向量:
和[d1-1y1]
[d2-1y2]
- 取这两个向量的叉积,得到一个新向量:
(我将让您查看如何计算叉积,但它只是简单的乘法)[d1 -1 y1] x [d2 -1 y2] = [a b c]
(a/c,b/c)
。如果两条线不平行,c将不为零
见:
直线方程的
a*x+b*y+c=0
形式的一个优点是,你可以自然地表示垂直线:你不能用y=m*x+c
的形式表示直线x=1
,因为m
将是无穷大,而你可以用1*x+0*y-1=0
,例如,因为它不是cl>ear结果是如何变得更糟的?同样,若你们是指小数点的精度,那个么请使用BigDecimal。请解释x1、y1和d1的意思。请解释什么是“对应行的增量”意思是。请用x,y和d来陈述行的方程。我在代码注释中添加了变量的解释。δ是行的方向。方程也被添加了。我根据你的答案生成了一个新函数。我相信你的最后一段是重要的错误所在。我的新意思是安蒂顿仍然有完全相同的缺点,所以有些地方仍然不太好。