2014-06-11 165 views
1

我有一個橢圓,中點'mid',水平半徑'h'和垂直半徑'v'和Line2D。橢圓和線交點JAVA

現在我需要一些代碼來計算兩個交點。 我已經嘗試了一些代碼,並嘗試在我自己的,但總是有一個錯誤。

有人有一些工作代碼嗎?

回答

1

我會使用內置的橢圓和線/多邊形類有他們都有方法來確定碰撞和交匯

+0

我找不到給我這個信息的方法。最好的方法是正確的? – user3658206

+0

http://docs.oracle.com/javase/7/docs/api/java/awt/geom/Ellipse2D.html – user3730340

+0

和什麼方法? – user3658206

2

您將需要使用代數來解決這兩個方程,它會得到一個有點亂。首先,你必須讓橢圓的原點爲中心在你的座標軸寫出來的橢圓

(1) (x/h)^2 + (y/v)^2 = 1 

和行格式

(2) y = ax + b 

首先,移位。你可以通過從線上減去中間值來實現。一旦你計算出相交點,通過增加中點將它們移回去。

您可以從線的起點和終點計算delta-y/delta-x的線性斜率。你將不得不檢查斜坡是否垂直。如果斜率是垂直的,則只需檢查線點的x值是否落在橢圓的位置,然後輕鬆計算這些值。在紙上畫出來,看看如何計算它。

現在假設斜坡不是垂直的。既然你從行中知道y,就可以代入(1)。簡化給出了二次方程。

(3) ((ah)^2+v^2)x^2 + (2abh^2)x + ((hb)^2-(hv)^2) = 0 

使用二次公式給出交點x座標的兩個值。如果x有兩個實數值,則有兩個交點。如果x只有一個實數解,則有一個交點。如果x沒有真正的解決方案,則不存在交集。

鑑於斧^ 2 + BX + C = 0,x由

x = (1/2a)(-b +- Sqrt(b^2 - 4ac)) 

令d給定= B^2 - 4AC

如果d < 0時,不存在交叉點

如果d = 0,有一個交叉

如果d> 0,存在兩個交點

一旦你計算了x交點的值,用x的值代入(2)得到y值。

現在,您需要確保這些點落在該線內。爲此,只需檢查計算點的x和y分量是否滿足x1 = < = x= x2和y1 = < = y< = y2其中x1是最小的,x2是線的最大x端點,y1是最小的,y2是線的最大y端點。

下面是一個例子的方法,我做

public static ArrayList<Point2D> getIntersection(double x1, double x2, double y1, double y2, double midX, double midY, double h, double v) { 
    ArrayList<Point2D> points = new ArrayList(); 

    x1 -= midX; 
    y1 -= midY; 

    x2 -= midX; 
    y2 -= midY; 

    if (x1 == x2) { 
     double y = (v/h)*Math.sqrt(h*h-x1*x1); 
     if (Math.min(y1, y2) <= y && y <= Math.max(y1, y2)) { 
      points.add(new Point2D(x1+midX, y+midY); 
     } 
     if (Math.min(y1, y2) <= -y && -y <= Math.max(y1, y2)) { 
      points.add(newPoint2D(x1+midX, -y+midY); 
     } 
    } 
    else { 
     double a = (y2 - y1)/(x2 - x1); 
     double b = (y1 - a*x1); 

     double r = a*a*h*h + v*v; 
     double s = 2*a*b*h*h; 
     double t = h*h*b*b - h*h*v*v; 

     double d = s*s - 4*r*t; 

     if (d > 0) { 
      double xi1 = (-s+Math.sqrt(d))/(2*r); 
      double xi2 = (-s-Math.sqrt(d))/(2*r); 

      double yi1 = a*xi1+b; 
      double yi2 = a*xi2+b; 

      if (isPointInLine(x1, x2, y1, y2, xi1, yi1)) { 
       points.add(new Point2D.Double(xi1+midX, yi1+midY); 
      } 
      if (isPointInLine(x1, x2, y1, y2, xi2, yi2)) { 
       points.add(new Point2D.Double(xi2+midX, yi2+midY); 
      } 
     } 
     else if (d == 0) { 
      double xi = -s/(2*r); 
      double yi = a*xi+b; 

      if (isPointInLine(x1, x2, y1, y2, xi, yi)) { 
       points.add(new Point2D.Double(xi+midX, yi+midY)); 
      } 
     } 
    } 

    return points; 
} 

public static boolean isPointInLine(double x1, double x2, double y1, double y2, double px, double py) { 
    double xMin = Math.min(x1, x2); 
    double xMax = Math.max(x1, x2); 

    double yMin = Math.min(y1, y2); 
    double yMax = Math.max(y1, y2); 

    return (xMin <= px && px <= xMax) && (yMin <= py && py <= yMax); 
} 

隨意檢查我的代數和我的代碼,但你應該通過每個代數一步仔細去解決這個問題。

0

當該線由兩個點P0P1給出時,該線上的任何點是(X, Y) = (X0, Y0) + t (X1 - X0, Y1 - Y0) = (X0, Y0) + t (DX, DY)

橢圓是(X - Xm)²/h² + (Y - Ym)²/v² = 1

我們將使用一個技巧來簡化計算:採取一切X,減去由hXm和鴻溝,讓x;取全部Y,減去Ym併除以h,給出y。這將把橢圓變成一個以原點爲中心的圓。 (如果您願意,可以在不減少座標的情況下進行所有計算。)

現在,(x, y) = (x0, y0) + t (dx, dy)x² + y² = 1

(t dx + x0)² + (t dy + y0)² = 1

(dx² + dy²) t² + 2 (dx x0 + dy y0) t + (x0² + y0² - 1) = 0

解決t的二次方程式。如果有真正的根源,則可以通過條件0 <= t <= 1檢查它們是否屬於線段。交叉點本身由第一個等式給出。