点和线的扇形缓冲
from shapely.ops import substring
from shapely.geometry import LineString, Polygon
from math import pi
import numpy as np
import logging
logging.basicConfig(level=logging.WARNING,
format='%(asctime)s-%(filename)s[line:%(lineno)d]-%(levelname)s:%(message)s',
datefmt='%H:%M:%S')
def pnt2polar(p):
x, y = p
length = np.sqrt(x * x + y * y)
x = round(x, 6)
y = round(y, 6)
alpha = np.arctan(abs(y / x)) if x != 0. else 0.
if x > 0:
if y > 0:
angle = alpha
elif y == 0:
angle = 0
else:
angle = pi * 2 - alpha
elif x == 0:
if y > 0:
angle = pi / 2
elif y == 0:
angle = 0
else:
angle = 3 * pi / 2
else:
if y > 0:
angle = pi - alpha
elif y == 0:
angle = pi
else:
angle = pi + alpha
return round(length, 3), round(angle, 3)
def polar2pnt(p):
length, angle = p
eps = 1e-8
if length == 0:
x, y = 0
else:
if angle < eps:
x = length
y = 0
elif angle - 3 * pi / 2 > eps:
x = length * np.cos(2 * pi - angle)
y = -length * np.sin(2 * pi - angle)
elif angle - 3 * pi / 2 == eps:
x = 0
y = length
elif angle - pi > eps:
x = -length * np.cos(angle - pi)
y = -length * np.sin(angle - pi)
elif angle - pi == eps:
x = -length
y = 0
elif angle - pi / 2 > eps:
x = -length * np.cos(pi - angle)
y = length * np.sin(pi - angle)
elif angle - pi / 2 == eps:
x = 0
y = -length
else:
x = length * np.cos(angle)
y = length * np.sin(angle)
return round(x, 3), round(y, 3)
def arcPointBuffer(p, r, fangle, tangle):
if tangle > fangle:
angles = np.linspace(fangle, tangle, num=64)
else:
angles = np.linspace(fangle, 2*pi, num=32)
angles_ = np.linspace(0, tangle, num=32)
angles = np.r_[angles, angles_]
polars = np.c_[[r] * 64, angles]
vector = [polar2pnt(_) for _ in polars]
x, y = np.array(p).tolist()
vector = [[x+i, y+j] for i, j in vector]
ply = [[x, y]] + vector + [[x, y]]
return Polygon(ply)
def arcLineBuffer(geom, r, arc):
length = geom.length
if length < r:
fl = geom
else:
fl = substring(geom, length-r, length)
ps, pe = fl.coords[0], fl.coords[-1]
vec = pe[0]-ps[0], pe[1]-ps[1]
logging.warning(f"vec:{vec}")
lgth, angle = pnt2polar(vec)
fangle = angle - arc/2
tangle = angle + arc/2
if fangle < 0:
fangle = 2*pi - (arc/2 - angle)
if tangle > 2*pi:
tangle = tangle - pi*2
logging.warning(f"angle:{angle:.3f}")
logging.warning(f"ftangle:{fangle:.3f},{tangle:.3f}")
res = arcPointBuffer(pe, lgth, fangle, tangle)
return res
if __name__ == '__main__':
ls = LineString([[0, 0], [10, 0]])
arc = pi/4
res = arcLineBuffer(ls, 2, arc)
res = arcPointBuffer((10, 0), 1, 0, arc)