集群中面积最大的返回圆

时间:2019-02-23 21:05:17

标签: python python-3.x algorithm python-2.7 python-requests

列表以(x,y,r)形式给出,其中x和y是中心坐标,r是半径。 对于每个群集,保留面积最大的圆,并删除该群集中的所有其他圆。返回结果元组。

代码

import math

class Circle(object):
    def __init__(self, x, y, r):
        super(Circle, self).__init__()
        self.x = x
        self.y = y
        self.r = r

    def get_distance(self, circle):
        return math.sqrt(math.pow(self.x - circle.x, 2) + math.pow(self.y - circle.y, 2))

    def is_intersect(self, circle):
        return self.get_distance(circle) < self.r + circle.r

    @staticmethod
    def has_intersections(list_circles):
        list_circles.sort(key=lambda a: a.x - a.r)
        sweep_intersected = []
        for circle in list_circles:
            for in_sweep in sweep_intersected:
                if circle.is_intersect(in_sweep):
                    return True
                if in_sweep.x + in_sweep.r < circle.x - circle.r:
                    sweep_intersected.remove(in_sweep)
            sweep_intersected.append(circle)
        return False

cir = [(12,5,0.9),(2,4,0.8),(2,3,0.4)]
cv1 = cir[0]
cv2 = cir[1]
cv3 = cir[2]
#cv4 = cir[3]
c1 = Circle(cv1[0], cv1[1], cv1[2])
c2 = Circle(cv2[0], cv2[1], cv2[2])
c3 = Circle(cv3[0], cv3[1], cv3[2])

a = []
cval = Circle.has_intersections([c1, c2, c3])
if cval == False:
  for num in range(len(cir)):
    break
  print(cir)
if cval == True:
  for n in range(len(cir)):
    #max(cir[n][2])
    a.append(cir[n][2])
    max_value = max(a)
    max_index = a.index(max_value)
  print(cir[max_index])

我有2个主要问题 1.如何接受来自用户和返回列表的元组列表? 2.我无法通过测试用例下面的内容。谢谢

测试用例 输入:[(0.5,0.5,0.4),(1.7,1.3,1),(0.4,0.6,0.3)] 输出:[(1.7,1.3,1)]

2 个答案:

答案 0 :(得分:1)

对于每个圆元组,您都可以做一个幼稚的方法,您可以计算出它与所有其他圆元组的距离,如果此距离大于它们的半径之和,则可以计算出该距离。这样,您将知道某个圆是否与另一个圆重叠,那么半径的总和将小于其中心的距离。

因此您可以定义一些功能:

import math
def distance(p1, p2):
    return math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)

并且它们为重叠定义了一个函数:

def isoverlapping(circle1, circle2):
    sum_of_radius = circle1[2] + circle2[2]
    distance_bettwen_circles = distance(circle1, circle2)
    return sum_of_radius >= distance_bettwen_circles

因此,如果上面的函数返回true,则必须忽略较小的圆圈。为此,您可以创建一个函数来计算圆的面积并返回更大的值:

def greatercircle(circle1, circle2):
    area1 = math.pi * circle1[2]
    area2 = math.pi * circle2[2]
    return circle1 if area1 >= area2 else circle2

现在只需要将他加入一个循环中即可

output = []

# 1: Iterate over circles array, comparing every position with the others.
for index, circle in enumerate(circles):
#     2: get the other circles in array
    another_circles = circles[:index] + circles[index+1:]
    for another_circle in another_circles:
#         3: Iterate over the other circles
        if isoverlapping(circle, another_circle):
#         if an overlap ocurrs then get the greater circle.
#         Now this will be the current circle for comparison.
            greater = greatercircle(circle, another_circle)
            circle = greater
#   4: If this circle is already in output, do not append it.
    if circle not in output:
        output.append(circle)

print(output)

希望它可以为您提供帮助!

答案 1 :(得分:1)

由于您只对保持最大的圆圈感兴趣,因此我们可以应用贪心算法。在这里,我们首先对最大半径上的所有圆进行排序,然后循环遍历它们,如果它们没有任何相交(如果我们已经包含在结果集中的圆),则将它们添加到我们的结果集中。

circles = [c1, c2, c3, c4]

from operator import attrgetter


def largest_non_overlapping_circles(circles):
    circles.sort(key=attrgetter('r'), reverse=True)  # sort on largest radius
    res = []  # list of circles we want to keep
    for c in circles:
        if not Circle.has_intersections(res + [c]):
            res.append(c)
    return res


print([(c.x, c.y, c.r) for c in largest_non_overlapping_circles(circles)])

对于第二个问题,我们可以利用Python的input()函数。在这里,我选择在一行中要求所有数字(x,y,r)。我还使用了while循环,以便用户可以根据需要输入更多的圆圈。没有错误处理,如果有意外输入,应用程序只会崩溃。由您决定,使其更加出色。

print("""Give each circle with three numbers using the decimal as a dot.
The three numbers should be resp. x y r and should be seperated by a space.""")
c1 = Circle(*map(float, input("Give first circle >> ").split()))
circles = [c1]
while "y" in input("Do you want to give another circle? >> "):
    circles.append(Circle(*map(float, input("Give another circle >> ").split())))

print([(c.x, c.y, c.r) for c in largest_non_overlapping_circles(circles)])