【发布时间】:2020-02-20 03:47:45
【问题描述】:
我正在使用 LibGDX,我有一个线段 (x1, y1, x2, y2) 与圆心 (cx, cy) 和半径 R 相交。
如何使用 LibGDX(或纯 Java)确定交叉点的坐标?
我检查了 Intersector.intersectSegmentCircle 方法,但这仅返回 true 或 false 而不返回交点坐标。
感谢您的帮助。
【问题讨论】:
我正在使用 LibGDX,我有一个线段 (x1, y1, x2, y2) 与圆心 (cx, cy) 和半径 R 相交。
如何使用 LibGDX(或纯 Java)确定交叉点的坐标?
我检查了 Intersector.intersectSegmentCircle 方法,但这仅返回 true 或 false 而不返回交点坐标。
感谢您的帮助。
【问题讨论】:
这是我的解决方案。
基本上找到了直线的参数方程,然后将每个坐标替换在圆的方程中,我们使用二次公式求解t。获得的值用于获取点坐标。有关数学的更深入解释,请参阅答案 here。此外,由于在这种情况下线不是无限的,因此会检查获得的交点是否适合线所在的同一矩形。
我使用了与图中相同的符号。
public class Intersections {
/**
* Returns a list of intersection points between the edge of a circle and a line.
* @param cx Circle center X coordinate.
* @param cy Circle center Y coordinate.
* @param r Circle radius.
* @param x1 First line X coordinate.
* @param y1 First line Y coordinate.
* @param x2 Second line X coordinate.
* @param y2 Second line Y coordinate.
* @return A list of intersection points.
*/
public static List<Vector2> getCircleLineIntersectionPoints(
float cx, float cy, float r, float x1, float y1, float x2, float y2) {
// Find values to use in quadratic formula
float dx = x2 - x1;
float dy = y2 - y1;
float a = dx * dx + dy * dy;
float b = 2 * dx * (x1 - cx) + 2 * dy * (y1 - cy);
float c = (float) Math.pow((x1 - cx), 2) + (float) Math.pow((y1 - cy), 2) - r * r;
float d = b * b - 4 * a * c; // Discriminant
ArrayList<Vector2> points = new ArrayList<>();
if (d >= 0) {
// Perform quadratic formula to get 2 points
float root = (float) Math.sqrt(d);
float t1 = 2 * c / (-b + root);
float t2 = 2 * c / (-b - root);
// Need the rectangle bounds that the line fits in to check
// if intersection points are within the line bounds
float xmin = Math.min(x1, x2);
float ymin = Math.min(y1, y2);
float xmax = Math.max(x1, x2);
float ymax = Math.max(y1, y2);
// Add first point
float p1x = x1 + dx * t1;
float p1y = y1 + dy * t1;
if (isPointInRectangle(xmin, ymin, xmax, ymax, p1x, p1y)) {
points.add(new Vector2(p1x, p1y));
}
// Add second point if there's one
if (!MathUtils.isEqual(t1, t2)) {
float p2x = x1 + dx * t2;
float p2y = y1 + dy * t2;
if (isPointInRectangle(xmin, ymin, xmax, ymax, p2x, p2y)) {
points.add(new Vector2(p2x, p2y));
}
}
}
return points;
}
private static boolean isPointInRectangle(
float xmin, float ymin, float xmax, float ymax, float px, float py) {
return px >= xmin && py >= ymin && px <= xmax && py <= ymax;
}
}
请注意,如果两个线点相同但位于圆的边缘,则此操作失败并且不返回任何点。我没有对其进行太多测试,因此请确保它适用于您的所有情况。
编辑:可以检查t的值是否在0和1之间,而不是检查点是否在矩形中。但是x1、y1、x2、y2会需要替换为xmin、ymin、xmax、ymax。
【讨论】:
对于评论并使用仅适用于答案的格式,还不是真正的答案。
要在数学上找到相交点,您需要求解两个联立方程。一个用于圆形,一个用于直线。
您可以通过搜索 Internet 轻松找到这些方程的形式。
给定直线上的两个点,你可以找到一条直线的方程,并且你声称有两个这样的点。
您还声称拥有圆的所有数据,即圆心的坐标加上其半径的长度。
然后您需要在 Internet 上搜索如何在 java 中求解联立方程。我发现了这个 SO 问题:
How to solve a 2 variable linear simultaneous equation? Java
【讨论】: