Java 几乎平行的直线的远交点

Java 几乎平行的直线的远交点,java,geometry,Java,Geometry,我在画布上绘制了大量连接的边,所有这些边都以某种方式排列,这些边的特定延伸总是给出与另一条延伸边的交点。这一点需要进一步的计算——这与画布上出现的内容无关。我的代码在一般情况下非常有效,但是如果边缘的相应扩展超出了范围,那么交叉点并不总是存在(但是,直线不是平行的)-至少不在本程序的范围内。有人有什么想法来提高这段代码的精确度吗?事实上,我稍后会使用大小数,但对于绘图步骤,我最初认为使用double就足够了 这一条将边缘延伸到两侧: public Line2D.Double ExteLine(P

我在画布上绘制了大量连接的边,所有这些边都以某种方式排列,这些边的特定延伸总是给出与另一条延伸边的交点。这一点需要进一步的计算——这与画布上出现的内容无关。我的代码在一般情况下非常有效,但是如果边缘的相应扩展超出了范围,那么交叉点并不总是存在(但是,直线不是平行的)-至少不在本程序的范围内。有人有什么想法来提高这段代码的精确度吗?事实上,我稍后会使用大小数,但对于绘图步骤,我最初认为使用double就足够了

这一条将边缘延伸到两侧:

public Line2D.Double ExteLine(Point2D p, Point2D q){
   double slope, y3, y4;
   slope = (q.getY() - p.getY())/(q.getX() - p.getX());
   y3 = (slope * (100000 - p.getX())) + p.getY();
   y4 = (slope * (-100000 - p.getX())) + p.getY();
   Point2D out1 = new Point2D.Double(100000, y3);
   Point2D out2 = new Point2D.Double(-100000, y4);
   Line2D.Double line = new Line2D.Double(out1, out2);
   return line; }
这一个找到了交叉点:

public Point2D.Double getIntersectionPoint(Line2D.Double line1, Line2D.Double line2) {
if (! line1.intersectsLine(line2)) { 
  System.out.println("No intersection"); 
  return null;} 
  double s1 = line1.getX1(),
        sp2 = line1.getY1(),
        rx = line1.getX2()-s1,
        ry = line1.getY2()-sp2;
  double qx = line2.getX1(),
        qy = line2.getY1(),
        sx = line2.getX2()-qx,
        sy = line2.getY2()-qy;
  double det = sx*ry - sy*rx;
  if (det == 0) { System.out.println("Det = 0");
    return null;} 
  else {
    double z = (sx*(qy-sp2)+sy*(s1-qx))/det;
    if (z==0 ||  z==1) return null;  
    return new Point2D.Double(
      (double)(s1+z*rx), (double)(sp2+z*ry));
  }
}

使用齐次坐标的射影几何是处理几乎平行甚至完全平行的直线的好方法。这是一个速成班:

  • 平面中的点(x,y)将均匀化为(x,y,1)
  • 它的倍数表示相同的点,因此您可以将其写成(2x,2y,2)
  • 直线ax+by+c=0表示为(A,b,c)
  • 齐次坐标p=(x,y,z)的点位于直线g=(A,b,c)上当且仅当其点积p·g=ax+by+cz为零时。(您可能不需要这样做,因为与double进行相等比较总是很棘手的,但这解释了为什么其他步骤都是如此。)
  • 连接两个点的线可以计算为其齐次坐标的叉积
  • 两条直线之间的交点也可以计算为这些直线坐标的交点
  • 由于上述步骤总是相乘,如果将其中几个步骤组合起来,您的双精度数字可能会溢出。因此,不时地重新缩放向量,例如,将向量与一些标量相乘,使其具有最大绝对值的条目变为1或任何值
  • 如果要在画布上绘制点(x,y,z),请计算(x/z,y/z)并绘制该点
  • 如果z=0,则无法执行上一步。这表示一个“无限”点
  • 如果x=y=z=0或a=b=c=0,则该矢量不表示点响应。一条线,而是一种堕落的状态。例如,您试图计算连接点与自身的直线

正如您所看到的,这非常容易实现,而且更好的是:您不需要在任何地方区分任何案例!对于实际的绘图内容,您可能希望将线与画布的边界相交,然后使用连接这些相交点的线作为图形基本体的定义。

是在两个方向上延伸到无限的边“真”线(并且只需穿过由Line2D.Doubles表示的线段),或者它们是由Line2D.Doubles表示的具有不同起点和终点的线段?一个人永远不能依赖由不同方法计算的两个浮点值,这两个浮点值应该相等,才能完全相等(for==)。如果必须使用浮点,则必须在某个小值epsilon内进行比较。也就是说,
if(abs(a-b)<1.0E-6)
而不是
if(a==b)
@JimGarrison这是一个很好的观点,也是我在稍后阶段使用的一种方法——但我不太明白我如何在这里合并它(甚至使用浮点以外的东西?)@paulk23它们不会扩展到无穷大——事实上,我不知道它们可以。我想当时我可能不得不使用不同的对象类。我可以通过使用不同的类来提高精度,但我真的很喜欢这个想法,它实际上非常适合我正在做的事情——我希望我能着手实现它。我知道这可能是一个后期跟进,但在这种情况下,如何计算齐次坐标中四个共线点的交比?我必须首先用真实的射影线来识别它们吗?@Denor:通常你选择一个点
P
不在四个点
a,B,C,D
的线上,然后计算
CR(a,B;C,D)=([ACP][BDP])/([ADP][BCP])
其中
[XYZ是平面上齐次坐标的行列式,即3×3行列式。但事实上,这更像是一个新问题,最好继续问下去。毕竟,我的回答使用了交叉比率。好吧,很抱歉把它扩展到原来问题的范围之外。我想出来了,我做了一些类似于你建议的事情。非常感谢。