From 8cb8a8d91b7aad768d4f736c96dc002fea4bd38a Mon Sep 17 00:00:00 2001 From: Skullheadx <704277@pdsb.net> Date: Tue, 27 Dec 2022 21:04:44 -0500 Subject: [PATCH] Added Traveling Salesman --- display.py | 83 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 16 deletions(-) diff --git a/display.py b/display.py index 8318bdd..5faebd3 100644 --- a/display.py +++ b/display.py @@ -1,5 +1,5 @@ import pygame - +import math pygame.init() @@ -7,6 +7,7 @@ WHITE = (255, 255, 255) BLACK = (0, 0, 0) GRAY = (128, 128, 128) BLUE = (0, 0, 255) +ORANGE = (255, 165, 0) class Node: @@ -14,50 +15,100 @@ class Node: outline_colour = BLACK text_colour = WHITE - radius = 15 + radius = 5 thickness = 1 - font = pygame.font.SysFont("arial", 15) + + # font = pygame.font.SysFont("arial", 12) def __init__(self, position: tuple, number: int) -> None: self.position = pygame.Vector2(position) - self.text = self.font.render(str(number), True, self.text_colour) + # self.text = self.font.render(str(number), True, self.text_colour) + + def draw(self, surf: pygame.Surface) -> None: + pygame.draw.circle(surf, self.background_colour, self.position, self.radius) + pygame.draw.circle(surf, self.outline_colour, self.position, self.radius, width=self.thickness) + # surf.blit(self.text, self.text.get_rect(center=self.position)) + + +class Salesman: + background_colour = ORANGE + outline_colour = BLACK + + radius = 7 + thickness = 1 + + speed = 150 # pixels/second + + def __init__(self, route: list, start_index=0) -> None: + self.route = route + self.index = start_index + self.position = pygame.Vector2(self.route[self.index]) + self.destination = self.get_destination() + + def get_destination(self) -> pygame.Vector2: + self.index = (self.index + 1) % len(self.route) + return pygame.Vector2(self.route[self.index]) + + def update(self, delta: float) -> None: + direction = math.atan2(self.destination.y - self.position.y, self.destination.x - self.position.x) + step = self.speed * delta + if abs(step * math.cos(direction)) > abs(self.destination.x - self.position.x): + self.position.x = self.destination.x + else: + self.position.x += step * math.cos(direction) + + if abs(step * math.sin(direction)) > abs(self.destination.y - self.position.y): + self.position.y = self.destination.y + else: + self.position.y += step * math.sin(direction) + if self.position == self.destination: + self.destination = self.get_destination() def draw(self, surf: pygame.Surface) -> None: pygame.draw.circle(surf, self.background_colour, self.position, self.radius) pygame.draw.circle(surf, self.outline_colour, self.position, self.radius, width=self.thickness) - surf.blit(self.text, self.text.get_rect(center=self.position)) class Display: pygame.display.set_caption("Traveling Salesman Problem") - def __init__(self, path: str) -> None: + def __init__(self, path: str, route: list) -> None: with open(path, "r") as f: contents = f.read().split("\n") if contents[-1] == "": contents = contents[:-1] self.WIDTH, self.HEIGHT, self.N = tuple(map(int, contents[0].split(" "))) - self.nodes = [Node(tuple(map(int, node.split(" "))), num) for num, node in enumerate(contents[1:])] + self.nodes = [Node(node, num) for num, node in enumerate(route)] self.screen = pygame.display.set_mode((self.WIDTH, self.HEIGHT)) - self.is_running = True - self.clock = pygame.time.Clock() - self.delta = 0 + self.route = route + self.salesman = Salesman(self.route) - def show(self, route: list) -> None: - while self.is_running: + def update(self, delta: float) -> None: + self.salesman.update(delta) + + def show(self) -> None: + is_running = True + + clock = pygame.time.Clock() + delta = 0 + while is_running: for event in pygame.event.get(): if event.type == pygame.QUIT: - self.is_running = False + is_running = False + + self.salesman.update(delta) self.screen.fill(WHITE) - if len(route) > 1: - pygame.draw.aalines(self.screen, BLUE, True, route, 5) + if len(self.route) > 1: + pygame.draw.aalines(self.screen, BLUE, True, self.route, 5) for node in self.nodes: node.draw(self.screen) + self.salesman.draw(self.screen) + pygame.display.update() - self.delta = self.clock.tick(60) + delta = clock.tick(60) / 1000 # Seconds -- 2.54.0