确定圆是否与无限线相交

时间:2016-09-23 00:44:04

标签: java

所以,我需要检查圆是否以代数方式与一条线相交。我试图通过对穿过圆心的无限远垂直线来做到这一点。然后,我测量垂直于圆的半径,并指出如果d > r,该线不相交。

import java.util.Scanner;

public class LineCircle_Intersection {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        double p1x, p2x, p1y, p2y, cx, cy, r;

        System.out.print("Enter p1x: ");
        p1x = in.nextDouble();
        System.out.print("Enter p1y: ");
        p1y = in.nextDouble();
        System.out.print("Enter p2x: ");
        p2x = in.nextDouble();
        System.out.print("Enter p2y: ");
        p2y = in.nextDouble();
        System.out.print("Enter cx: ");
        cx = in.nextDouble();
        System.out.print("Enter cy: ");
        cy = in.nextDouble();
        System.out.print("Enter r: ");
        r = in.nextDouble();

        double m = (p2y - p1y) / (p2x - p1x);
        double pem = -1 / m;
        double pey = pem + p1y;   //  pe = perpendicular line (used E instead of L because lowercase l looks too much like 1)
        double pex = (pey - p1y) / pem;
        double d = Math.sqrt((pex - cx) * (pex - cx) + (pey - cy) * (pey - cy));

        if (d <= r) {
            if (d == r) {
                System.out.println("Line intersects the circle at one point.");
            } else {
                System.out.println("Line intersects the circle at two points.");
            }
        } else if (m == 1) {
            if (d <= r) // There's a problem in this area.  I'm not sure what, or how to fix it.
            {
                if (d == r) {
                    System.out.println("The line intersects the circle at one point.");
                } else {
                    System.out.println("Line intersects the circle at two points.");
                }
            } else {
                System.out.println("Line does not intersect the circle.");
            }
        } else {
            System.out.println("Else.");  //This says "Else" for testing purposes.
        }
    }

}

这里的事情开始出错了。有几个点可以输入,显然应该相交或不相交,但程序经常说不然。

将在这个问题上工作几个小时,所以如果我在别人面前解决这个问题,我会发布更新以及我是如何解决的。

1 个答案:

答案 0 :(得分:0)

原则是正确的,但我不会验证您的计算。

简而言之:

boolean intersects=false, is_tangent=false;
double p2p1x=p2x-p1x, p2p1y=p2y-p1y;
double p1p2DistSq=p2p1x*p2p1x+p2p1y*p2p1y;
if(p1p2DistSq > 1e-12) { // well-behaved line 
  double p1cx=p1x-cx, p1cy=p1y-cy;
  double crossprod=p2p1x*p1cy-p2p1y*p1cx;
  double distCenterToLineSquare=crossprod*crossprod/p1p2DistSq;
  double rSquare=r*r;
  intersects = (distCenterToLineSquare <= rSquare); // r is radius
  // for practical purposes, if the relative error of
  // (r-dist) is 1e-6 of r, we might consider the line as tangent.
  is_tangent = Math.abs(distCenterToLineSquare - rSquare)/rSquare < 1e-12;
} // cowardly refusing to deal with ill-configured lines

详情:

初步(如果您目前没有互联网,请将此作为推断点与线之间距离的简便方法)

两个载体之间的交叉产物

{ax, ay} x {bx, by} = |a|*|b|*sin(angle_between_dir_a_and_b)

此交叉产品也是(ax*by-ay*bx)

现在,假设一条线穿过P1,方向由酉向量{ux,uy}定义。点的距离{cx。 cy}到这一行将是

dist=sin(alpha)*|P1-C|

其中| P1-C |是C和P1之间的距离,alpha是方向{ux,uy}和方向{P1,C}之间的角度。让我们用{vx,vy}来表示{P1,C}行的单一方向。在这种情况下,由于 u v 是单一的(|u|=|v|=1

 sin(alpha)=ux*vy-uy*vx

因此

dist=(ux*vy-uy*vx)*|P1-C|

使用

插入vx,vy
vx=(P1x-Cx)/|P1-C| // it's a unitary vector
vy=(P1y-Cy)/|P1-C|

结果

dist=ux*(P1y-Cy)-uy*(P1x-Cx)

现在,唯一剩下的就是ux和uy。由于您的行由P1和P2定义

ux=(P2x-P1x)/|P1-P2|
uy=(P2y-P1y)/|P1-P2|

(再次,| P1-P2 |,P1和P2之间的距离)

dist=( (P2x-P1x)*(P1y-Cy)-(P2y-P1y)*(P1x-Cx) )/ |P1-P2|

好的,| P1-P2 |需要进行sqrt评估,我们可以通过将dist^2radius^2

进行比较来摆脱它

'线相交圆'然后变为

double p1cx=p1x-cx, p1cy=p1y-cy;
double p2p1x=p2x-p1x, p2p1y=p2y-p1y;
double crossprod=p2p1x*p1cy-p2p1y*p1cx;
double distCenterToLineSquare=crossprod*crossprod/(p2p1x*p2p1x+p2p1y*p2p1y);
boolean intersects= (distCenterToLineSquare <= r*r); // r is radius