Python 如何判断一个圆是否被其他几个圆包围

Python 如何判断一个圆是否被其他几个圆包围,python,geometry,geopy,Python,Geometry,Geopy,我正在构建一个与Google Places API交互的程序,以识别美国县内给定类型的所有机构。谷歌接受半径形式的搜索——因此为了覆盖整个区域,我正在按顺序构建我的搜索半径。然而,这个算法创建了很多重叠的圆,我想过滤掉它们。因此: 给定一个圆列表,每个圆都有圆心和半径,如何判断单个圆是否完全被其他圆的任何组合覆盖 我已经可以判断出一个圆是否被另一个圆所包围——我的问题是,很多圆都被其他几个圆的组合所包围 有人问我现有的代码-如果一个圆与另一个圆完全重叠,我目前测试的代码-不是它们的组合。但这就是

我正在构建一个与Google Places API交互的程序,以识别美国县内给定类型的所有机构。谷歌接受半径形式的搜索——因此为了覆盖整个区域,我正在按顺序构建我的搜索半径。然而,这个算法创建了很多重叠的圆,我想过滤掉它们。因此:

给定一个圆列表,每个圆都有圆心和半径,如何判断单个圆是否完全被其他圆的任何组合覆盖

我已经可以判断出一个圆是否被另一个圆所包围——我的问题是,很多圆都被其他几个圆的组合所包围

有人问我现有的代码-如果一个圆与另一个圆完全重叠,我目前测试的代码-不是它们的组合。但这就是我所拥有的。你可以看到,我通过排除它与其他20个圆圈重叠来近似当前的问题,在这一点上,它可能包含:

def radiusIsInsidePreviousQuery(self, testQuery):
    newSearchCoordinates = (testQuery['center']['lat'], testQuery['center']['lng'])
    alreadyBeenSearched = False

    numberOfIntersectingCircles = 0

    for queryNumber in self.results.keys():
        previousQuery = self.results[queryNumber]
        previousSearchCoordinates = (previousQuery['center']['lat'], 
                                     previousQuery['center']['lng'])

        centroidDistance = VincentyDistance(newSearchCoordinates, 
                                            previousSearchCoordinates)

        centroidDistanceMeters = centroidDistance.meters
        newQueryRadius = testQuery['radius']
        fullSearchDistance = centroidDistanceMeters + newQueryRadius

        #If the full search distance (the sum of the distance between
        #the two searches' centroids and the new search's radius) is less
        #than the previous search's radius, then the new search is encompassed
        #entirely by the old search.
        previousQueryRadius = previousQuery['radius']
        if fullSearchDistance <= previousQueryRadius:
            print "Search area encompassed"
            alreadyBeenSearched = True
        elif centroidDistanceMeters < newQueryRadius + previousQueryRadius:
            numberOfIntersectingCircles += 1
        elif self.queriesAreEqual(testQuery, previousQuery):
            print "found duplicate"
            alreadyBeenSearched = True   

    #If it intersects with 20 other circles, it's not doing any more good.
    if numberOfIntersectingCircles > 20:
        alreadyBeenSearched = True    

    return alreadyBeenSearched 
def radiusinsidepreviousquery(self,testQuery):
newSearchCoordinates=(testQuery['center']['lat'],testQuery['center']['lng'])
alreadyBeenSearched=False
相交圆数=0
对于self.results.keys()中的queryNumber:
previousQuery=self.results[queryNumber]
previousSearchCoordinates=(previousQuery['center']['lat'],
上一个查询['center']['lng'])
质心距离=文森特距离(新搜索坐标,
上一页(坐标)
质心距离米=质心距离米
newQueryRadius=testQuery['radius']
fullSearchDistance=质心距离计+新的QueryRadius
#如果是完整的搜索距离(两个
#两次搜索的质心和新搜索的半径)较小
#比上一次搜索的半径大,则新搜索被包含
#完全是旧的搜索。
previousQueryRadius=previousQuery['radius']

如果完全搜索距离

让我们考虑要测试的圆A/P> 我不知道你的计算需要有多精确,但假设用100个点表示A的周长就足够了

输入数学

#Circle to be tested

Circle_A = (3,2,1)
resolution = 100

circumference_A = []
for t in xrange(resolution):
    step = (2*math.pi)/resolution 
    x = Circle_A[0]
    y = Circle_A[1]
    r = Circle_A[2]
    circumference_A.append((x+(r*math.cos(t*step)),y+(r*math.sin(t*step))))

# Given list of circles (we need to know center and radius of each).
# Put them in a list of tuples like this (x,y,r)

ListOfCircles=[(5,2,2),(2,4,2),(2,2,1),(3,1,1)]

# Test:Check if all the points of circumference A are not < r from each one of the circles in the list.

overlap_count = 0
for p in circumference_A:
    print('testing p:',p)
    for c in ListOfCircles:
        distance = math.sqrt(math.pow(p[0]-c[0],2) + math.pow(p[1]-c[1],2))
        if distance < c[2]:
            overlap_count += 1
            print('overlap found with circle',c)
            break
        else:
            print('distance:',str(distance))
            print('origin:',c)



if overlap_count == resolution:
    print("Circle A is completely overlapped by the ListOfCircles")
else:
    print(str(overlap_count)+" points out of "+ str(resolution) + " overlapped with the composed area")
#待测圆圈
圈A=(3,2,1)
分辨率=100
周长A=[]
对于X范围内的t(分辨率):
步骤=(2*math.pi)/分辨率
x=圆[0]
y=圆[1]
r=圆A[2]
周长A.append((x+(r*math.cos(t*step)),y+(r*math.sin(t*step)))
#给定的圆列表(我们需要知道每个圆的中心和半径)。
#将它们放入这样的元组列表中(x,y,r)
循环列表=[(5,2,2)、(2,4,2)、(2,2,1)、(3,1,1)]
#测试:检查周长A的所有点与列表中每个圆的距离是否小于r。
重叠计数=0
对于圆周_A中的p:
打印('testing p:',p)
对于圆形列表中的c:
距离=math.sqrt(math.pow(p[0]-c[0],2)+math.pow(p[1]-c[1],2))
如果距离
您可以将其作为磁盘联合问题来解决。这个问题与磁盘的理论有关,可以通过构造一个可以在时间
O(n Log(n))
中为
n
磁盘执行的磁盘来解决

您可以按如下方式使用此构造:从列表中计算磁盘的并集。然后将单个磁盘添加到此联合。如果没有更改,则包含单个磁盘

您将不得不使用一个高级包,比如CGAL,因为算法远不简单


如果您可以使用近似的解决方案,并且目标是简化编程,只需以合适的分辨率在空白图像中绘制磁盘即可。然后检查单个磁盘的绘制是否达到新像素

由于需要处理相当于磁盘总面积的像素数,这种方法的成本可能会很高


混合解决方案也可以作为难度和效率之间的折衷方案


选择垂直分辨率并用等距水平线交叉填充平面。它们将沿着线段与每个磁盘相交。为每个水平方向保留一个段列表,并在添加新磁盘时执行段的并集是一件容易的事情。(通过对重叠部分进行排序和计数,可以轻松实现
n
段的合并。)

请发布您刚刚开发的代码,谢谢@il_raffa。在目前的问题上,这不是一个很大的进步。我真的很想知道为什么这个答案被否决了。答案准确地解释了OP需要知道的内容。TL;DR:测试圆周上的任何一点是否在给定圆列表中的每个圆的面积内。非常感谢您的帮助!所以,也许我误读了你的代码,如果是的话,我很抱歉。但是假设你测试的圆圈列表恰好都是同一个圆圈的三个实例-如果它们的重叠计数之和等于分辨率,这不是说圆圈被完全包围了,即使它只是圆圈的同一部分被多次覆盖,零件仍然暴露在外?这就是为什么中断声明很重要。一旦一个点在里面,它就会停止测试,这样就不会给你误报。您可以按原样运行脚本并开始使用它。break语句还使它非常快=>resolution*log(n)是您正在测试的圈数。它也使用std库,不再使用了。谢谢