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

如何提取矩形内的Voronoi顶点及Voronoi边与矩形的交点?

提取矩形区域内的Voronoi顶点及边界交点

实现思路

  • 用scipy.spatial.Voronoi生成全局Voronoi图
  • 筛选坐标落在矩形[-1,10]×[-1,10]内的原始Voronoi顶点
  • 遍历所有Voronoi边,判断边的端点是否跨出矩形边界,若跨边界则计算该边与矩形四条边的交点
  • 整合内部顶点与边界交点,可视化验证结果

修改后的完整代码

import numpy as np
from scipy.spatial import Voronoi, voronoi_plot_2d
import matplotlib.pyplot as plt

# 定义矩形边界
x_min, x_max = -1, 10
y_min, y_max = -1, 10

# 生成随机种子点(可替换为自定义点集)
np.random.seed(42)
points = np.random.rand(20, 2) * 11 - 1  # 确保点落在[-1,10]范围内

# 生成Voronoi图
vor = Voronoi(points)

# 1. 筛选矩形内部的Voronoi顶点
interior_vertices = []
for vertex in vor.vertices:
    x, y = vertex
    if x_min < x < x_max and y_min < y < y_max:
        interior_vertices.append(vertex)
interior_vertices = np.array(interior_vertices)

# 2. 计算Voronoi边与矩形边界的交点
def segment_rectangle_intersection(seg_start, seg_end, rect):
    # rect参数格式: (x_min, x_max, y_min, y_max)
    x_min_r, x_max_r, y_min_r, y_max_r = rect
    intersections = []
    
    # 检查线段与矩形四条边的交点
    # 左边界x=x_min_r
    if (seg_start[0] < x_min_r and seg_end[0] > x_min_r) or (seg_start[0] > x_min_r and seg_end[0] < x_min_r):
        t = (x_min_r - seg_start[0]) / (seg_end[0] - seg_start[0])
        y = seg_start[1] + t * (seg_end[1] - seg_start[1])
        if y_min_r <= y <= y_max_r:
            intersections.append([x_min_r, y])
    # 右边界x=x_max_r
    if (seg_start[0] < x_max_r and seg_end[0] > x_max_r) or (seg_start[0] > x_max_r and seg_end[0] < x_max_r):
        t = (x_max_r - seg_start[0]) / (seg_end[0] - seg_start[0])
        y = seg_start[1] + t * (seg_end[1] - seg_start[1])
        if y_min_r <= y <= y_max_r:
            intersections.append([x_max_r, y])
    # 下边界y=y_min_r
    if (seg_start[1] < y_min_r and seg_end[1] > y_min_r) or (seg_start[1] > y_min_r and seg_end[1] < y_min_r):
        t = (y_min_r - seg_start[1]) / (seg_end[1] - seg_start[1])
        x = seg_start[0] + t * (seg_end[0] - seg_start[0])
        if x_min_r <= x <= x_max_r:
            intersections.append([x, y_min_r])
    # 上边界y=y_max_r
    if (seg_start[1] < y_max_r and seg_end[1] > y_max_r) or (seg_start[1] > y_max_r and seg_end[1] < y_max_r):
        t = (y_max_r - seg_start[1]) / (seg_end[1] - seg_start[1])
        x = seg_start[0] + t * (seg_end[0] - seg_start[0])
        if x_min_r <= x <= x_max_r:
            intersections.append([x, y_max_r])
    
    return np.array(intersections)

boundary_intersections = []
# 遍历所有Voronoi边(跳过无穷远边)
for ridge in vor.ridge_vertices:
    v1, v2 = ridge
    if v1 == -1 or v2 == -1:
        continue
    seg_start = vor.vertices[v1]
    seg_end = vor.vertices[v2]
    # 计算当前边与矩形的交点
    inters = segment_rectangle_intersection(seg_start, seg_end, (x_min, x_max, y_min, y_max))
    if len(inters) > 0:
        boundary_intersections.extend(inters)
boundary_intersections = np.array(boundary_intersections)

# 3. 可视化结果
fig, ax = plt.subplots(figsize=(8,8))
# 绘制原始Voronoi图
voronoi_plot_2d(vor, ax=ax, show_vertices=False, line_colors='gray', line_width=1)
# 绘制矩形边界
rect = plt.Rectangle((x_min, y_min), x_max-x_min, y_max-y_min, fill=False, edgecolor='black', linewidth=2)
ax.add_patch(rect)
# 标记内部Voronoi顶点(蓝色)
if len(interior_vertices) > 0:
    ax.scatter(interior_vertices[:,0], interior_vertices[:,1], c='blue', s=50, zorder=5, label='内部顶点')
# 标记边界交点(红色,对应附图中的红圈)
if len(boundary_intersections) > 0:
    ax.scatter(boundary_intersections[:,0], boundary_intersections[:,1], c='red', s=50, zorder=5, label='边界交点')
ax.set_xlim(x_min-0.5, x_max+0.5)
ax.set_ylim(y_min-0.5, y_max+0.5)
ax.legend()
plt.show()

# 输出结果
print("内部Voronoi顶点:\n", interior_vertices)
print("\n边界交点:\n", boundary_intersections)

关键说明

  • 内部顶点筛选:默认严格判断顶点在矩形内部,若需要包含边界上的点,可将判断条件中的<改为<=
  • 边界交点计算:通过线段跨边判断+线性插值计算交点,确保交点落在矩形的四条边上
  • 可视化验证:用蓝色标记内部顶点,红色标记边界交点,直观确认结果准确性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:50:43