在一组圆圈中找到完全覆盖的圆圈

时间:2016-05-26 20:31:04

标签: algorithm geometry

我们在一个矩形区域有一组圆圈,所有的圆圈都有相同的半径,我想找到完全由其他圆圈覆盖的圆圈。 那有什么算法吗?

1 个答案:

答案 0 :(得分:1)

几何

首先,找到中心距离主圆中心2×r以内的所有圆;更远的圆圈不重叠。

overlapping circles

示例:主(黑色)圆圈和3个重叠圆圈。

然后,要知道主圆被完全覆盖,你必须找到一组圆,其中位于主(黑色)圆内的两个圆的每个交叉点被第三个圆覆盖。

算法

实际上,你从2个圆圈(例如蓝色和红色)开始,找到它们相交的2个点(紫色圆点)。如果一个或两个点位于主(黑色)圆圈内,则这些点必须由另一个圆圈覆盖。

然后,逐个添加一个额外的圆圈(例如绿色),看看它是否覆盖未覆盖的点(在它的例子中)。但是,这个新圆圈会在集合中的其他圆圈中添加新的交叉点(蓝色和红色);找到这些点(蓝绿色和棕色点),并检查它们是否被任何圆圈覆盖(红色圆圈覆盖了青色圆圈,但蓝色圆圈未覆盖棕色圆圈)。

继续向集合添加圆圈,直到主(黑色)圆圈内的每个交叉点被集合中的另一个圆圈覆盖(在这种情况下整个主圆圈都被覆盖),或者直到你的圆圈用完(其中如果主圆没有完全覆盖的话。)

特殊情况:
如果其中一个圆与中心圆具有完全相同的中心点,则它自己覆盖主圆 如果没有圆圈在主圆内有交叉点,则不覆盖主圆。

代码示例

此代码示例演示了如何查找两个圆的交叉点,这样可以处理算法中所需的大多数几何体。

intersecting points two circles

function intersections(p, q, r) {
    var d = distance(p, q);
    if (d > 2 * r) return [];
    var m = middle(p, q);
    if (d == 2 * r) return [m];
    var a = angle(p, q) + Math.PI / 2;
    var l = length(d, r);
    return [{x: m.x + l * Math.cos(a), y: m.y + l * Math.sin(a)},
            {x: m.x - l * Math.cos(a), y: m.y - l * Math.sin(a)}];

    function distance(p, q) {
        return Math.sqrt(Math.pow(p.x - q.x, 2) + Math.pow(p.y - q.y, 2));
    }
    function middle(p, q) {
        return {x: (p.x + q.x) / 2, y: (p.y + q.y) / 2};
    }
    function angle(p, q) {
        return Math.atan2(q.y - p.y, q.x - p.x);
    }
    function length(d, r) {
        return Math.sqrt(Math.pow(r, 2) - Math.pow(d, 2) / 4);
    }
}

document.write(JSON.stringify(intersections({x:1, y:2}, {x:3, y:-4}, 5)));