圆 - 圆交叉点

fma*_*ark 53 algorithm math geometry intersection

如何计算两个圆的交点.我希望在所有情况下都有两个,一个或没有交叉点.

我有中心点的x和y坐标,以及每个圆的半径.

python中的答案是首选,但任何工作算法都是可以接受的.

Jac*_*cob 92

两个圆圈的交点

由Paul Bourke撰写

以下注释描述了如何在平面上找到两个圆之间的交点,使用以下符号.目的是找到两个点P 3 =(x 3,y 3)(如果它们存在).

2个圆圈的交点

首先计算圆心之间的距离d.d = || P 1 - P 0 ||.

  • 如果d> r 0 + r 1则没有解,圆圈是分开的.

  • 如果d <| r 0 - r 1 | 然后没有解决方案,因为一个圆圈包含在另一个圆圈内.

  • 如果d = 0且r 0 = r 1则圆圈重合并且存在无限数量的解.

考虑到两个三角形P 0 P 2 P 3 和P 1 P 2 P 3,我们可以写

a 2 + h 2 = r 0 2且b 2 + h 2 = r 1 2

使用d = a + b我们可以求解a,

a =(r 0 2 - r 1 2 + d 2)/(2 d)

可以容易地示出,当两个圆在一个点处接触时,这减小到r 0,即:d = r 0 + r 1

通过将a代入第一个等式来求解h,h 2 = r 0 2 - a 2

所以

P 2 = P 0 + a(P 1 -P 0)/ d

最后,P 3 =(X 3,Y 3以P计)0 =(X 0,Y 0),P 1 =(X 1,Y 1)和P 2 =(X 2,Y 2),是

x 3 = x 2 + - h(y 1 -y 0)/ d

y 3 = y 2 - + h(x 1 -x 0)/ d

资料来源:http://paulbourke.net/geometry/circlesphere/

  • `使用 d = a + b 我们可以求解 a。`怎么样?这一步对我来说就像黑魔法。哪个方程用于求解 a? (4认同)
  • 很好,这是一个很好的解释。这是python中的算法:https://gist.github.com/xaedes/974535e71009fa8f090e (2认同)
  • b ^ 2 = r1 ^ 2-h ^ 2`和h ^ 2 = r0 ^ 2-a ^ 2` b ^ 2 = r1 ^ 2-r0 ^ 2 + a ^ 2` r0 ^ 2-r1 ^ 2 = a ^ 2-b ^ 2``d ^ 2 + r0 ^ 2-r1 ^ 2 = a ^ 2-b ^ 2 + d ^ 2`现在使用等式((a + b)^ 2 = d ^ 2 = a ^ 2 + b ^ 2 + 2ab``d ^ 2 + r0 ^ 2-r1 ^ 2 = a ^ 2-b ^ 2 + a ^ 2 + b ^ 2 + 2ab``d ^ 2 + r0 ^ 2-r1 ^ 2 = 2 * a ^ 2 + 2ab`如果将两边都乘以2a,则可以从`a + b = d`得到2 * a ^ 2 + 2ab = 2da。 d ^ 2 + r0 ^ 2-r1 ^ 2 = 2da` (2认同)

rob*_*ing 15

这是我基于Paul Bourke的文章的 C++实现.只有在有两个交叉点时它才有效,否则它可能会返回NaN NAN NAN NAN.

class Point{
    public:
        float x, y;
        Point(float px, float py) {
            x = px;
            y = py;
        }
        Point sub(Point p2) {
            return Point(x - p2.x, y - p2.y);
        }
        Point add(Point p2) {
            return Point(x + p2.x, y + p2.y);
        }
        float distance(Point p2) {
            return sqrt((x - p2.x)*(x - p2.x) + (y - p2.y)*(y - p2.y));
        }
        Point normal() {
            float length = sqrt(x*x + y*y);
            return Point(x/length, y/length);
        }
        Point scale(float s) {
            return Point(x*s, y*s);
        }
};

class Circle {
    public:
        float x, y, r, left;
        Circle(float cx, float cy, float cr) {
            x = cx;
            y = cy;
            r = cr;
            left = x - r;
        }
        pair<Point, Point> intersections(Circle c) {
            Point P0(x, y);
            Point P1(c.x, c.y);
            float d, a, h;
            d = P0.distance(P1);
            a = (r*r - c.r*c.r + d*d)/(2*d);
            h = sqrt(r*r - a*a);
            Point P2 = P1.sub(P0).scale(a/d).add(P0);
            float x3, y3, x4, y4;
            x3 = P2.x + h*(P1.y - P0.y)/d;
            y3 = P2.y - h*(P1.x - P0.x)/d;
            x4 = P2.x - h*(P1.y - P0.y)/d;
            y4 = P2.y + h*(P1.x - P0.x)/d;

            return pair<Point, Point>(Point(x3, y3), Point(x4, y4));
        }

};
Run Code Online (Sandbox Code Playgroud)

  • 不;)-听起来像是一种有趣的练习,虽然可以尝试一下; p (2认同)

wil*_*set 8

这是Javascript中使用向量的实现.代码已有详细记录,您应该能够遵循它.这是原始来源

在这里观看现场演示: 在此输入图像描述

// Let EPS (epsilon) be a small value
var EPS = 0.0000001;

// Let a point be a pair: (x, y)
function Point(x, y) {
  this.x = x;
  this.y = y;
}

// Define a circle centered at (x,y) with radius r
function Circle(x,y,r) {
  this.x = x;
  this.y = y;
  this.r = r;
}

// Due to double rounding precision the value passed into the Math.acos
// function may be outside its domain of [-1, +1] which would return
// the value NaN which we do not want.
function acossafe(x) {
  if (x >= +1.0) return 0;
  if (x <= -1.0) return Math.PI;
  return Math.acos(x);
}

// Rotates a point about a fixed point at some angle 'a'
function rotatePoint(fp, pt, a) {
  var x = pt.x - fp.x;
  var y = pt.y - fp.y;
  var xRot = x * Math.cos(a) + y * Math.sin(a);
  var yRot = y * Math.cos(a) - x * Math.sin(a);
  return new Point(fp.x+xRot,fp.y+yRot);
}

// Given two circles this method finds the intersection
// point(s) of the two circles (if any exists)
function circleCircleIntersectionPoints(c1, c2) {

  var r, R, d, dx, dy, cx, cy, Cx, Cy;

  if (c1.r < c2.r) {
    r  = c1.r;  R = c2.r;
    cx = c1.x; cy = c1.y;
    Cx = c2.x; Cy = c2.y;
  } else {
    r  = c2.r; R  = c1.r;
    Cx = c1.x; Cy = c1.y;
    cx = c2.x; cy = c2.y;
  }

  // Compute the vector <dx, dy>
  dx = cx - Cx;
  dy = cy - Cy;

  // Find the distance between two points.
  d = Math.sqrt( dx*dx + dy*dy );

  // There are an infinite number of solutions
  // Seems appropriate to also return null
  if (d < EPS && Math.abs(R-r) < EPS) return [];

  // No intersection (circles centered at the 
  // same place with different size)
  else if (d < EPS) return [];

  var x = (dx / d) * R + Cx;
  var y = (dy / d) * R + Cy;
  var P = new Point(x, y);

  // Single intersection (kissing circles)
  if (Math.abs((R+r)-d) < EPS || Math.abs(R-(r+d)) < EPS) return [P];

  // No intersection. Either the small circle contained within 
  // big circle or circles are simply disjoint.
  if ( (d+r) < R || (R+r < d) ) return [];

  var C = new Point(Cx, Cy);
  var angle = acossafe((r*r-d*d-R*R)/(-2.0*d*R));
  var pt1 = rotatePoint(C, P, +angle);
  var pt2 = rotatePoint(C, P, -angle);
  return [pt1, pt2];

}
Run Code Online (Sandbox Code Playgroud)

  • 演示链接已损坏 (2认同)

Cur*_*arc 7

为什么不直接使用7行最喜欢的程序语言(或可编程计算器!),如下所示.

假设你有P0坐标(x0,y0),P1坐标(x1,y1),r0和r1,你想找到P3坐标(x3,y3):

d=sqr((x1-x0)^2 + (y1-y0)^2)
a=(r0^2-r1^2+d^2)/(2*d)
h=sqr(r0^2-a^2)
x2=x0+a*(x1-x0)/d   
y2=y0+a*(y1-y0)/d   
x3=x2+h*(y1-y0)/d       // also x3=x2-h*(y1-y0)/d
y3=y2-h*(x1-x0)/d       // also y3=y2+h*(x1-x0)/d
Run Code Online (Sandbox Code Playgroud)