车辆路径规划问题的研究一般较常遇到需要画出车辆路径示意图,已知有每辆车的真实坐标序列,那么如何利用在一个空白的坐标轴上画出路径呢?
1.准备
1.1 matplotlib引入
一般情况下只引入plt就行了,但是我这里因为要修改图例的字体,直接将matplotlib也引入进来:
import matplotlib
import matplotlib.pyplot as plt
1.2 数据形式
我的数据形式是一个三维数组,最外层包含若干车辆,车辆包含若干乘客,乘客的位置用数组[纬度,经度]表示。
schedule = [[[30.612542, 104.124815], [30.612542, 104.124815]],[[30.664593, 104.027993], [30.691008, 104.039441]]]
如果采用真实坐标,尺度太小会导致箭头粗细、标志大小的调整问题,所以我在后面画图的过程中都采取真实坐标*10的表示。
2.画图
我的问题是需要有发车点和终点的,所以需要先用以下代码标出发车点,如果没有单独发车点,或已经包含在前面的数组内,可以直接循环画图。for循环对每辆车的路径画图,应包含两个部分:画出点,在点之间用箭头连线。
2.1 画出散点
用scatter方法可以画出散点图,如果需要对每一辆车标注图例,可以调整参数,方法的参数设置可以参见:scatter方法官方文档
plt.scatter(x0, y0, s = 200, color = 'k',
marker='*',label = u'机场')
*如果需要显示中文图例,并设置中文字体大小,可以在文件开始设置字体并在每一个中文字符串前加u:
#引入中文字体
myfont = matplotlib.font_manager.FontProperties(fname='C:/Windows/Fonts/simsun.ttc',size=7)
#使用中文字体
plt.scatter(x0, y0, s = 200, color = 'k',
marker='*',label = u'机场')
#设置图例
plt.legend(bbox_to_anchor=(1.05, 0), loc=3, borderaxespad=0,prop=myfont)
2.2 画出箭头连线
用plt.arrow()方法画出箭头连线,具体方法参见:arrow方法官方文档
def route1(x0, y0, car, plt):
plt_arrow(x0, y0, car[0][0]*10, car[0][1]*10)
for i in range(len(car)-1):
plt_arrow(car[i][0]*10, car[i][1]*10, car[i+1][0]*10,car[i+1][1]*10)
plt_arrow(car[-1][0]*10, car[-1][1]*10, x0, y0)
def plt_arrow(x_begin,y_begin,x_end,y_end):
plt.arrow(x_begin, y_begin, x_end - x_begin, y_end - y_begin,
length_includes_head=True,
head_width = 0.01, head_length =0.02, fc="black", ec="black",linestyle=line[np.random.randint(1,4)],linewidth=0.001)
2.3 完整代码
# coding=utf-8
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
#显示中文
myfont = matplotlib.font_manager.FontProperties(fname='C:/Windows/Fonts/simsun.ttc',size=7)
#点和线的形状集合
line = ['-','--','-.',':']
point = ['.',',','o','v','^','<','>','1','2','3','4','s','p','*','h','H','+','x','D','d','|','_','x','P','X','8']
schedule = [[[30.612542, 104.124815], [30.612542, 104.124815], [30.655155, 104.130167], [30.65551, 104.128293], [30.664906, 104.123196], [30.655029, 104.102768], [30.641632, 104.111138]], [[30.655078, 104.089894], [30.655078, 104.089894], [30.659934, 104.080402], [30.675628, 104.080586], [30.693483, 104.089597], [30.665345, 104.077832], [30.679517, 104.050707]]]
def DrawPointMap():
plt.figure()
x0 = 30.584035 * 10
y0 = 103.967432 * 10
plt.scatter(x0, y0, s = 200, color = 'k',
marker='*',label = u'机场')
# annotate an important value
for i in range(len(schedule)):
x = []
y = []
for location in schedule[i]:
x.append(location[0]*10)
y.append(location[1]*10)
plt.scatter(x, y, color='k', marker=point.pop() # 要标记的点的坐标、大小及颜色
, label=(u'车辆'+ str(i+1)))
route1(x0, y0, schedule[i], plt)
plt.legend(bbox_to_anchor=(1.05, 0), loc=3, borderaxespad=0,prop=myfont) # 图例
x = [305.8,306.0,306.2,306.4,306.6,306.8,307.0,307.2]
plt.xticks(x,( '30.58', '30.60', '30.62', '30.64', '30.66', '30.68', '30.70', '30.72'))
y = [1039.50, 1039.75, 1040.00, 1040.25, 1040.50, 1040.75, 1041.00, 1041.25, 1041.50]
plt.yticks(y, ('103.950', '103.9750', '104.000', '104.025', '104.050', '104.075', '104.100', '104.125', '104.150'))
plt.show()
# 配送路线
def route1(x0, y0, car, plt):
plt_arrow(x0, y0, car[0][0]*10, car[0][1]*10)
for i in range(len(car)-1):
plt_arrow(car[i][0]*10, car[i][1]*10, car[i+1][0]*10,car[i+1][1]*10)
plt_arrow(car[-1][0]*10, car[-1][1]*10, x0, y0)
def plt_arrow(x_begin,y_begin,x_end,y_end):
plt.arrow(x_begin, y_begin, x_end - x_begin, y_end - y_begin,
length_includes_head=True, # 增加的长度包含箭头部分
head_width = 0.01, head_length =0.02, fc="black", ec="black",linestyle=line[np.random.randint(1,4)],linewidth=0.001)
if __name__=='__main__':
DrawPointMap()
最终就得到我们想要的图啦: