如何用与多边形最长边平行的等距直线填充多边形?
多边形内生成平行于最长边的等距直线通用解决方案
核心思路
要解决这个问题,关键是基于最长边的法向量方向生成等距直线,再通过直线与多边形边的交点确定内部线段,步骤如下:
- 确定最长边的方向与法向量
- 计算多边形在法向量方向上的投影范围,确定直线生成区间
- 生成每条平行直线的方程
- 求直线与多边形的所有交点,筛选出有效线段
代码实现(通用版)
import matplotlib.pyplot as plt import numpy as np from shapely.geometry import LineString, Polygon from shapely.ops import split def longest_side(points): """返回最长边的两个端点及长度""" max_len = 0 longest = None n = len(points) for i in range(n): p1 = np.array(points[i]) p2 = np.array(points[(i+1)%n]) # 处理闭合多边形的最后一条边 length = np.linalg.norm(p1 - p2) if length > max_len: max_len = length longest = (p1, p2) return longest def generate_parallel_lines(polygon_points, spacing): """生成多边形内部与最长边平行的等距直线线段""" # 1. 创建Shapely多边形对象(处理闭合、顶点顺序问题) poly = Polygon(polygon_points) if not poly.is_valid: raise ValueError("输入的多边形无效,请检查顶点顺序或是否自交") # 2. 获取最长边及方向、法向量 p1, p2 = longest_side(polygon_points) dir_vec = p2 - p1 # 最长边的方向向量 # 计算单位法向量(垂直于最长边的方向,用于偏移生成平行直线) norm_vec = np.array([-dir_vec[1], dir_vec[0]]) norm_vec = norm_vec / np.linalg.norm(norm_vec) # 3. 计算多边形所有顶点在法向量方向上的投影,确定偏移范围 projections = [np.dot(np.array(p), norm_vec) for p in polygon_points] min_proj = min(projections) max_proj = max(projections) # 4. 生成等距平行直线 line_segments = [] # 从最小投影到最大投影,按间距生成每条直线的偏移量 for offset in np.arange(min_proj, max_proj + spacing, spacing): # 构造平行于最长边的直线:沿法向量偏移offset的直线 # 取最长边的两个端点分别沿法向量偏移offset,得到直线上的两个点 line_p1 = p1 + offset * norm_vec line_p2 = p2 + offset * norm_vec line = LineString([line_p1, line_p2]) # 5. 求直线与多边形的交点,得到内部线段 intersection = poly.intersection(line) if intersection.geom_type == 'LineString': coords = list(intersection.coords) line_segments.append(coords) elif intersection.geom_type == 'MultiLineString': for seg in intersection.geoms: line_segments.append(list(seg.coords)) return line_segments if __name__ == "__main__": # 测试多边形顶点(闭合) points = ([0, 8], [2, 10], [10, 4], [10, 0], [0, 8]) # 生成平行直线线段 segments = generate_parallel_lines(points, spacing=1) # 绘制多边形 x = [p[0] for p in points] y = [p[1] for p in points] plt.plot(x, y, 'ro-', label='多边形') # 绘制内部平行直线 for seg in segments: seg_x = [p[0] for p in seg] seg_y = [p[1] for p in seg] plt.plot(seg_x, seg_y, 'b-') plt.axis('scaled') plt.legend() plt.show()
关键细节说明
- 使用Shapely库简化几何计算:无需手动实现直线与多边形的交点逻辑,Shapely的
intersection方法可以直接得到直线在多边形内部的线段,避免了复杂的边界判断。 - 法向量方向的正确性:法向量是垂直于最长边的方向,沿这个方向偏移才能生成等距的平行直线,单位化后偏移量的单位就是实际的间距。
- 处理多边形有效性:先检查多边形是否有效(非自交、顶点顺序正确),避免后续计算出错。
- 覆盖整个多边形范围:通过顶点在法向量上的投影极值,确保生成的直线覆盖多边形的全部区域,不会遗漏或超出。
适配任意多边形的注意事项
- 输入的多边形顶点必须是闭合的(最后一个顶点和第一个顶点相同),如果不闭合,代码中可以自动补充。
- 支持简单多边形(非自交),如果是自交多边形,需要先处理为简单多边形再进行计算。
- 间距参数可以根据需求调整,注意如果间距过大,可能会跳过部分区域,过小则会生成过多线段。
内容的提问来源于stack exchange,提问作者Son.Dre
相关产品推荐
相关产品推荐

