python地铁路线可视化 您所在的位置:网站首页 广州三号线各站点分布图片 python地铁路线可视化

python地铁路线可视化

2023-12-25 08:49| 来源: 网络整理| 查看: 265

目录 事前准备绘制地铁站点路线图利用百度api获取地铁站点坐标[^1]经纬度坐标系的转换[^2]绘制地铁路线图[^3]设置地图默认语言为中文[^4] 绘制精细地铁线路图利用百度api获取精细地铁线路百度墨卡托(BD-09MC)坐标[^1]提取地铁路线经纬度坐标序列绘制地铁路线图

事前准备 需要安装的第三方库:plotly、requests、numpy由于plotly使用的地图api是mapbox,我们需要先注册一个mapbox的账号,之后可在Account界面下获取一个token备用,也可直接使用我代码中所用的token而无需注册 绘制地铁站点路线图 利用百度api获取地铁站点坐标1

  百度地图获取城市地铁站点信息的api为http://map.baidu.com/?qt=bsi&c={城市编号}&t={13位时间戳},这里附上百度地图城市编号文件:BaiduMap_cityCode

  有了api之后,我们以广州为例,获取广州所有地铁站点信息,代码如下

import requests import time null = None #将json中的null定义为None city_code = 257 #广州的城市编号 station_info = requests.get('http://map.baidu.com/?qt=bsi&c=%s&t=%s' % ( city_code, int(time.time() * 1000) ) ) station_info_json = eval(station_info.content) #将json字符串转为python对象

  这样处理以后我们会得到json格式的字典,其中键名为content的内容是我们感兴趣的线路信息字典组成的列表,其中每一个字典为一条线路的信息,现给出线路字典的键值信息如下

键名描述数据类型line_name线路名strline_uid线路uidstrpair_line_uid反向线路uidstrstops站点信息dict  而每一个站点信息字典的键值信息如下键名描述数据类型:-::-::-:is_practical未知intname站点名字struid站点uidstrx站点百度墨卡托x坐标floaty站点百度墨卡托y坐标float  这样我们可提取出我们所需的各条地铁线路的站点名及百度墨卡托(BD-09MC)坐标,代码如下 for line in station_info_json['content']: plots = [] plots_name = [] for plot in line['stops']: plots.append([plot['x'], plot['y']]) plots_name.append(plot['name']) plot_mercator = np.array(plots) #...... 经纬度坐标系的转换2

  由于mapbox采用WGS-84坐标系,我们还得将提取出的BD-09MC坐标转换为WGS-84坐标系下的经纬度,要做到这一点,我们先将BD-09MC坐标转换到BD-09坐标系(百度的另一个坐标系)下,再转到GCJ-02坐标系(国内常用的坐标系)下,之后才能转换到WGS-84坐标系下,关于这几个坐标系就不在此赘述了,下面提供几个转换函数

import numpy as np import math PI = math.pi def _transformlat(coordinates): lng = coordinates[ : , 0] - 105 lat = coordinates[ : , 1] - 35 ret = -100 + 2 * lng + 3 * lat + 0.2 * lat * lat + \ 0.1 * lng * lat + 0.2 * np.sqrt(np.fabs(lng)) ret += (20 * np.sin(6 * lng * PI) + 20 * np.sin(2 * lng * PI)) * 2 / 3 ret += (20 * np.sin(lat * PI) + 40 * np.sin(lat / 3 * PI)) * 2 / 3 ret += (160 * np.sin(lat / 12 * PI) + 320 * np.sin(lat * PI / 30.0)) * 2 / 3 return ret def _transformlng(coordinates): lng = coordinates[ : , 0] - 105 lat = coordinates[ : , 1] - 35 ret = 300 + lng + 2 * lat + 0.1 * lng * lng + \ 0.1 * lng * lat + 0.1 * np.sqrt(np.fabs(lng)) ret += (20 * np.sin(6 * lng * PI) + 20 * np.sin(2 * lng * PI)) * 2 / 3 ret += (20 * np.sin(lng * PI) + 40 * np.sin(lng / 3 * PI)) * 2 / 3 ret += (150 * np.sin(lng / 12 * PI) + 300 * np.sin(lng / 30 * PI)) * 2 / 3 return ret def gcj02_to_wgs84(coordinates): """ GCJ-02转WGS-84 :param coordinates: GCJ-02坐标系的经度和纬度的numpy数组 :returns: WGS-84坐标系的经度和纬度的numpy数组 """ ee = 0.006693421622965943 # 偏心率平方 a = 6378245 # 长半轴 lng = coordinates[ : , 0] lat = coordinates[ : , 1] is_in_china= (lng > 73.66) & (lng 3.86) & (lat

  如图所示 添加引用 3. 在代码中搜索”Map({“(如果使用正则表达式要注意加上转义),找到定义Map的地方,在后面添加如下代码

p.addControl(new MapboxLanguage({ defaultLanguage: 'zh' })); //p是定义为Map类型的变量

  如图所示 设置默认语言为中文

  这样修改之后打开该html文件就能以中文地名显示了,可视化效果如下

地铁路线图   这时候可能有挑剔的小伙伴会说:“这地铁路线图看上去好假啊喂(嫌弃)。“那么接下来我们再来绘制更加精细的地铁路线图。

绘制精细地铁线路图 利用百度api获取精细地铁线路百度墨卡托(BD-09MC)坐标1

  百度地图获取城市精细地铁线路坐标的api为https://map.baidu.com/?qt=bsl&tps=&newmap=1&uid={地铁线路uid}&c={城市编号},获取广州精细地铁线路坐标的代码如下

import requests import time null = None #将json中的null定义为None city_code = 257 #广州的城市编号 station_info = requests.get('http://map.baidu.com/?qt=bsi&c=%s&t=%s' % ( city_code, int(time.time() * 1000) ) ) station_info_json = eval(station_info.content) #将json字符串转为python对象 for railway in station_info_json['content']: uid = railway['line_uid'] railway_json = requests.get( 'https://map.baidu.com/?qt=bsl&tps=&newmap=1&uid=%s&c=%s' % (uid, city_id) ) railway_json = eval(railway_json.content) #将json字符串转为python对象 #......

  这样做之后我们同样得到了一个字典,键名为content的内容是长度为1的保存了线路信息字典的列表,现给出线路信息字典的部分键值信息如下

键名描述数据类型geo整条线路坐标信息,以 ”|“ 为分隔符分为三部分,第三部分为该线路有序的BD-09MC坐标,格式为" x 1 , y 1 , x 2 , y 2 , . . . , x n , y n ; x_1,y_1,x_2,y_2,...,x_n,y_n; x1​,y1​,x2​,y2​,...,xn​,yn​;"strstations具体站点信息listuid地铁路线uidstrlineColor线路16进制RGBstr 提取地铁路线经纬度坐标序列

  有了上面获取到的字典,我们可以提取出里面的BD-09MC坐标并转换成WGS-84坐标,代码如下

trace_mercator = np.array( # 取出线路信息字典,以“|”划分后,取出第三部分信息,去掉末尾的“;”,获取BD-09MC坐标序列 railway_json['content'][0]['geo'].split('|')[2][ : -1].split(','), dtype=float ).reshape((-1, 2)) trace_coordinates = bd09_to_wgs84(mercator_to_bd09(trace_mercator)) 绘制地铁路线图

  与前面的绘制路线图的代码整合后,最新的绘制代码如下

import random mapbox_access_token = ( 'pk.eyJ1IjoibHVrYXNtYXJ0aW5lbGxpIiwiYSI6ImNpem85dmhwazAy' 'ajIyd284dGxhN2VxYnYifQ.HQCmyhEXZUTz3S98FMrVAQ' ) # 此处的写法只是为了排版,结果为连接在一起的字符串 layout = go.Layout( autosize=True, mapbox=dict( accesstoken=mapbox_access_token, bearing=0, center=dict( lat=23.12864583, #广州市纬度 lon= 113.2648325 #广州市经度 ), pitch=0, zoom=10 ), ) colors = ('blue', 'green', 'yellow', 'purple', 'orange', 'red', 'violet', 'navy', 'crimson', 'cyan', 'magenta', 'maroon', 'peru') #可按需增加 null = None #将json中的null定义为None city_code = 257 #广州的城市编号 data = [] #绘制数据 marked = set() for railway in station_info_json['content']: uid = railway['line_uid'] if uid in marked: #由于线路包括了来回两个方向,需要排除已绘制线路的反向线路 continue railway_json = requests.get( 'https://map.baidu.com/?qt=bsl&tps=&newmap=1&uid=%s&c=%s' % (uid, city_code) ) railway_json = eval(railway_json.content) #将json字符串转为python对象 trace_mercator = np.array( # 取出线路信息字典,以“|”划分后,取出第三部分信息,去掉末尾的“;”,获取BD-09MC坐标序列 railway_json['content'][0]['geo'].split('|')[2][ : -1].split(','), dtype=float ).reshape((-1, 2)) trace_coordinates = bd09_to_wgs84(mercator_to_bd09(trace_mercator)) plots = [] #站台BD-09MC坐标 plots_name = [] #站台名称 for plot in railway['stops']: plots.append([plot['x'], plot['y']]) plots_name.append(plot['name']) plot_mercator = np.array(plots) plot_coordinates = bd09_to_wgs84(mercator_to_bd09(plot_mercator)) #站台经纬度 color = railway_json['content'][0]['lineColor'] #利用json所给线路的颜色 if color == '': color = random.choice(colors) data.extend([ # 地铁路线 go.Scattermapbox( lon=trace_coordinates[:, 0], #路线点经度 lat=trace_coordinates[:, 1], #路线点纬度 mode='lines', # 设置路线的参数 line=go.scattermapbox.Line( width=2, color=color ), name=railway['line_name'], #线路名称,显示在图例(legend)上 legendgroup=railway['line_name'] ), # 地铁站台 go.Scattermapbox( lon=plot_coordinates[:, 0], #站台经度 lat=plot_coordinates[:, 1], #站台纬度 mode='markers', text=plots_name, # 设置标记点的参数 marker=go.scattermapbox.Marker( size=10, color=color ), name=railway['line_name'], #线路名称,显示在图例(legend)及鼠标悬浮在标记点时的路线名上 legendgroup=railway['line_name'], #设置与路线同组,当隐藏该路线时隐藏标记点 showlegend=False #不显示图例(legend) ) ]) marked.add(uid) #添加已绘制线路的uid marked.add(railway['pair_line_uid']) #添加已绘制线路反向线路的uid fig = dict(data=data, layout=layout) #py.iplot(fig) #直接显示地图 py.plot(fig, filename='Guangzhou_railway.html') #生成html文件并打开

  最后,再通过上述同样的步骤完成地图默认语言的设置,即可得到最终效果,如图 广州精细地铁线路  放大后我们能够看出地铁路线与地图道路的匹配程度较好,如图 广州精细地铁线路局部完整的代码文件

2019.05.22更新:坐标系转换代码第57行bool_out_of_china更正为is_in_china 2019.07.07更新:更改错误描述“墨卡托”为“百度墨卡托(BD-09MC)”,更改参考2中非百度摩卡托坐标转换参考链接。 2019.07.30更新:更改原代码中mapbox_access_token的赋值操作,避免因缩进导致字符串中出现空格,进而导致认证失败,地图加载不出来 2019.09.25更新:新增城市公交百度api如下

  百度地图获取城市公交信息的api为https://map.baidu.com/?qt=spot&c={城市编号}&wd=XX市公交&rn=50&t={13位时间戳},如https://map.baidu.com/?qt=spot&c=257&wd=广州市公交&rn=50&t=1563956728633

  百度地图获取城市公交详细线路信息的api为https://map.baidu.com/?qt=bsl&uid={公交线路uid}&c={城市编号}&t={13位时间戳},如https://map.baidu.com/?qt=bsl&uid=89426be2781c4681f70e7757&c=257&t=1564015808798

2019.12.08更新:改正精细线路绘制代码中由于查询接口返回的颜色值可能为空导致的错误,具体修改如下

import random

station_info_json = eval(station_info.content) #将json字符串转为python对象 colors = ('blue', 'green', 'yellow', 'purple', 'orange', 'red', 'violet',     'navy', 'crimson', 'cyan', 'magenta', 'maroon', 'peru') #可按需增加 data = [] #绘制数据 marked = set()

color = railway_json['content'][0]['lineColor'] #利用json所给线路的颜色 if color == '':     color = random.choice(colors)

地图地铁信息api参考http://www.yanweijia.cn/2016/07/24/subway_info_api/ ↩︎ ↩︎

非百度墨卡托坐标转换参考https://blog.csdn.net/pashine/article/details/81283390百度墨卡托坐标转换参考https://www.jianshu.com/p/063bee79507a ↩︎

plotly官方文档参考https://plot.ly/python/maps/plotly python版api参考https://plot.ly/python/reference/ ↩︎

html文件设置mapbox的默认语言参考https://blog.csdn.net/hyzhang6/article/details/79760166 ↩︎



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有