2014-06-11 105 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检查它们是否属于线段。交叉点本身由第一个等式给出。