直线与圆的位置关系
直线与圆的位置关系有三种。判定有两条路:联立方程消元后看判别式的符号,或者直接比较圆心到直线的距离 与半径 。两者等价,后者不必解方程。
1 · 距离与半径的比较
定理 1.1 设圆心到直线的距离为 、半径为 。则 时直线与圆相离, 时相切, 时相交。
判据的来历就是圆的定义:圆上的点到圆心的距离恒为 ,而直线上离圆心最近的点(垂足)距离为 。垂足落在圆外则整条直线都在圆外;恰在圆上则它是唯一的公共点;落在圆内则直线从圆内穿出,两侧各交一次。
联立法给出同一个结论。把直线方程代入圆的方程消去一个变量,得到一个一元二次方程,、、 分别对应两个、一个、零个公共点。代数上 与 相差一个正因子,故两种判据同号。几何法的好处是不必消元,也不必先讨论「直线是否竖直」——竖直线代入时消去的是另一个变量,联立法要分两种写法。
2 · 弦长公式
相交时两交点之间的线段是弦。圆心到弦的垂线平分弦,于是半弦、、 构成直角三角形:
时弦过圆心,弦长取到最大值 (直径); 时弦长趋于零。这个公式把「求弦长」化归成「求点到直线的距离」,比解出两个交点再算距离省得多。
例 2.1 圆 被直线 截得的弦长。圆心 到直线的距离 ,直线过圆心,弦长即直径 。把直线改成 ,则 ,弦长 。
公式在
略大于
时会失效,而失效的方式不是报错。实测
、:,开平方得 NaN。相离时本来就没有弦,所以正确的写法是先分类、再决定要不要算弦长。lineCircle 按这个次序实现:相离与相切两支直接把弦长置零,只有相交那一支才开平方,且被开的量还先与零取大。判定与计算的先后不是风格问题——反过来写,一个
量级的浮点误差就能让整个结果变成 NaN。
3 · 切线
时直线与圆相切,切点就是垂足。已知切点求切线只需一步:切线垂直于该点处的半径,故 、( 为圆心), 由过点条件定出。
过一个给定点作切线则要分三种情形:点在圆外有两条,点在圆上一条,点在圆内零条。圆外一点 到切点的距离(切线长)由勾股定理给出:
4 · 切点弦:绕开「斜率不存在」
求过圆外一点的两条切线,常见解法是设切线为 ,用 解出 。这个解法有一处必须单独讨论:若其中一条切线竖直,它的 不存在,解方程只会得到另一条,答案漏一半。 的方程是一元二次的,出现「只有一个根」时就该怀疑漏了竖直的那一条。
tangentLinesFrom 换一条路:先写出切点弦所在的直线
再拿它与圆求交,两个交点就是两个切点,切线由「
与切点」两点式给出。这条路上没有斜率出现,竖直的切线只是一个普通的交点。实现上它还复用了 lineCircle——求切点这件事被化归成了上一节的直线与圆求交。
注 · 切点弦这条直线在 落到圆内时依然有方程,且它与圆不相交(此时 到圆心的距离小于 ,代数上对应无实交点)。这与「圆内一点作不出切线」是一致的,故实现里不必为圆内的情形另设分支,只需在最外层按 与 的比较先分类:圆内直接返回零条,避免把一个空交点列表当成「有切线但算不出来」。
5 · 参考文献
- Line–sphere intersection. Wikipedia. 直线与圆 / 球面求交的一般处理。https://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection
- Tangent lines to circles. Wikipedia. 切线的性质、切线长与过一点的两条切线。https://en.wikipedia.org/wiki/Tangent_lines_to_circles
- Chord (geometry). Wikipedia. 弦、弦心距与弦长公式。https://en.wikipedia.org/wiki/Chord_(geometry)