# coding:utf-8
import numpy as np
import logging
logging.basicConfig(level=logging.WARNING,
format='%(asctime)s-%(filename)s[line:%(lineno)d]-%(levelname)s:%(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
from shapely.ops import split, nearest_points, snap
from shapely.geometry import LineString, Point
class vectorAngle():
def vecAttr(self, x, y):
# 判断点所在的象限
# N
# W O E
# S
ref = 0.
if x == ref:
if y == ref:
res = 'OO'
elif y > ref:
res = 'ON'
else:
res = 'OS'
elif x > ref:
if y == ref:
res = 'OE'
elif y > ref:
res = 'EN'
else:
res = "ES"
else:
if y == ref:
res = "OW"
elif y > ref:
res = "WN"
else:
res = "WS"
return res
def vecAngle(self, x, y):
flag = self.vecAttr(x, y)
if flag == "OO":
angle = 0.
elif flag == "OE":
angle = 0.
elif flag == "EN":
angle = np.arctan(y/x)
elif flag == "ON":
angle = np.pi / 2
elif flag == "WN":
angle = np.pi - np.arctan(abs(y/x))
elif flag == "OW":
angle = np.pi
elif flag == "WS":
angle = np.pi + np.arctan(abs(y/x))
elif flag == "OS":
angle = np.pi * 1.5
else:
angle = np.pi * 2.0 - np.arctan(abs(y/x))
return round(angle, 3)
class stopAngle(vectorAngle):
# func 用于计算站点的方向
def __init__(self, busline):
# busline, 公交线路描点
dtype = busline.__class__
if dtype is list:
self.line = LineString(busline)
elif dtype is LineString:
self.line = busline
else:
logging.warning(f"busline coords error:{busline}")
def splitLine(self, stop):
# 在站点处打断公交线路
# para: stop -> Point()
p1, pr = nearest_points(self.line, stop)
line_ = snap(self.line, p1, 0.0001)
l1, l2 = split(line_, p1)
return l1, l2
def stopAngle(self, stop):
# 获取站点的方向
p1, pr = nearest_points(self.line, stop)
line_ = snap(self.line, p1, 0.0001)
l1, l2 = split(line_, p1)
pline = line_.intersection(p1.buffer(0.1))
vec = np.array(pline.coords[-1]) - np.array(pline.coords[0])
angle = self.vecAngle(vec[0], vec[1])
if 0 <= angle <= np.pi/4:
prompt = "ED"
elif np.pi/4 < angle <= 3*np.pi/4:
prompt = "NU"
elif 3*np.pi/4 < angle <= 5*np.pi/4:
prompt = "WU"
elif 5*np.pi/4 < angle <= 7*np.pi/4:
prompt = "SD"
else:
prompt = "ED"
return prompt
if __name__ == "__main__":
line = LineString(([0, 0], [2, 0], [2, 2], [0, 2], [0, 0]))
pnts = [[1,0.0], [2,0], [1,2.1], [0.1,1]]
stops = [Point(_)for _ in pnts]
obj = stopAngle(line)
for stop in stops:
flag = obj.stopAngle(stop)
logging.warning(flag)