我有一个椭圆,其中点为“mid”,水平半径为“h”,垂直半径为“v”,还有一个 Line2D。
现在我需要一些代码来计算两者的两个交点。 我已经尝试过一些代码并自己尝试过,但总是有错误。
有人有一些工作代码吗?
最佳答案
您需要使用代数来求解这两个方程,这会变得有点困惑。首先你必须写出椭圆
(1) (x/h)^2 + (y/v)^2 = 1
以及格式中的行
(2) y = ax + b
首先,在坐标轴上移动,使椭圆以原点为中心。您可以通过从直线中减去 mid 来做到这一点。计算出交点后,通过添加中点将它们向后移动。
您可以从直线的起点和终点计算 delta-y/delta-x 的线性斜率。您必须检查斜坡是否垂直。如果斜率是垂直的,您只需检查线点的 x 值是否落在椭圆的位置,然后轻松计算值。把它画在纸上,看看如何计算。
现在假设斜坡不是垂直的。由于您通过直线知道了 y 的 x 值,因此将其平方并代入 (1)。化简得到二次方程。
(3) ((ah)^2+v^2)x^2 + (2abh^2)x + ((hb)^2-(hv)^2) = 0
使用二次公式给出交点 x 坐标的两个值。如果 x 有两个实值,则有两个交集。如果 x 只有一个实数解,则存在一个交集。如果 x 没有实数解,则不存在交集。
给定 ax^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 是线的最小 x 端点,x2 是线的最大 x 端点,y1是线的最小 y 端点,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);
}
请随意检查我的代数和代码,但您应该通过仔细完成每个代数步骤来解决这个问题。
关于java - 椭圆与直线相交JAVA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24164485/