随多边形尺寸变化动态缩放内部填充圆的技术需求
动态调整多边形内填充圆半径以适配尺寸
我目前使用Shapely库创建多边形,并在内部按固定半径和间距生成填充圆,现有实现代码如下:
import matplotlib.pyplot as plt from shapely.geometry import Polygon, Point import numpy as np def pack_circles_inside_polygon(polygon, radius, distance): circles = [] # 计算行列可容纳的圆数量 num_rows = int((polygon.bounds[3] - polygon.bounds[1] - 2 * radius) / (2 * radius + distance)) + 1 num_cols = int((polygon.bounds[2] - polygon.bounds[0] - 2 * radius) / (2 * radius + distance)) + 1 # 生成圆心坐标并筛选在多边形内的圆 for i in range(num_rows): for j in range(num_cols): x = polygon.bounds[0] + (2 * radius + distance) * j + radius y = polygon.bounds[1] + (2 * radius + distance) * i + radius center = Point(x, y) if polygon.contains(center.buffer(radius)): circle = center.buffer(radius) circles.append(circle) return circles # 原多边形与参数设置 polygon_vertices = [(2, 2), (5, 8), (10, 6), (7, 1)] polygon = Polygon(polygon_vertices) radius = 0.5 distance = 0.5 polygon2 = polygon.buffer(-distance, join_style=2) # 生成填充圆并可视化 circles = pack_circles_inside_polygon(polygon2, radius, distance) fig, ax = plt.subplots() x, y = polygon.exterior.xy ax.plot(x, y, color='blue', alpha=0.7, linewidth=2, solid_capstyle='round') ax.fill(x, y, color='blue', alpha=0.3) for circle in circles: x, y = circle.exterior.xy ax.plot(x, y, color='red', alpha=0.5) ax.set_aspect('equal', 'datalim') plt.xlabel('X') plt.ylabel('Y') plt.title('Circles Packed Inside Polygon') plt.grid(True) plt.show()
接下来需要基于原多边形生成多个变体多边形,核心需求是:当变体多边形尺寸与原多边形不同时,动态调整填充圆的半径,使圆的大小适配多边形尺寸。例如原多边形可容纳N个圆,若变体多边形无法容纳同半径同间距的N个圆,则减小圆半径,实现圆随多边形尺寸缩放的效果。
实现方案
核心逻辑
- 先计算原多边形能容纳的目标圆数量,以此为适配基准
- 保持圆间距与半径的比例(原设置中
distance/radius=1,动态调整时该比例不变) - 对变体多边形,从原半径开始逐步缩小半径,直到能容纳目标数量的圆,或达到预设的最小半径阈值
修改后的完整代码
import matplotlib.pyplot as plt from shapely.geometry import Polygon, Point import numpy as np def pack_circles_inside_polygon(polygon, radius, distance): circles = [] spacing = 2 * radius + distance # 计算行列可容纳的圆数量 num_rows = int((polygon.bounds[3] - polygon.bounds[1] - 2 * radius) / spacing) + 1 num_cols = int((polygon.bounds[2] - polygon.bounds[0] - 2 * radius) / spacing) + 1 # 生成圆心坐标并筛选在多边形内的圆 for i in range(num_rows): for j in range(num_cols): x = polygon.bounds[0] + spacing * j + radius y = polygon.bounds[1] + spacing * i + radius center = Point(x, y) if polygon.contains(center.buffer(radius)): circles.append(center.buffer(radius)) return circles def get_target_circle_count(original_polygon, original_radius, original_distance): # 计算原多边形的目标圆数量 buffered_poly = original_polygon.buffer(-original_distance, join_style=2) circles = pack_circles_inside_polygon(buffered_poly, original_radius, original_distance) return len(circles) def adjust_radius_for_variant(variant_polygon, target_count, original_radius, original_distance, min_radius=0.1): # 保持间距与半径的比例 spacing_ratio = original_distance / original_radius current_radius = original_radius buffered_variant = variant_polygon.buffer(-(current_radius * spacing_ratio), join_style=2) # 迭代调整半径,直到满足数量要求或达到最小半径 while current_radius >= min_radius: circles = pack_circles_inside_polygon(buffered_variant, current_radius, current_radius * spacing_ratio) if len(circles) >= target_count: return current_radius, circles # 每次减小10%的半径 current_radius *= 0.9 buffered_variant = variant_polygon.buffer(-(current_radius * spacing_ratio), join_style=2) # 达到最小半径时返回当前结果 return current_radius, pack_circles_inside_polygon(buffered_variant, current_radius, current_radius * spacing_ratio) # ------------------------------ # 示例:原多边形与变体多边形测试 # ------------------------------ # 原多边形设置 original_vertices = [(2, 2), (5, 8), (10, 6), (7, 1)] original_polygon = Polygon(original_vertices) original_radius = 0.5 original_distance = 0.5 # 获取目标圆数量 target_count = get_target_circle_count(original_polygon, original_radius, original_distance) print(f"原多边形可容纳圆数量: {target_count}") # 生成一个缩小的变体多边形(各顶点坐标乘以0.7) variant_vertices = [(x*0.7, y*0.7) for x, y in original_vertices] variant_polygon = Polygon(variant_vertices) # 动态调整半径并生成填充圆 adjusted_radius, variant_circles = adjust_radius_for_variant(variant_polygon, target_count, original_radius, original_distance) print(f"变体多边形适配后的圆半径: {round(adjusted_radius, 3)}") print(f"变体多边形实际容纳圆数量: {len(variant_circles)}") # 可视化原多边形与变体多边形的填充效果 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6)) # 原多边形可视化 x, y = original_polygon.exterior.xy ax1.plot(x, y, color='blue', alpha=0.7, linewidth=2) ax1.fill(x, y, color='blue', alpha=0.3) original_circles = pack_circles_inside_polygon(original_polygon.buffer(-original_distance, join_style=2), original_radius, original_distance) for circle in original_circles: cx, cy = circle.exterior.xy ax1.plot(cx, cy, color='red', alpha=0.5) ax1.set_aspect('equal') ax1.set_title(f"原多边形 (半径={original_radius})") ax1.grid(True) # 变体多边形可视化 x, y = variant_polygon.exterior.xy ax2.plot(x, y, color='green', alpha=0.7, linewidth=2) ax2.fill(x, y, color='green', alpha=0.3) for circle in variant_circles: cx, cy = circle.exterior.xy ax2.plot(cx, cy, color='orange', alpha=0.5) ax2.set_aspect('equal') ax2.set_title(f"变体多边形 (适配半径={round(adjusted_radius,3)})") ax2.grid(True) plt.tight_layout() plt.show()
关键说明
get_target_circle_count:计算原多边形的基准圆数量,作为变体多边形的适配目标adjust_radius_for_variant:通过迭代缩小半径(每次减少10%),保持间距与半径的比例不变,直到变体多边形能容纳目标数量的圆- 可通过调整
min_radius参数设置最小允许半径,避免半径过小失去实际意义
内容的提问来源于stack exchange,提问作者Vismaya Hostcurator
相关产品推荐
相关产品推荐

