LibGDX 线段与圆的交点坐标
LibGDX coordinates of intersection points between a Line Segment and a Circle
我正在使用 LibGDX 并且我有一条线段 (x1, y1, x2, y2) 与圆心 (cx, cy) 和半径 R 相交。
如何使用LibGDX(或纯Java)确定交点的坐标?
我检查了 Intersector.intersectSegmentCircle
方法,但是这个 return 只有 true
或 false
没有 return交点坐标。
感谢您的帮助。
不是真正的答案,但对于评论和使用仅适用于答案的格式来说太长了。
要找到交点,在数学上,您需要求解两个联立方程。一个是圆,一个是直线。
您可以通过搜索互联网轻松找到这些方程式的形式。
- 圆:(x - h)2 + (y - k)2 = r2
- 行:y = mx + c
你可以找到一条直线的方程,给定直线上的两个点,你声称有两个这样的点。
您还声称拥有圆的所有数据,即圆心的坐标加上半径的长度。
然后您需要在 Internet 上搜索如何求解 java 中的联立方程。我发现了这个问题:
这是我的解决方案。
基本上是找到直线的一个参数方程,然后在圆的方程中代入各个坐标,我们用二次方程求解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;
}
}
请注意,如果两个线点相同但位于圆的边缘,则此操作失败并且 returns 没有点。我没有对其进行太多测试,因此请确保它适用于您的所有情况。
编辑:可以检查 t
值是否在 0 和 1 之间,而不是检查点是否在矩形中。但是 x1
、y1
、 x2
、y2
需要替换为 xmin
、ymin
、xmax
、ymax
。
我正在使用 LibGDX 并且我有一条线段 (x1, y1, x2, y2) 与圆心 (cx, cy) 和半径 R 相交。
如何使用LibGDX(或纯Java)确定交点的坐标?
我检查了 Intersector.intersectSegmentCircle
方法,但是这个 return 只有 true
或 false
没有 return交点坐标。
感谢您的帮助。
不是真正的答案,但对于评论和使用仅适用于答案的格式来说太长了。
要找到交点,在数学上,您需要求解两个联立方程。一个是圆,一个是直线。
您可以通过搜索互联网轻松找到这些方程式的形式。
- 圆:(x - h)2 + (y - k)2 = r2
- 行:y = mx + c
你可以找到一条直线的方程,给定直线上的两个点,你声称有两个这样的点。
您还声称拥有圆的所有数据,即圆心的坐标加上半径的长度。
然后您需要在 Internet 上搜索如何求解 java 中的联立方程。我发现了这个问题:
这是我的解决方案。
基本上是找到直线的一个参数方程,然后在圆的方程中代入各个坐标,我们用二次方程求解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;
}
}
请注意,如果两个线点相同但位于圆的边缘,则此操作失败并且 returns 没有点。我没有对其进行太多测试,因此请确保它适用于您的所有情况。
编辑:可以检查 t
值是否在 0 和 1 之间,而不是检查点是否在矩形中。但是 x1
、y1
、 x2
、y2
需要替换为 xmin
、ymin
、xmax
、ymax
。