Java 椭圆与直线相交
我有一个椭圆,有一个中点“mid”,一个水平半径“h”,一个垂直半径“v”,还有一条直线2d 现在我需要一些代码来计算两者的两个交点。 我已经试过一些代码,并且自己试过了,但是总是有错误Java 椭圆与直线相交,java,geometry,line,intersection,ellipse,Java,Geometry,Line,Intersection,Ellipse,我有一个椭圆,有一个中点“mid”,一个水平半径“h”,一个垂直半径“v”,还有一条直线2d 现在我需要一些代码来计算两者的两个交点。 我已经试过一些代码,并且自己试过了,但是总是有错误 有人有工作代码吗?我会使用内置的ellipse和line/polygon类,它们都有确定碰撞和相交的方法你需要使用代数来解这两个方程,这会有点混乱。首先你必须写出椭圆 (1) (x/h)^2 + (y/v)^2 = 1 以及格式中的行 (2) y = ax + b 首先,在坐标轴上移动,使椭圆以原点为中心。
有人有工作代码吗?我会使用内置的ellipse和line/polygon类,它们都有确定碰撞和相交的方法你需要使用代数来解这两个方程,这会有点混乱。首先你必须写出椭圆
(1) (x/h)^2 + (y/v)^2 = 1
以及格式中的行
(2) y = ax + b
首先,在坐标轴上移动,使椭圆以原点为中心。你可以通过从直线上减去中点来实现。计算交点后,通过添加中点将其移回
您可以从直线的起点和终点计算线性坡度,即δ-y/δ-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当直线由两点
P0
和P1
给出时,直线上的任何点都是(x,y)=(X0,Y0)+t(x1-X0,Y1-Y0)=(X0,Y0)+t(DX,DY)
椭圆是(X-Xm)²/h²+(Y-Ym)²/v²=1
我们将使用一个技巧来简化计算:取所有X
,减去Xm
,然后除以h
,得到X
;取所有Y
,减去Ym
,然后除以h
,得到Y
。这将使椭圆变成以原点为中心的圆。(如果愿意,您可以在不减少坐标的情况下进行所有计算。)
现在,(x,y)=(x0,y0)+t(dx,dy)
和x²+y²=1
或(tdx+x0)²+(tdy+y0)²=1
或(dx²+dy²)t²+2(dx x0+dy y0)t+(x0²+y0²-1)=0
求解
t
的二次方程。如果有实根,您可以通过条件0检查它们是否属于线段。我找不到提供此信息的方法。哪种方法是正确的?知道它们是否相交就足够了吗?你必须通过猜测来研究数学,因为你似乎将使用三角形。
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);
}