Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/101.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 一种求解二维点集外接圆的算法_Algorithm_Geometry_Computational Geometry - Fatal编程技术网

Algorithm 一种求解二维点集外接圆的算法

Algorithm 一种求解二维点集外接圆的算法,algorithm,geometry,computational-geometry,Algorithm,Geometry,Computational Geometry,我有一组二维点,我想找到它的最小外接圆。点绘制在下面(我将它们作为Python中的元组集合): 原因如下:每个红点都是一个“种子”,用于查询在线地图方向服务以查找可能的路线,这样我就可以逐步扩大道路网络。问题是:由于我在种子附近进行查询,内部种子往往会得到重复的结果,因此我正在考虑对它们进行“修剪”。为此,我需要找到包含圆的中心和直径,这样我就可以删除最里面的圆-例如,在小于外圆半径一半的圆内的圆。我找到了一个使用live demo的有效解决方案(Python和JavaScript) 导入数学

我有一组二维点,我想找到它的最小外接圆。点绘制在下面(我将它们作为Python中的元组集合):


原因如下:每个红点都是一个“种子”,用于查询在线地图方向服务以查找可能的路线,这样我就可以逐步扩大道路网络。问题是:由于我在种子附近进行查询,内部种子往往会得到重复的结果,因此我正在考虑对它们进行“修剪”。为此,我需要找到包含圆的中心和直径,这样我就可以删除最里面的圆-例如,在小于外圆半径一半的圆内的圆。

我找到了一个使用live demo的有效解决方案(Python和JavaScript)

导入数学,随机
#数据约定:点是一对浮点数(x,y)。圆是三个浮点数(中心x、中心y、半径)。
#返回包含所有给定点的最小圆。在预期的O(n)时间内运行,随机。
#输入:浮点或整数对的序列,例如[0,5)、(3.1,-2.7]。
#输出:表示圆的三个浮点数。
#注:0分不返回。如果给定1点,则返回半径为0的圆。
def make_圆(点):
#转换为浮点并随机化顺序
洗牌=[(浮点(p[0]),浮点(p[1])表示p的点数]
随机。洗牌(洗牌)
#逐步向圆中添加点或重新计算圆
c=无
对于枚举(洗牌)中的(i,p):
如果c为无或不为_为_圆(c,p)中的_:
c=_make_circle_one_point(无序[0:i+1],p)
返回c
#已知一个边界点
定义?使?圆?一点(点,p):
c=(p[0],p[1],0.0)
对于枚举(点)中的(i,q):
如果不是,则在圆(c,q)中:
如果c[2]==0.0:
c=制造直径(p,q)
其他:
c=(点[0:i+1],p,q)使(点)圆(点(点[0:i+1])
返回c
#已知两个边界点
定义两个点(点,p,q):
直径=制造直径(p,q)
如果所有(_为_in_圆(直径,r)表示r in点):
回流直径
左=无
右=无
对于r in点:
交叉=_交叉乘积(p[0],p[1],q[0],q[1],r[0],r[1])
c=_make_外接圆(p,q,r)
如果c为无:
持续
elif cross>0.0和(左为无或_cross_乘积(p[0],p[1],q[0],q[1],c[0],c[1])>_cross_乘积(p[0],p[1],q[0],q[1],左[0],左[1]):
左=c
elif cross<0.0和(右为无或_cross_乘积(p[0],p[1],q[0],q[1],c[0],c[1])<_cross_乘积(p[0],p[1],q[0],q[1],右[0],右[1]):
右=c
如果(right为None)或(left为None,left为None)返回left[2]可以帮助您吗?
import math, random

# Data conventions: A point is a pair of floats (x, y). A circle is a triple of floats (center x, center y, radius).

# Returns the smallest circle that encloses all the given points. Runs in expected O(n) time, randomized.
# Input: A sequence of pairs of floats or ints, e.g. [(0,5), (3.1,-2.7)].
# Output: A triple of floats representing a circle.
# Note: If 0 points are given, None is returned. If 1 point is given, a circle of radius 0 is returned.

def make_circle(points):
    # Convert to float and randomize order
    shuffled = [(float(p[0]), float(p[1])) for p in points]
    random.shuffle(shuffled)

    # Progressively add points to circle or recompute circle
    c = None
    for (i, p) in enumerate(shuffled):
        if c is None or not _is_in_circle(c, p):
            c = _make_circle_one_point(shuffled[0 : i + 1], p)
    return c


# One boundary point known
def _make_circle_one_point(points, p):
    c = (p[0], p[1], 0.0)
    for (i, q) in enumerate(points):
        if not _is_in_circle(c, q):
            if c[2] == 0.0:
                c = _make_diameter(p, q)
            else:
                c = _make_circle_two_points(points[0 : i + 1], p, q)
    return c


# Two boundary points known
def _make_circle_two_points(points, p, q):
    diameter = _make_diameter(p, q)
    if all(_is_in_circle(diameter, r) for r in points):
        return diameter

    left = None
    right = None
    for r in points:
        cross = _cross_product(p[0], p[1], q[0], q[1], r[0], r[1])
        c = _make_circumcircle(p, q, r)
        if c is None:
            continue
        elif cross > 0.0 and (left is None or _cross_product(p[0], p[1], q[0], q[1], c[0], c[1]) > _cross_product(p[0], p[1], q[0], q[1], left[0], left[1])):
            left = c
        elif cross < 0.0 and (right is None or _cross_product(p[0], p[1], q[0], q[1], c[0], c[1]) < _cross_product(p[0], p[1], q[0], q[1], right[0], right[1])):
            right = c
    return left if (right is None or (left is not None and left[2] <= right[2])) else right


def _make_circumcircle(p0, p1, p2):
    # Mathematical algorithm from Wikipedia: Circumscribed circle
    ax = p0[0]; ay = p0[1]
    bx = p1[0]; by = p1[1]
    cx = p2[0]; cy = p2[1]
    d = (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by)) * 2.0
    if d == 0.0:
        return None
    x = ((ax * ax + ay * ay) * (by - cy) + (bx * bx + by * by) * (cy - ay) + (cx * cx + cy * cy) * (ay - by)) / d
    y = ((ax * ax + ay * ay) * (cx - bx) + (bx * bx + by * by) * (ax - cx) + (cx * cx + cy * cy) * (bx - ax)) / d
    return (x, y, math.hypot(x - ax, y - ay))


def _make_diameter(p0, p1):
    return ((p0[0] + p1[0]) / 2.0, (p0[1] + p1[1]) / 2.0, math.hypot(p0[0] - p1[0], p0[1] - p1[1]) / 2.0)


_EPSILON = 1e-12

def _is_in_circle(c, p):
    return c is not None and math.hypot(p[0] - c[0], p[1] - c[1]) < c[2] + _EPSILON


# Returns twice the signed area of the triangle defined by (x0, y0), (x1, y1), (x2, y2)
def _cross_product(x0, y0, x1, y1, x2, y2):
    return (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0)