给定地图上的区域(用多边形顶点的经纬度表示), 需要用正多边形(三角形/正方形/六边形)对地图上的区域进行填充. 在一些实际应用中, 这样做的是为了划分标准的作业单元, 例如定义共享自行车的骑行范围, 物流的配送范围, 外卖骑手的接单范围等.
效果如下(杭州市西湖区: 六边形半径1000米).
问题描述
给定地图区域边界顶点的集合V={(x1,y1),(x2,y2),…,(xn,yn)}V={(x1,y1),(x2,y2),…,(xn,yn)}V=\{(x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n)\}V={(x1,y1),(x2,y2),…,(xn,yn)}. 用正多边形对VVVV定义的区域进行分割. 为了保证正多边形恰好填满平面, 可选的正多边形为三角形, 四边形, 六边形.
正多边形
给定正kkkk边形的中心点(x0,y0)(x0,y0)(x_0, y_0)(x0,y0)和初始角度θθ\thetaθ(如下图所示).
用(xi,yi)(xi,yi)(x_i, y_i)(xi,yi)代表其顶点坐标, 我们有:
xi=x0+r⋅cos(2π(ik+θ360))yi=y0+r⋅sin(2π(ik+θ360)).xi=x0+r⋅cos(2π(ik+θ360))yi=y0+r⋅sin(2π(ik+θ360)).\begin{aligned}& x_i = x_0 + r \cdot \cos\left(2\pi \left(\frac{i}{k} + \frac{\theta}{360}\right)\right) \\& y_i = y_0 + r\cdot \sin\left(2\pi \left(\frac{i}{k} + \frac{\theta}{360}\right)\right).\end{aligned}xi=x0+r⋅cos(2π(ki+360θ))yi=y0+r⋅sin(2π(ki+360θ)).
为了方便后面的计算, 先定义一个PolyGetter的类用来生成正多边形对象.
#poly_getter.py
import math
from shapely.geometry import Polygon, Point
class PolyGetter(object):
""" 生成正多边形对象
"""
def __init__(self, radius, k, theta=0):
self.radius = radius
self.k = k # 正多边形的边数
self.theta = theta # 起始角度: degree
def fr