求有限线段上到指定点距离为给定半径r的点的更简便解法
嘿,其实不用联立圆和直线方程来解,用向量投影的思路会清爽很多,步骤也更直接,给你拆解一下:
首先先明确前提:假设我们要找线段AB(端点A(x₁,y₁)、B(x₂,y₂))上的点Q,使得Q到圆心C(x₀,y₀)的距离等于r。
第一步,先算线段AB的基本参数:
向量AB = (x₂ - x₁, y₂ - y₁),线段AB的长度len_AB = sqrt((x₂-x₁)² + (y₂-y₁)²),如果len_AB是0(两点重合),那直接判断A点到C的距离是不是r就行。
再算向量AC = (x₀ - x₁, y₀ - y₁),也就是从A到圆心C的向量。第二步,计算投影长度:
把向量AC投影到AB上,得到投影长度t_proj = (AC·AB) / len_AB,这里的·是向量点积(也就是(x₀-x₁)(x₂-x₁) + (y₀-y₁)(y₂-y₁))。这个t_proj代表从A点出发,沿着AB方向走t_proj长度,就能到达C在AB上的投影点P。第三步,判断圆和线段的位置关系:
计算投影点P到C的距离d = sqrt( |AC|² - t_proj² ),这里|AC|是向量AC的长度,也就是sqrt((x₀-x₁)² + (y₀-y₁)²)。- 如果d > r:圆和线段没有交点,直接返回空;
- 如果d == r:投影点P就是唯一的交点,只要P在线段AB上(也就是t_proj在0到len_AB之间),就返回P;
- 如果d < r:会有两个候选点,分别在P的两侧,距离P的长度是
delta = sqrt(r² - d²)。
第四步,计算候选点并验证是否在线段上:
先算AB方向的单位向量u = ( (x₂-x₁)/len_AB, (y₂-y₁)/len_AB ),然后两个候选点的坐标是:Q₁ = (x₁ + (t_proj + delta)*u.x, y₁ + (t_proj + delta)*u.y)Q₂ = (x₁ + (t_proj - delta)*u.x, y₁ + (t_proj - delta)*u.y)
最后检查这两个点的t值(也就是从A出发的长度,t = t_proj ± delta)是否在0到len_AB之间,符合的就是线段上的有效点。
如果你的需求是找线段上到某个端点距离为r的点,那更简单:直接从端点出发,沿着线段方向走r长度就行。比如从A出发,点的坐标就是 (x₁ + r*(x₂-x₁)/len_AB, y₁ + r*(y₂-y₁)/len_AB),只要r ≤ len_AB,这个点就在线段上;如果r > len_AB,那要么是B点,要么没有符合要求的点(看你的实际需求)。
这种方法全程不用解二次方程,都是线性计算,比联立圆和直线方程要简洁不少~
备注:内容来源于stack exchange,提问作者mk3

