(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.")