我正在阅读Steven和Felix Halim撰写的“竞争性编程3”的第7章。然后我发现了这个问题,如图所示:
这里还给出了两个圆的两个交叉点和相应的半径。我必须找到两个圆圈的中心。他们给出了解决方案代码。但我不明白它背后的技术。给定的代码是:
我已多次搜索,但我没有找到。任何人都可以解释这种技术吗?
无论如何,提前谢谢:)
答案 0 :(得分:1)
我们可以看到,d2
代表p1
和p2
之间距离的平方。让我们放d = sqrt(d2)
。然后是d^2 = d2
。
使用毕达哥拉斯:r^2 = h^2 + d^2/4
。因此,h^2 = r^2 - d^2/4
。
加入1
和p1
的行方向上的单一(norm = p2
)向量为:
v := (p2 - p1)/d = (p2.x - p1.x, p2.y - p1.y)/d.
它的垂直是
w := (p2.y - p1.y, p1.x - p2.x)/d
现在我们可以将c1
表示为垂直方向上的一个点:
c1 = q + w*h = (p1 + p2)/2 + w*h,
因为w
具有范数1
而h
恰好是c1
和q
之间的距离。因此,
c1 = (p1.x + p2.x, p1.y + p2.y)/2 + (p2.y - p1.y, p1.x - p2.x)*h/d
,其中
h/d = sqrt(r^2 - d^2/4)/d = sqrt(r^2/d2 - 1/4)
解释了代码。
备注强>
从r
始终为ge
而非d/2
的图片中。因此,r^2 ≥ d^2/4
或(r/d)^2 ≥ 1/4
并且无需检查是否det < 0
,因为它永远不会(如果圆圈相交)。
上面的推导实际上会为c1
生成两个解,一个位于从p1
到p2
的蓝线右侧,这是图中的一个,在另一条线的左边。实际上,这些对应于方程式
c1 = q ± w*h = q + w*(±h)
为了决定是否应该使用+h
或-h
,我们可以应用一个众所周知的标准来确定某个点是位于有向段的左侧还是右侧。例如,我们可以计算行列式的符号
| 1 p1.x p1.y |
D = | 1 p2.x p2.y | = (p2.x-p1.x)(c1.y-p1.y) - (p2.y-p1.y)(c1.x-p1.x)
| 1 c1.x c1.y |
的标记为+h
,而-h
则相反。使h
成为D < 0
的值是c1
从p1
到p2
的段右侧的mysite.xyz/builder
。
答案 1 :(得分:0)
在正三角形中应用毕达哥拉斯。这为您提供了p1p2中点与中心之间的距离。
从平行然后正交于p1p2的单位矢量,很容易获得偏移矢量。