You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求最优算法:添加2D平面点使新增Voronoi区域面积最大化

优化限定区域内整数点Voronoi新增区域最大化的策略

数学核心思路

1. 明确新增区域的本质

新点 ( P(x_i,y_i) ) 的Voronoi区域是限定区域 ( \Omega ) 与所有原有站点 ( S_j ) 的半平面 ( H_j: d(P,X) \leq d(S_j,X) ) 的交集。面积最大化的点,本质是在 ( \Omega ) 内找到离所有原有站点最远的区域对应的整数点——这类点通常集中在:

  • 限定区域的边界上(如你测试案例中的 ( (1,-5) ) 处于Y轴边界)
  • 现有站点最小包围范围之外的区域
  • 现有Voronoi图顶点/对偶Delaunay三角剖分外接圆圆心附近的整数点

2. 缩小候选点范围

无需遍历所有整数点,只需聚焦以下几类候选:

  • 限定区域边界上的所有整数点:边界点的区域往往能利用区域边界的“无限延伸截断”特性,获得更大的有效面积
  • 现有站点最小包围矩形外的整数点:计算所有原有站点的X/Y坐标极值,筛选出 ( \Omega ) 中落在该矩形外的点,这些点受原有站点的约束更少
  • Maximin点附近的整数点:求解 ( \Omega ) 内使 ( \min(d(P,S_j)) ) 最大的点(连续空间的maximin问题),将其坐标四舍五入到整数,再取周围1-2格的整数点作为候选——这个点是连续空间中最优解,附近的整数点大概率是离散最优解
  • Voronoi顶点/Delaunay外接圆圆心附近的整数点:现有Voronoi图的顶点是到3个原有站点等距的点,Delaunay外接圆圆心与其重合,这些点附近的整数点往往能获得较大的区域

编程优化策略

1. 预计算与缓存

  • 提前计算所有原有站点的坐标平方和 ( s_j = x_j^2 + y_j^2 ),避免重复计算垂直平分线公式:
    半平面 ( H_j ) 的直线方程可简化为 ( 2(x_j - p_x)x + 2(y_j - p_y)y = s_j - (p_x^2 + p_y^2) )
  • 预定义限定区域 ( \Omega ) 的多边形顶点(如你的测试案例为 ( [(-5,-5),(5,-5),(5,5),(-5,5)] )),方便后续裁剪计算

2. 高效的区域面积计算

无需重新构建整个Voronoi图,直接对每个候选点计算区域:

  • 使用Sutherland-Hodgman裁剪算法:以限定区域多边形为初始形状,依次用每个半平面 ( H_j ) 裁剪,最终得到的多边形即为新点的Voronoi区域
  • 用鞋带公式计算裁剪后多边形的面积,复杂度为 ( O(n) )(n为多边形顶点数)
  • 提前终止逻辑:如果裁剪过程中多边形面积已小于当前已知最大值,直接跳过该点的后续计算

3. 并行加速

由于每个候选点的面积计算完全独立,可通过多线程/多进程并行处理候选点集,大幅缩短计算时间。示例Python代码片段:

from multiprocessing import Pool
import numpy as np

def compute_area(p, sites, omega):
    # 实现半平面裁剪与鞋带公式计算面积的逻辑
    # 1. 初始化当前多边形为限定区域omega
    current_poly = omega.copy()
    px, py = p
    p_sq = px**2 + py**2
    max_area_so_far = 0  # 假设外部传入当前最大值,这里简化示例
    for (sx, sy) in sites:
        s_sq = sx**2 + sy**2
        # 生成半平面的直线方程 ax + by = c
        a = 2 * (sx - px)
        b = 2 * (sy - py)
        c = s_sq - p_sq
        # Sutherland-Hodgman裁剪步骤
        new_poly = []
        for i in range(len(current_poly)):
            x1, y1 = current_poly[i]
            x2, y2 = current_poly[(i+1)%len(current_poly)]
            val1 = a*x1 + b*y1 - c
            val2 = a*x2 + b*y2 - c
            if val1 <= 0:
                new_poly.append((x1, y1))
            if (val1 > 0 and val2 <= 0) or (val1 <=0 and val2 >0):
                # 计算交点
                t = (c - a*x1 - b*y1) / (a*(x2-x1) + b*(y2-y1))
                ix = x1 + t*(x2-x1)
                iy = y1 + t*(y2-y1)
                new_poly.append((ix, iy))
        current_poly = new_poly
        if not current_poly:
            return 0.0
        # 提前计算当前面积,小于最大值则终止
        area = 0.5 * abs(sum(x1*y2 - x2*y1 for (x1,y1),(x2,y2) in zip(current_poly, current_poly[1:]+[current_poly[0]])))
        if area < max_area_so_far:
            return area
    return 0.5 * abs(sum(x1*y2 - x2*y1 for (x1,y1),(x2,y2) in zip(current_poly, current_poly[1:]+[current_poly[0]])))

if __name__ == "__main__":
    sites = [[-5,7],[2,5],[-6,-2],[7,2],[-4,6]]
    omega = [(-5,-5),(5,-5),(5,5),(-5,5)]
    # 生成候选点:边界点 + maximin点附近(示例中直接取Y=-5的所有X整数点)
    candidates = [(x, -5) for x in range(-5,5)]
    with Pool(processes=4) as pool:
        results = pool.starmap(compute_area, [(p, sites, omega) for p in candidates])
    max_area = max(results)
    best_point = candidates[results.index(max_area)]
    print(f"最优点: {best_point}, 最大面积: {max_area:.2f}")

4. Maximin点的快速求解

连续空间的maximin点可通过梯度上升或非线性规划求解:

  • 目标函数:( f(x,y) = \min_{j} d((x,y), S_j) )
  • 约束:( (x,y) \in \Omega )
  • 求解得到连续点后,取其周围的整数点作为候选即可

内容的提问来源于stack exchange,提问作者armangrewal007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 10:27:51