给出一组2D坐标和每个坐标的半径,如何有效地找到该组圆中至少2个圆相交的所有点?
我知道两个圆最多相交2个点,因此可以通过两个圆之间的成对比较并遍历整个数据集来完成,但是当实际数据集具有10000个圆时,将进行所有成对比较计算昂贵。
下面是用于生成测试数据的示例代码。
library("plotrix")
set.seed(1995)
XCoordinate = sample(x = 1:100,size = 20)
set.seed(2000)
YCoordinate = sample(x = 1:100,size = 20)
set.seed(1997)
Radius = sample(x = 1:50,size = 20)
## Create DataFrame
TestData = data.frame(XCoordinate = XCoordinate,YCoordinate = YCoordinate,
Radius = Radius )
## Plot Circle
plot(TestData$XCoordinate, TestData$YCoordinate,
type="n", xlab="", ylab="" , main="Test draw.circle")
for(Row in 1:nrow(TestData)){
PlotCircle(TestData$XCoordinate[Row],
TestData$YCoordinate[Row],
TestData$Radius[Row])
}
我正在尝试查找附件中所有用黑色标记的点。
答案 0 :(得分:2)
您可能会得到很多误报的候选对象,但是除非圆圈彼此重叠,否则我们可以通过计算圆圈的边界框并进行线扫来显着减少配对检查的次数。相交的圆圈表示边界框相交,尽管反之亦然。
答案 1 :(得分:1)
实施起来可能更复杂,但可能比גלעדבבקן的解决方案更具选择性:
构建一个R-Tree,组织圆圈中心并添加一个
每个拥有最大值的节点的附加属性maxRadius
节点中包含的圆心的半径
对于每个圈子c
,查找在以下位置执行范围搜索的候选圈子
R树。当p
minDist(c, p) > c.radius + p.maxRadius
在2D中构建R树通常为O(n log n),对于中等范围(半径),范围搜索被视为O(log n)。在一般情况下,总计为 O(n log n)。
答案 2 :(得分:0)
我在这里用 C++ 实现了圆相交的扫描线算法: github.com/malyasova/intersect_circles
它的工作原理类似于 segment intersection algorithm,只是每个圆的上下圆弧被插入到状态而不是线段中。它在 O((n+k)log n) 时间内工作,其中 n 是圆的数量,k 是交叉点的数量。