簡體   English   中英

確定圓是否與無限線相交

[英]Decide if a circle intersects with an infinite line

因此,我需要檢查圓是否與代數線相交。 我嘗試通過與穿過圓心的無限垂直線垂直來做到這一點。 然后,我測量垂直於圓半徑的垂直線,並指出如果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.
        }
    }

}

這是開始出錯的地方。 可以輸入的幾個點顯然應該相交或不相交,但是程序經常說不。

我們將為此工作幾個小時,因此,如果我在其他人之前解決了該問題,我將發布更新以及解決方法。

原理是正確的,但我不會驗證您的計算。

簡而言之:

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,其方向由by矢量{ux,uy}定義。 點的距離{cx。 cy}到這行

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

|| P1-C | 是C和P1之間的距離,而alpha是方向{ux,uy}與線{P1,C}方向之間的角度。 讓我們用{vx,vy}表示{P1,C}行的單一方向。 在這種情況下,由於uv是單一的( |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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM