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

如何在正方形区域内无重叠均匀分布几何对象?

优化正方形内对象均匀无重叠分布的代码

现有一个10×10的正方形区域,包含3个方形对象(obj_1st)和3个三角形对象(obj_2nd),需求是让这些对象在正方形内均匀分布且无重叠。原代码仅解决了重叠问题,但存在对象分布不均、视觉效果差的问题,同时边界处理逻辑存在漏洞。

输入数据

import numpy as np

square = np.array([[0, 0, 0, 0, 10, 0, 10, 10, 0, 10, 0, 0, 0, 0, 0]])

obj_1st = np.array([
    [1.0, 8.0, 0, 3.0, 8.0, 0, 3.0, 6.0, 0, 1.0, 6.0, 0, 1.0, 8.0, 0], 
    [6.0, 7.0, 0, 8.0, 7.0, 0, 8.0, 5.0, 0, 6.0, 5.0, 0, 6.0, 7.0, 0], 
    [3.0, 4.0, 0, 5.0, 4.0, 0, 5.0, 2.0, 0, 3.0, 2.0, 0, 3.0, 4.0, 0]
])

obj_2nd = np.array([
    [2.0, 3.0, 0, 3.0, 4.0, 0, 4.0, 3.0, 0, 2.0, 3.0, 0], 
    [2.0, 6.0, 0, 3.0, 7.0, 0, 4.0, 6.0, 0, 2.0, 6.0, 0], 
    [7.0, 3.0, 0, 8.0, 4.0, 0, 9.0, 3.0, 0, 7.0, 3.0, 0]
])

优化后的代码

import numpy as np
import matplotlib.pyplot as plt

# 计算对象的包围盒(min_x, max_x, min_y, max_y, center_x, center_y, width, height)
def get_bounding_box(obj):
    x_coords = obj[:, 0::3].flatten()
    y_coords = obj[:, 1::3].flatten()
    min_x = np.min(x_coords)
    max_x = np.max(x_coords)
    min_y = np.min(y_coords)
    max_y = np.max(y_coords)
    center_x = (min_x + max_x) / 2
    center_y = (min_y + max_y) / 2
    width = max_x - min_x
    height = max_y - min_y
    return (min_x, max_x, min_y, max_y, center_x, center_y, width, height)

# 检查两个对象是否重叠(含最小间距)
def are_objects_overlapping(obj1, obj2, min_gap=0.5):
    b1 = get_bounding_box(obj1)
    b2 = get_bounding_box(obj2)
    # 分离轴定理判断,加入最小间距
    return not (b1[1] + min_gap < b2[0] or b1[0] > b2[1] + min_gap or 
                b1[3] + min_gap < b2[2] or b1[2] > b2[3] + min_gap)

# 移动对象
def move_object(obj, vector):
    obj[:, 0::3] += vector[0]
    obj[:, 1::3] += vector[1]
    return obj

# 将对象限制在正方形内
def clamp_to_square(obj, square_size=10):
    bbox = get_bounding_box(obj)
    min_x, max_x, min_y, max_y = bbox[0], bbox[1], bbox[2], bbox[3]
    dx, dy = 0, 0
    
    # X轴边界修正
    if min_x < 0:
        dx = -min_x
    elif max_x > square_size:
        dx = square_size - max_x
    
    # Y轴边界修正
    if min_y < 0:
        dy = -min_y
    elif max_y > square_size:
        dy = square_size - max_y
    
    if dx != 0 or dy != 0:
        move_object(obj, (dx, dy))
    return obj

# 初始化均匀分布位置
def initialize_uniform_distribution(objects, square_size=10):
    total_objects = sum(len(obj_grp) for obj_grp in objects)
    # 按2x3网格分配6个对象
    grid_cols = 3
    grid_rows = 2
    cell_width = square_size / grid_cols
    cell_height = square_size / grid_rows
    
    idx = 0
    for obj_grp in objects:
        for obj in obj_grp:
            # 计算目标网格中心
            col = idx % grid_cols
            row = idx // grid_cols
            target_center_x = (col + 0.5) * cell_width
            target_center_y = (row + 0.5) * cell_height
            
            # 移动对象到目标中心
            bbox = get_bounding_box(obj)
            current_center_x, current_center_y = bbox[4], bbox[5]
            move_vec = (target_center_x - current_center_x, target_center_y - current_center_y)
            move_object(obj, move_vec)
            
            # 修正边界
            clamp_to_square(obj, square_size)
            idx += 1

# 主分布算法
def distribute_objects(objects, square_size=10, max_iterations=100, min_gap=0.5):
    # 先初始化均匀分布
    initialize_uniform_distribution(objects, square_size)
    
    iteration = 0
    while iteration < max_iterations:
        has_overlap = False
        # 整理所有对象到列表
        all_objects = []
        for grp in objects:
            all_objects.extend(grp)
        
        for i in range(len(all_objects)):
            for j in range(i+1, len(all_objects)):
                obj1 = all_objects[i]
                obj2 = all_objects[j]
                if are_objects_overlapping(obj1, obj2, min_gap):
                    has_overlap = True
                    # 获取两个对象的中心
                    b1 = get_bounding_box(obj1)
                    b2 = get_bounding_box(obj2)
                    center1 = np.array([b1[4], b1[5]])
                    center2 = np.array([b2[4], b2[5]])
                    
                    # 计算排斥方向和距离
                    direction = center1 - center2
                    distance = np.linalg.norm(direction)
                    if distance == 0:
                        direction = np.array([np.random.uniform(-1,1), np.random.uniform(-1,1)])
                        distance = np.linalg.norm(direction)
                    
                    # 计算需要移动的距离(确保分开到最小间距)
                    required_distance = (b1[6]/2 + b2[6]/2 + min_gap) + (b1[7]/2 + b2[7]/2 + min_gap)
                    move_distance = required_distance - distance
                    if move_distance < 0:
                        move_distance = 0
                    
                    # 归一化方向,加入衰减因子避免过度移动
                    move_vec = (direction / distance) * move_distance * 0.5
                    
                    # 移动两个对象
                    move_object(obj1, move_vec)
                    move_object(obj2, -move_vec)
                    
                    # 修正边界
                    clamp_to_square(obj1, square_size)
                    clamp_to_square(obj2, square_size)
        
        if not has_overlap:
            break
        iteration += 1

# 绘图函数
def plot_scene(square, objects):
    plt.figure(figsize=(8, 8))
    # 绘制正方形
    sq_x = square[0][0::3]
    sq_y = square[0][1::3]
    plt.plot(sq_x, sq_y, color='black', linewidth=2, label='Square')
    
    # 绘制方形对象
    for obj in obj_1st:
        x = obj[0::3]
        y = obj[1::3]
        plt.plot(x, y, color='blue', linewidth=1.5, label='Square Object' if obj is obj_1st[0] else "")
    
    # 绘制三角形对象
    for obj in obj_2nd:
        x = obj[0::3]
        y = obj[1::3]
        plt.plot(x, y, color='red', linewidth=1.5, label='Triangle Object' if obj is obj_2nd[0] else "")
    
    plt.title('Uniformly Distributed Objects without Overlapping')
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.grid(True)
    plt.axis('equal')
    plt.legend()
    plt.show()

# 执行分布并绘图
if __name__ == "__main__":
    square = np.array([[0, 0, 0, 0, 10, 0, 10, 10, 0, 10, 0, 0, 0, 0, 0]])
    obj_1st = np.array([
        [1.0, 8.0, 0, 3.0, 8.0, 0, 3.0, 6.0, 0, 1.0, 6.0, 0, 1.0, 8.0, 0], 
        [6.0, 7.0, 0, 8.0, 7.0, 0, 8.0, 5.0, 0, 6.0, 5.0, 0, 6.0, 7.0, 0], 
        [3.0, 4.0, 0, 5.0, 4.0, 0, 5.0, 2.0, 0, 3.0, 2.0, 0, 3.0, 4.0, 0]
    ])
    obj_2nd = np.array([
        [2.0, 3.0, 0, 3.0, 4.0, 0, 4.0, 3.0, 0, 2.0, 3.0, 0], 
        [2.0, 6.0, 0, 3.0, 7.0, 0, 4.0, 6.0, 0, 2.0, 6.0, 0], 
        [7.0, 3.0, 0, 8.0, 4.0, 0, 9.0, 3.0, 0, 7.0, 3.0, 0]
    ])
    
    objects = [obj_1st, obj_2nd]
    distribute_objects(objects)
    plot_scene(square, objects)

优化说明

  • 均匀初始化:将6个对象分配到2×3的网格中,每个对象初始位于网格中心,从根源避免堆积
  • 精确重叠判断:使用包围盒+最小间距的分离轴定理,确保对象间有合理空隙
  • 智能排斥移动:基于对象中心距离计算移动向量,加入衰减因子避免过度移动,同时保证对象分开到安全距离
  • 修复边界处理:直接修改原对象的坐标,确保边界修正生效
  • 收敛控制:设置最大迭代次数,避免无限循环

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:37:02