公交站点方向的计算

# 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)
原文地址:https://www.cnblogs.com/ddzhen/p/14958139.html