gpt4 book ai didi

围绕一组二维点查找外接圆的算法

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:00:04 24 4
gpt4 key购买 nike

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

enter image description here

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

最佳答案

我通过现场演示找到了一个可行的解决方案(使用 Python 和 JavaScript)here .

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)

关于围绕一组二维点查找外接圆的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37416509/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com