答案 0 :(得分:3)
圈'接触点将放置在从center1到center2的线上。因此,例如,如果两个圆圈都具有samze大小,您可以选择intersection = center1 + 1/2*(center2-center1)
但是由于您的圈子大小不同,您可以选择以下内容:
compute dirVector = center2-center1
compute d = |dirVector|
if d < radius1 + radius2 + threshold: consider circles to intersect so now compute contact point
gap = d - radius1 - radius2 // remark: here gap might become < 0 which is ok
contactPoint = center1 + (radius1+gap/2)*(dirVector/d)
我已经用原始C ++代码测试了这种方法,并且我得到了这个结果:
绿色圆圈是您的原始图像,红色圆圈是我提取的圆圈(不完美但很简单),粉红色圆点是contact points
,用于某些接触距离阈值(20像素)
这是接触距离阈值低得多的结果(5)(但请记住,我提取的圆半径比你的低一点):
为了提高效率(因为你必须比较每对圆圈,不管它们有多远=&gt; O(n²)
)你应该使用某种二进制空间分区,如:
或类似的
或尝试Spatial Hashing,但这些更适合稀疏区域。
一般情况下,您可能希望搜索碰撞检测优化以加快速度(在那里您可以找到有关二进制空间分区和空间散列的更多信息)。
由于你的空间非常丰富,你也可以考虑一个简单的网格(在这种情况下类似于空间哈希):
//choose size of each grid cell to be the maximum found radius of all your circles.
gridCellSize = max diameter + contact-threshold-distance // radius was wrong I think
for each circle
indexX = round(center.x/gridCellSize)
indexY = round(center.y/gridCellSize)
grid[x,y].push_back(current circle)
for each circle in a grid-cell:
compare this circle to each other circle in the cell
compare this circle to each circle in all surrounding cells
ignore all circles in all other cells
对于我之前的例子我已经提取了44像素的最大半径(你的像素可能是47像素,具体取决于你用来绘制圆圈的线条大小。
因此计算出这样的网格:
例如,如果网格为0索引,则在网格单元格位置(1,1)中,有2个圆圈。应将它们中的每一个与同一细胞中的所有圆形和周围细胞中的每个圆形进行比较。因此,这2个圈子只会与12个圈子进行比较,而不是n-1
圈子。
或以图形标记的示例:红色单元格中的所有圆圈必须与周围蓝色单元格中的每个圆圈进行比较,此外还要与红色单元格中的其他圆圈进行比较(在此示例中均为无):
答案 1 :(得分:1)
有几种方法可以尝试此问题:
正如您所说,圆圈的半径和中心,这意味着您有圆的边界(圆周坐标)。这意味着您可以知道哪个坐标属于哪个圆圈,因此您可以使用此信息找到交叉点。
你可以对图像进行分割,然后根据圆度进一步区分它们,圆形的斑点将它们移除。现在你将拥有所有那些不遵循圆度的斑点(因为圆圈已经连接在一起),所以你可以再次应用第1步,现在检查交叉点的点数非常少。
分水岭算法比上述方法复杂,但您可以尝试一下,为此您可以创建一个图像,您可以使用它们的中心和半径绘制所有这些圆(此图像将是二进制图像)填充所有圆圈并使用中心作为分水岭的种子应用分水岭算法,它将为您提供两个对象加入的坐标。
在我看来,你可以使用方法1或2解决问题。
谢谢