圆圈交点
我如何计算两个圆的交点。 我希望在所有情况下都有两个,一个或没有交点。
我有中心点的x和y坐标,以及每个圆的半径。
在python中的答案是首选,但任何工作algorithm是可以接受的。
两个圆的交集
由Paul Bourke撰写
以下注释描述了如何find平面上两个圆之间的交点,使用下面的表示法。 目的是find两点P 3 =(x 3 ,y 3 )(如果它们存在的话)。
首先计算圆心的距离d。 d = || P 1 -P 0 ||。
- 如果d> r 0 + r 1那么就没有解,圆是分开的。
- 如果d <| r 0 – r 1 | 那么就没有解决scheme,因为一个圆圈包含在另一个圆圈内。
- 如果d = 0且r 0 = r 1,那么圆是重合的,并且存在无限数量的解。
考虑到两个三angular形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 =(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 0 =(x 0 ,y 0 ),P 1 =(x 1 ,y 1 )和P 2 =(x 2 ,y 2 )的P 3 =
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/
这是基于Paul Bourke文章的 C ++实现。 只有有两个十字路口才有效,否则可能会返回南南南。
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(cx, cy); float d, a, h; d = P0.distance(P1); a = (r*r - cr*cr + 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)); } };
为什么不使用你最喜欢的过程语言(或可编程计算器!)的7行如下。
假设你给出了P0坐标(x0,y0),P1坐标(x1,y1),r0和r1,你想findP3坐标(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
这里是使用vector的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(Rr) < 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*rd*dR*R)/(-2.0*d*R)); var pt1 = rotatePoint(C, P, +angle); var pt2 = rotatePoint(C, P, -angle); return [pt1, pt2]; }