summaryrefslogtreecommitdiffstats
path: root/vprtw_aco_figure.py
blob: 9860f8ef54d385bd64808d8a3455914d5915a0e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import matplotlib.pyplot as plt
from queue import Queue


class VrptwAcoFigure:
    def __init__(self, nodes: list, path_queue: Queue):
        """
        matplotlib绘图计算需要放在主线程,寻找路径的工作建议另外开一个线程,
        当寻找路径的线程找到一个新的path的时候,将path放在path_queue中,图形绘制线程就会自动进行绘制
        queue中存放的path以PathMessage(class)的形式存在
        nodes中存放的结点以Node(class)的形式存在,主要使用到Node.x, Node.y 来获取到结点的坐标

        :param nodes: nodes是各个结点的list,包括depot
        :param path_queue: queue用来存放工作线程计算得到的path,队列中的每一个元素都是一个path,path中存放的是各个结点的id
        """

        self.nodes = nodes
        self.figure = plt.figure(figsize=(10, 10))
        self.figure_ax = self.figure.add_subplot(1, 1, 1)
        self.path_queue = path_queue
        self._depot_color = 'k'
        self._customer_color = 'steelblue'
        self._line_color = 'darksalmon'

    def _draw_point(self):
        # 画出depot
        self.figure_ax.scatter([self.nodes[0].x], [self.nodes[0].y], c=self._depot_color, label='depot', s=40)

        # 画出customer
        self.figure_ax.scatter(list(node.x for node in self.nodes[1:]),
                               list(node.y for node in self.nodes[1:]), c=self._customer_color, label='customer', s=20)
        plt.pause(0.5)

    def run(self):
        # 先绘制出各个结点
        self._draw_point()
        self.figure.show()

        # 从队列中读取新的path,进行绘制
        while True:
            if not self.path_queue.empty():
                # 取队列中最新的一个path,其他的path丢弃
                info = self.path_queue.get()
                while not self.path_queue.empty():
                    info = self.path_queue.get()

                path, distance, used_vehicle_num = info.get_path_info()
                if path is None:
                    print('[draw figure]: exit')
                    break

                # 需要先记录要移除的line,不能直接在第一个循环中进行remove,
                # 不然self.figure_ax.lines会在循环的过程中改变,导致部分line无法成功remove
                remove_obj = []
                for line in self.figure_ax.lines:
                    if line._label == 'line':
                        remove_obj.append(line)

                for line in remove_obj:
                    self.figure_ax.lines.remove(line)
                remove_obj.clear()
                plt.pause(1)

                # 重新绘制line
                self.figure_ax.set_title('current path travel distance: %f' % distance)
                self._draw_line(path)
            plt.pause(1)

    def _draw_line(self, path):
        # 根据path中index进行路径的绘制
        for i in range(1, len(path)):
            x_list = [self.nodes[path[i - 1]].x, self.nodes[path[i]].x]
            y_list = [self.nodes[path[i - 1]].y, self.nodes[path[i]].y]
            self.figure_ax.plot(x_list, y_list, color=self._line_color, linewidth=1.5, label='line')
            plt.pause(0.02)