圆内点沿指定角度到圆周的距离计算及伪代码修正
问题分析与正确实现
你的伪代码存在两个核心错误:
- 角度逻辑完全错误:用
atan2得到的是向量相对于x轴的绝对方向角,这两个角并非三角形ACD的内角,直接代入三角形内角和公式没有任何几何依据。 - 正弦定理应用错误:即便角度计算正确,你也搞混了三角形边与角的对应关系,导致公式完全不成立。
正确几何推导与实现
先明确核心条件:
- D是圆上一点,直线AD的方向由AB确定(AD与AB共线)
- A在圆内,C为圆心,CD = r(半径)
- 我们用余弦定理求解AD,步骤如下:
- 计算向量AC及其长度:
- 向量AC:
(c_x - a_x, c_y - a_y) - AC长度:
ac_len = sqrt( (c_x - a_x)^2 + (c_y - a_y)^2 )
- 向量AC:
- 计算向量AB及其长度:
- 向量AB:
(b_x - a_x, b_y - a_y) - AB长度:
ab_len = sqrt( (b_x - a_x)^2 + (b_y - a_y)^2 )
- 向量AB:
- 计算∠CAD的余弦值(向量AC与AB的夹角余弦):
- 点积:
dot = (c_x - a_x)*(b_x - a_x) + (c_y - a_y)*(b_y - a_y) - 余弦值:
cos_theta = dot / (ac_len * ab_len)
- 点积:
- 代入余弦定理求解AD:
在△ACD中,CD² = AC² + AD² - 2*AC*AD*cosθ,整理为一元二次方程:AD² - 2*ac_len*cos_theta*AD + (ac_len² - r²) = 0
解得:AD = ac_len*cos_theta ± sqrt( r² - ac_len²*(1 - cos_theta²) )
由于A在圆内,根号内的值必为正,两个解对应直线AB与圆的两个交点,可根据需求选择。
正确伪代码实现
float dis(float a_x, float a_y, float b_x, float b_y, float c_x, float c_y, float r) { // 计算向量AC及长度 float ac_x = c_x - a_x; float ac_y = c_y - a_y; float ac_len = sqrt(ac_x * ac_x + ac_y * ac_y); // 计算向量AB及长度 float ab_x = b_x - a_x; float ab_y = b_y - a_y; float ab_len = sqrt(ab_x * ab_x + ab_y * ab_y); // 处理AB为零向量的异常情况 if (ab_len < 1e-8) { return 0.0f; } // 计算夹角余弦值 float dot = ac_x * ab_x + ac_y * ab_y; float cos_theta = dot / (ac_len * ab_len); // 计算根号内项,避免负数开方 float sqrt_term = r * r - ac_len * ac_len * (1.0f - cos_theta * cos_theta); sqrt_term = sqrt(fmax(sqrt_term, 0.0f)); // 两个解,这里取往B方向的交点(可根据实际需求调整符号) float ad1 = ac_len * cos_theta + sqrt_term; float ad2 = ac_len * cos_theta - sqrt_term; // 返回有效正解 return ad1 > 0 ? ad1 : ad2; }
补充说明
如果D点不是在AB直线上,而是由AB确定其他角度,需要调整推导逻辑,但根据你描述的“本质是求解三角形ACD”及伪代码意图,上述实现符合需求。代码加入了边界判断,避免运行时错误。
内容的提问来源于stack exchange,提问作者TheFurryDevil
相关产品推荐
相关产品推荐

