Bootstrap

(8-6-03)优先级遍历(Priority-based Search)算法:基于tkinter的多算法路径规划程序(3)

(11)方法create_line用于在画布上创建连接线。它接受两个城市的坐标 `(x1, y1)` 和 `(x2, y2)`,以及它们在城市列表中的索引 `fr` 和 `to`。然后,它在这两个城市之间创建一条带有随机颜色的直线,并在中间位置添加文本显示两城市之间的距离。最后,它将这条线的信息保存到 `self.lines` 列表中。

    def create_line(self, x1, y1, fr, x2, y2, to):
        j = random.randint(0, len(self.colors) - 1)
        name = "{},{}-{},{}".format(x1 + 5, y1 + 5, x2 + 5, y2 + 5)
        # print(name)
        self.canvas.create_line(x1 + 5, y1 + 5, x2 + 5, y2 + 5, fill=self.colors[j], tag=name + "_line")
        self.canvas.create_text((x1 + x2 + 10) / 2, (y1 + y2 + 10) / 2, fill=self.colors[j], font="Calibri 10",
                                text=str(int(distance(x1 + 5, y1 + 5, x2 + 5, y2 + 5, 1))), tag=name + "_text")
        line = {"coords": (x1 + 5, y1 + 5, x2 + 5, y2 + 5)}
        self.lines.append(line)

(12)方法create_city用于在画布上创建一个城市。它接收城市的坐标 `(x, y)`,然后在该位置创建一个填充颜色为 `self.c_color` 的椭圆代表城市,并在其上方创建一个标签显示城市的名称。如果城市的名称是 "Le_Havre" 或 "Le_Mans",则使用特定的字体显示,否则使用默认字体。最后,它将城市的信息保存到 `self.ovals` 列表中。

    def create_city(self, x, y):
        self.canvas.create_oval(x, y, x + 10, y + 10, fill=self.c_color, outline=self.c_color,
                                tag=self.cities[self.city_count] + "_oval")
        if self.cities[self.city_count] == "Le_Havre":
            self.canvas.create_text(x, y + 12, fill=self.h_color, font="Calibri 10", text="Le Havre",
                                    tag=self.cities[self.city_count] + "_text")
        elif self.cities[self.city_count] == "Le_Mans":
            self.canvas.create_text(x, y + 12, fill=self.h_color, font="Calibri 10", text="Le Mans",
                                    tag=self.cities[self.city_count] + "_text")
        else:
            self.canvas.create_text(x, y + 12, fill=self.h_color, font="Calibri 10", text=self.cities[self.city_count],
                                    tag=self.cities[self.city_count] + "_text")
        city = {"coords": (x, y), "name": self.cities[self.city_count]}
        self.ovals.append(city)

(13)方法create_randomly用于随机生成城市及其连接。首先,它会调用 refresh_canvas()方法清空画布并初始化一些变量。然后,通过循环随机生成城市的坐标 `(x, y)`,直到生成的城市数量达到预定值。在生成每个城市之前会调用 overlap()方法来检查新城市的坐标是否与现有城市重叠。如果不重叠,则调用 create_city()方法来创建城市。接着,它检查连接的数量是否在指定范围内,如果不在范围内,则弹出错误消息。然后,它以一种随机的方式开始创建城市之间的连接。它首先通过 `flags` 数组来确保每个城市都至少连接一个城市。然后,它在生成的连接数小于指定数量时,随机选择两个城市,并调用 `create_line()` 方法创建连接。最后,它返回已创建的城市和连接。

    def create_randomly(self):
        self.refresh_canvas()
        x = 0
        y = 0
        i = 0
        # add cities
        while self.city_count < (self.city_total.get()):
            x = random.randint(30, 670)
            y = random.randint(30, 670)

            if not self.overlap(x, y):
                self.create_city(x, y)
                self.city_count += 1

        if self.entry.get() < self.city_total.get() - 1 or self.entry.get() > self.city_total.get() * \
                (self.city_total.get() - 1) / 2:
            msg.showerror(title="Connection Number Error", message="Number of connections are not in the interval.")
            return
        # make connections
        # print(self.ovals)
        flags = np.zeros(self.city_total.get())
        i = 0
        while i < len(self.ovals) and self.conn_count < self.entry.get():
            if flags[i] == 0:
                to = random.randint(0, len(self.ovals) - 1)
                if i != to:
                    flags[i] = 1
                    flags[to] = 1
                    x1, y1 = self.ovals[i]["coords"]
                    x2, y2 = self.ovals[to]["coords"]
                    self.create_line(x1, y1, i, x2, y2, to)
                    self.conn_count += 1
                    i += 1
            else:
                i += 1

        while self.conn_count < self.entry.get():
            fr = random.randint(0, len(self.ovals) - 1)
            to = random.randint(0, len(self.ovals) - 1)
            if fr != to:
                x1, y1 = self.ovals[fr]["coords"]
                x2, y2 = self.ovals[to]["coords"]
                if (x1, y1, x2, y2) not in self.lines:
                    self.create_line(x1, y1, fr, x2, y2, to)
                    self.conn_count += 1
        # print(self.lines)

(14)方法is_a_city用于检查给定的坐标 `(x, y)` 是否位于一个城市的范围内。它会遍历所有已创建的城市,检查给定坐标是否落在某个城市的边界框内。如果找到了匹配的城市,它会返回 `True`,以及匹配城市的坐标 `(x1, y1)`。如果没有找到匹配的城市,它会返回 `False`,以及 `(0, 0)`。

    def is_a_city(self, x, y):
        i = 0
        found = False
        x1 = 0
        y1 = 0
        while i < len(self.ovals) and not found:
            x1, y1 = self.ovals[i]["coords"]
            if x1 - 1 < x < x1 + 11 and y1 - 1 < y < y1 + 11:  # it is a city
                found = True
            i += 1
        return found, x1, y1

(15)方法create_by_input用于根据用户的输入创建城市或连接。当用户点击画布时,它首先确定用户希望创建的是城市还是连接。如果用户选择创建城市,则会检查城市的数量是否达到了设定的城市总数,如果没有达到,则根据用户点击的位置创建城市,并更新城市数量。如果用户选择创建连接,则会检查连接的数量是否达到了预期的连接数。然后,它会检查用户点击的位置是否在某个已创建的城市范围内,如果是,则将该城市添加到已选择的城市列表中。当已选择的城市列表中包含两个城市时,它将使用这两个城市的坐标创建连接,并更新连接数量。

    def create_by_input(self, event):
        x = event.x
        y = event.y
        if self.city_or_conn.get() == 0:  # city
            if self.city_count < self.city_total.get():
                if not self.overlap(x, y):
                    self.create_city(x, y)
                    self.city_count += 1
            else:
                msg.showerror(title="Error", message="Number of cities completed.")

        elif self.city_or_conn.get() == 1:  # connection
            if self.conn_count < int(self.entry.get()):
                flag, x, y = self.is_a_city(x, y)
                if flag and (len(self.selected_cities) == 0 or len(self.selected_cities) == 1
                             and self.selected_cities[0] != (x, y)):
                    self.selected_cities.append((x, y))
                    if len(self.selected_cities) == 2:
                        (x1, y1) = self.selected_cities[0]
                        (x2, y2) = self.selected_cities[1]
                        if (x1, y1, x2, y2) not in self.lines:
                            self.create_line(x1, y1, find_in_ovals(x1, y1), x2, y2, find_in_ovals(x2, y2))
                            self.conn_count += 1
                        self.selected_cities = []
            else:
                msg.showerror(title="Error", message="Number of connections completed.")

;