From b111efd9bf99531732e4c14ab182b68d7a6b2394 Mon Sep 17 00:00:00 2001 From: leoleung-springernature Date: Fri, 2 Jun 2023 00:22:36 +0100 Subject: [PATCH 1/7] init npm package --- site/package.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 site/package.json diff --git a/site/package.json b/site/package.json new file mode 100644 index 0000000..f4f66bb --- /dev/null +++ b/site/package.json @@ -0,0 +1,11 @@ +{ + "name": "tf2deepfloorplan-site", + "version": "1.0.0", + "description": "site for deep floorplan deployment", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Leo Leung", + "license": "ISC" +} From e99ab2ddbc167e8e4f5ffcc3a766aca628938684 Mon Sep 17 00:00:00 2001 From: zcemycl Date: Fri, 2 Jun 2023 11:12:56 +0100 Subject: [PATCH 2/7] skip site for isort --- .isort.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.isort.cfg b/.isort.cfg index d3adbfc..10d5273 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -2,7 +2,7 @@ profile=black line_length=79 src_paths=src,tests -skip=.tox,.nox,venv,build,dist,resources,model,log +skip=.tox,.nox,venv,build,dist,resources,model,log,site known_setuptools=setuptools,pkg_resources known_test=pytest known_first_party=Deep_floorplan From 552be79c82bbca5eb2e237ae3beccd67fe354216 Mon Sep 17 00:00:00 2001 From: zcemycl Date: Thu, 8 Jun 2023 19:34:46 +0100 Subject: [PATCH 3/7] allow autoscale for big image to pygame window --- src/dfp/game/model.py | 25 ++++++++++++++++++++++++- src/dfp/game/view.py | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/dfp/game/model.py b/src/dfp/game/model.py index 987cb86..068dd41 100644 --- a/src/dfp/game/model.py +++ b/src/dfp/game/model.py @@ -4,6 +4,7 @@ import numpy as np import pygame +from PIL import Image from ..deploy import main from ..utils.settings import overwrite_args_with_toml @@ -18,10 +19,12 @@ class Model: SKY_COLOR = (0, 150, 200) GRD_COLOR = (100, 100, 100) PLAYER_COLOR = (255, 0, 0) + PLAYER_SIZE = 8 TILE_SIZE = 1 dangle = 0.01 - dpos = 1 + dpos = 0.1 GAME_TEXT_COLOR = pygame.Color("coral") + MAX_SIZE = 480 # surf = None def __init__(self, tomlfile: str = "docs/game.toml"): @@ -34,6 +37,7 @@ def __init__(self, tomlfile: str = "docs/game.toml"): def _initialise_map(self): self.result = main(self.args) + self.rescale_image() self.h, self.w = self.result.shape self.bg = self.rgb_im = np.zeros((self.h, self.w, 3)) self.bg[self.result != 10] = self.FLOOR_COLOR @@ -47,8 +51,27 @@ def _initialise_map(self): self.SCALE = (self.SCREEN_WIDTH / 2) / self.args.casted_rays self.surf = pygame.surfarray.make_surface(self.bg) + def rescale_image(self): + self.h, self.w = self.result.shape + max_side = max(self.h, self.w) + scale_factor = self.MAX_SIZE / max_side + tmpimg = Image.fromarray(self.result) + if self.h > self.w: + new_shp = ( + int(scale_factor * self.w), + self.MAX_SIZE, + ) + else: + new_shp = ( + self.MAX_SIZE, + int(scale_factor * self.h), + ) + tmpimg = tmpimg.resize(new_shp, resample=Image.NEAREST) + self.result = np.asarray(tmpimg).copy() + def _initialise_player_pose(self): posy, posx = np.where(self.result != 1) posidx = random.randint(0, len(posy) - 1) self.player_x, self.player_y = posx[posidx], posy[posidx] self.player_angle = math.pi + self.dpos = 20 * self.PLAYER_SIZE / self.MAX_DEPTH diff --git a/src/dfp/game/view.py b/src/dfp/game/view.py index 4f8d661..dd573e3 100644 --- a/src/dfp/game/view.py +++ b/src/dfp/game/view.py @@ -29,7 +29,7 @@ def draw_player_loc(self): self.win, self.model.PLAYER_COLOR, (self.model.player_x, self.model.player_y), - 8, + self.model.PLAYER_SIZE, ) def draw_player_rays( From af4936ae6c358762166ed70b22fe6ff1f966156e Mon Sep 17 00:00:00 2001 From: zcemycl Date: Sat, 15 Jul 2023 10:22:10 +0100 Subject: [PATCH 4/7] add auto_navigate variable --- src/dfp/game/controller.py | 13 +++++++++++++ src/dfp/game/model.py | 1 + 2 files changed, 14 insertions(+) diff --git a/src/dfp/game/controller.py b/src/dfp/game/controller.py index fba412f..93f5c21 100644 --- a/src/dfp/game/controller.py +++ b/src/dfp/game/controller.py @@ -12,6 +12,9 @@ def __init__(self, model: Model): def player_control(self): keys = pygame.key.get_pressed() + if True in keys: + self.model.auto_navigate = False + state = pygame.mouse.get_pressed() angle, x, y = ( self.model.player_angle, self.model.player_x, @@ -37,6 +40,16 @@ def player_control(self): if keys[pygame.K_q]: pygame.quit() sys.exit(0) + if state[0]: + if not self.model.auto_navigate: + self.model.auto_navigate = True + destination_pos = pygame.mouse.get_pos() + if ( + destination_pos[0] <= self.model.result.shape[1] + and destination_pos[1] <= self.model.result.shape[0] + ): + self.model.goal = destination_pos # x,y + print(self.model.result.shape, destination_pos) if x < 0: x = 0 if x >= self.model.w: diff --git a/src/dfp/game/model.py b/src/dfp/game/model.py index 068dd41..6ad7d4a 100644 --- a/src/dfp/game/model.py +++ b/src/dfp/game/model.py @@ -25,6 +25,7 @@ class Model: dpos = 0.1 GAME_TEXT_COLOR = pygame.Color("coral") MAX_SIZE = 480 + auto_navigate = False # surf = None def __init__(self, tomlfile: str = "docs/game.toml"): From aefff3eaa10f96d881cf90857a696c46058c93ea Mon Sep 17 00:00:00 2001 From: zcemycl Date: Sat, 15 Jul 2023 11:41:27 +0100 Subject: [PATCH 5/7] tuning --- src/dfp/game/controller.py | 55 +++++++++++++++++++++++++++++++++----- src/dfp/game/model.py | 6 +++++ src/dfp/game/view.py | 2 ++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/dfp/game/controller.py b/src/dfp/game/controller.py index 93f5c21..948dc18 100644 --- a/src/dfp/game/controller.py +++ b/src/dfp/game/controller.py @@ -1,7 +1,9 @@ import math import sys +import numpy as np import pygame +from scipy.ndimage.morphology import distance_transform_edt from .model import Model @@ -9,6 +11,25 @@ class Controller: def __init__(self, model: Model): self.model = model + self.get_repulsive_field() + + def get_repulsive_field(self): + d = distance_transform_edt(1 - self.model.result) + d2 = d / 500 + 1 + self.navigate_repulsive_field = self.model.nu_auto_navigate * ( + (1 / d2 - 1 / self.model.d0_auto_navigate) ** 2 + ) + self.navigate_repulsive_field[d2 > self.model.d0_auto_navigate] = 0 + + def get_attractive_field(self): + h, w = self.model.result.shape + self.x, self.y = np.meshgrid( + np.linspace(1, w, w), np.linspace(1, h, h) + ) + self.navigate_attractive_field = self.model.xi_auto_navigate * ( + (self.x - self.model.goal[0]) ** 2 + + (self.y - self.model.goal[1]) ** 2 + ) def player_control(self): keys = pygame.key.get_pressed() @@ -41,15 +62,35 @@ def player_control(self): pygame.quit() sys.exit(0) if state[0]: - if not self.model.auto_navigate: + destination_pos = pygame.mouse.get_pos() + if ( + destination_pos[0] <= self.model.result.shape[1] + and destination_pos[1] <= self.model.result.shape[0] + ): self.model.auto_navigate = True - destination_pos = pygame.mouse.get_pos() - if ( - destination_pos[0] <= self.model.result.shape[1] - and destination_pos[1] <= self.model.result.shape[0] - ): + if self.model.auto_navigate: + if self.model.goal != destination_pos: self.model.goal = destination_pos # x,y - print(self.model.result.shape, destination_pos) + # get new navigation map + self.get_attractive_field() + self.model.navigate_field = np.transpose( + self.navigate_attractive_field + + self.navigate_repulsive_field, + (1, 0), + ) + # print(self.navigate_attractive_field.shape, + # self.navigate_repulsive_field.shape) + # self.model.navigate_field = np.transpose( + # self.navigate_attractive_field, (1, 0) + # ) + # self.model.navigate_field = np.transpose( + # self.navigate_repulsive_field, (1, 0) + # ) + self.model.navigate_surf = pygame.surfarray.make_surface( + self.model.navigate_field + ).convert_alpha() + + self.model.goal = destination_pos # x,y if x < 0: x = 0 if x >= self.model.w: diff --git a/src/dfp/game/model.py b/src/dfp/game/model.py index 6ad7d4a..11b26d9 100644 --- a/src/dfp/game/model.py +++ b/src/dfp/game/model.py @@ -26,6 +26,12 @@ class Model: GAME_TEXT_COLOR = pygame.Color("coral") MAX_SIZE = 480 auto_navigate = False + goal = (0, 0) + nu_auto_navigate = 800 + d0_auto_navigate = 2 + xi_auto_navigate = 1 / 200 + navigate_field = None + navigate_surf = None # surf = None def __init__(self, tomlfile: str = "docs/game.toml"): diff --git a/src/dfp/game/view.py b/src/dfp/game/view.py index dd573e3..01eb6be 100644 --- a/src/dfp/game/view.py +++ b/src/dfp/game/view.py @@ -18,6 +18,8 @@ def register_window(self, win: pygame.Surface) -> View: def draw_dfp(self): self.win.blit(self.model.surf, (0, 0)) + if self.model.auto_navigate and self.model.navigate_surf: + self.win.blit(self.model.navigate_surf, (0, 0)) def show_fps(self, fps: str): font = pygame.font.SysFont("Arial", 18) From e87d2ffc0dc6478b03afef8e7e9801d79c8f190c Mon Sep 17 00:00:00 2001 From: zcemycl Date: Sun, 16 Jul 2023 14:24:53 +0100 Subject: [PATCH 6/7] normalise fields --- src/dfp/game/controller.py | 57 +++++++++++++++++++++++++------------- src/dfp/game/model.py | 4 +-- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/dfp/game/controller.py b/src/dfp/game/controller.py index 948dc18..6572380 100644 --- a/src/dfp/game/controller.py +++ b/src/dfp/game/controller.py @@ -14,22 +14,53 @@ def __init__(self, model: Model): self.get_repulsive_field() def get_repulsive_field(self): - d = distance_transform_edt(1 - self.model.result) - d2 = d / 500 + 1 - self.navigate_repulsive_field = self.model.nu_auto_navigate * ( - (1 / d2 - 1 / self.model.d0_auto_navigate) ** 2 + tmp_result = self.model.result.copy() + tmp_result[0, :] = 1 + tmp_result[-1, :] = 1 + tmp_result[:, 0] = 1 + tmp_result[:, -1] = 1 + self.navigate_repulsive_field = distance_transform_edt(1 - tmp_result) + self.navigate_repulsive_field /= np.max(self.navigate_repulsive_field) + self.navigate_repulsive_field = 1 / ( + self.navigate_repulsive_field**2 + 0.1 ) - self.navigate_repulsive_field[d2 > self.model.d0_auto_navigate] = 0 + self.navigate_repulsive_field *= self.model.nu_auto_navigate def get_attractive_field(self): h, w = self.model.result.shape self.x, self.y = np.meshgrid( np.linspace(1, w, w), np.linspace(1, h, h) ) - self.navigate_attractive_field = self.model.xi_auto_navigate * ( + self.navigate_attractive_field = 10 * ( (self.x - self.model.goal[0]) ** 2 + (self.y - self.model.goal[1]) ** 2 ) + self.navigate_attractive_field += ( + self.x - self.model.player_x + ) ** 2 + (self.y - self.model.player_y) ** 2 + self.navigate_attractive_field /= np.max( + self.navigate_attractive_field + ) + self.navigate_attractive_field *= self.model.xi_auto_navigate + + def get_navigate_field(self): + self.model.navigate_field = np.transpose( + self.navigate_attractive_field + self.navigate_repulsive_field, + (1, 0), + ) + # self.model.navigate_field = np.transpose( + # self.navigate_attractive_field, + # (1, 0), + # ) + # self.model.navigate_field = np.transpose( + # + self.navigate_repulsive_field, + # (1, 0), + # ) + self.model.navigate_field /= np.max(self.model.navigate_field) + self.model.navigate_field *= 255 + self.model.navigate_field = np.tile( + np.expand_dims(self.model.navigate_field, axis=2), (1, 1, 3) + ) def player_control(self): keys = pygame.key.get_pressed() @@ -73,19 +104,7 @@ def player_control(self): self.model.goal = destination_pos # x,y # get new navigation map self.get_attractive_field() - self.model.navigate_field = np.transpose( - self.navigate_attractive_field - + self.navigate_repulsive_field, - (1, 0), - ) - # print(self.navigate_attractive_field.shape, - # self.navigate_repulsive_field.shape) - # self.model.navigate_field = np.transpose( - # self.navigate_attractive_field, (1, 0) - # ) - # self.model.navigate_field = np.transpose( - # self.navigate_repulsive_field, (1, 0) - # ) + self.get_navigate_field() self.model.navigate_surf = pygame.surfarray.make_surface( self.model.navigate_field ).convert_alpha() diff --git a/src/dfp/game/model.py b/src/dfp/game/model.py index 11b26d9..6100244 100644 --- a/src/dfp/game/model.py +++ b/src/dfp/game/model.py @@ -27,9 +27,9 @@ class Model: MAX_SIZE = 480 auto_navigate = False goal = (0, 0) - nu_auto_navigate = 800 + nu_auto_navigate = 2000 # repulsive d0_auto_navigate = 2 - xi_auto_navigate = 1 / 200 + xi_auto_navigate = 5000 # attractive navigate_field = None navigate_surf = None # surf = None From c1210878ea8b68c3271fa4ac7a314192396ee08e Mon Sep 17 00:00:00 2001 From: zcemycl Date: Mon, 17 Jul 2023 23:54:26 +0100 Subject: [PATCH 7/7] add a star for fun --- src/dfp/game/__main__.py | 99 +++++++++++++++++++++++++++++++++++++- src/dfp/game/controller.py | 19 +++++--- src/dfp/game/model.py | 2 + 3 files changed, 113 insertions(+), 7 deletions(-) diff --git a/src/dfp/game/__main__.py b/src/dfp/game/__main__.py index 5615253..bcd500e 100644 --- a/src/dfp/game/__main__.py +++ b/src/dfp/game/__main__.py @@ -4,6 +4,7 @@ import time from typing import Tuple, Union +import matplotlib.pyplot as plt import numpy as np import pygame from numba import jit, njit @@ -93,6 +94,14 @@ def __init__(self, tomlfile: str = "docs/game.toml"): self.view = View(self.model).register_window(self.win) self.control = Controller(self.model) + self.statemap = np.zeros(self.model.result.shape[:2]) + self.statemap[self.model.result == 0] = 1 + self.statemap[self.model.result == 1] = 2 + self.statemap[int(self.model.player_y), int(self.model.player_x)] = 5 + self.statemap_color = np.zeros( + (self.model.result.shape[0], self.model.result.shape[1], 3) + ) + def _initialise_game_engine(self): pygame.init() self.win = pygame.display.set_mode( @@ -101,7 +110,17 @@ def _initialise_game_engine(self): pygame.display.set_caption("Deep Floorplan Raycasting") self.clock = pygame.time.Clock() + def colorise_routes(self): + self.statemap_color[self.statemap == 1] = (255, 255, 255) + self.statemap_color[self.statemap == 2] = (255, 255, 0) + self.statemap_color[self.statemap == 3] = (255, 0, 0) + self.statemap_color[self.statemap == 4] = (0, 0, 255) + self.statemap_color[self.statemap == 5] = (0, 255, 0) + self.statemap_color[self.statemap == 6] = (128, 129, 255) + def run(self): + old_destination = self.model.goal + while True: for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -115,6 +134,77 @@ def run(self): self.view.show_fps(str(int(self.clock.get_fps()))) self.view.draw_player_loc() + # init route data + if ( + self.model.auto_navigate + and not self.model.find_route + and old_destination != self.model.goal + ): + self.statemap[self.model.goal[1], self.model.goal[0]] = 6 + self.parentArr = np.zeros(self.model.result.shape[:2]) + h, w = self.model.result.shape + X, Y = np.meshgrid( + np.linspace(0, h - 1, h), np.linspace(0, w - 1, w) + ) + H = np.abs(X - self.model.goal[0]) + np.abs( + Y - self.model.goal[1] + ) + H = H.T + f = np.ones((h, w)) * np.inf + g = np.ones((h, w)) * np.inf + g[int(self.model.player_y), int(self.model.player_x)] = 0 + f[int(self.model.player_y), int(self.model.player_x)] = H[ + int(self.model.player_y), int(self.model.player_x) + ] + numExpanded = 0 + loc = np.array( + [ + [int(self.model.player_y), self.model.goal[1]], + [int(self.model.player_x), self.model.goal[0]], + ] + ) + st_node = np.ravel_multi_index(loc, (h, w)) + + old_destination = self.model.goal + self.model.display_route = True + + if self.model.display_route and not self.model.find_route: + min_dist = np.amin(f.flatten()) + current = np.argmin(f.flatten()) + if (current == st_node[-1]) or np.isinf(min_dist): + self.model.find_route = True + plt.imshow(self.statemap) + plt.show() + + current_ind = np.unravel_index(current, (h, w)) + self.statemap[current_ind] = 3 + f[current_ind] = np.inf + numExpanded += 1 + + i = current_ind[0] + j = current_ind[1] + for jw in range(j - 1, j + 2, 2): + if i >= 0 and i <= h - 1 and jw >= 0 and jw <= w - 1: + if (self.statemap[i, jw] == 1) or ( + self.statemap[i, jw] == 6 + ): + self.statemap[i, jw] = 4 + g[i, jw] = g[i, j] + 1 + f[i, jw] = g[i, j] + H[i, j] + self.parentArr[i, jw] = current + + for iw in range(i - 1, i + 2, 2): + if iw >= 0 and iw <= h - 1 and j >= 0 and j <= w - 1: + if (self.statemap[iw, j] == 1) or ( + self.statemap[iw, j] == 6 + ): + self.statemap[iw, j] = 4 + g[iw, j] = g[i, j] + 1 + f[iw, j] = g[i, j] + H[i, j] + self.parentArr[iw, j] = current + + self.colorise_routes() + # calculate player rays wallangles = loop_rays( self.model.player_x, @@ -129,7 +219,8 @@ def run(self): ) for idx, (angle, fdist, iswall) in enumerate(wallangles): - self.view.draw_player_rays(angle, fdist) + if not self.model.auto_navigate: + self.view.draw_player_rays(angle, fdist) wall_color = int( 255 * (1 - (3 * fdist / self.model.MAX_DEPTH) ** 2) ) @@ -139,6 +230,12 @@ def run(self): if iswall: self.view.draw_3d_wall(idx, wall_color, wall_height) + + if self.model.display_route and not self.model.find_route: + route_surf = pygame.surfarray.make_surface( + np.transpose(self.statemap_color, (1, 0, 2)) + ) + self.win.blit(route_surf, (0, 0)) pygame.display.flip() self.clock.tick() diff --git a/src/dfp/game/controller.py b/src/dfp/game/controller.py index 6572380..0488a3a 100644 --- a/src/dfp/game/controller.py +++ b/src/dfp/game/controller.py @@ -31,13 +31,19 @@ def get_attractive_field(self): self.x, self.y = np.meshgrid( np.linspace(1, w, w), np.linspace(1, h, h) ) - self.navigate_attractive_field = 10 * ( - (self.x - self.model.goal[0]) ** 2 - + (self.y - self.model.goal[1]) ** 2 + attract_to_target = (self.x - self.model.goal[0]) ** 2 + ( + self.y - self.model.goal[1] + ) ** 2 + attract_to_target /= np.max(attract_to_target) + reject_away_start = -np.sqrt( + (self.x - self.model.player_x) ** 2 + + (self.y - self.model.player_y) ** 2 + ) + reject_away_start -= np.min(reject_away_start) + reject_away_start /= np.max(reject_away_start) + self.navigate_attractive_field = ( + 100 * attract_to_target + reject_away_start ) - self.navigate_attractive_field += ( - self.x - self.model.player_x - ) ** 2 + (self.y - self.model.player_y) ** 2 self.navigate_attractive_field /= np.max( self.navigate_attractive_field ) @@ -108,6 +114,7 @@ def player_control(self): self.model.navigate_surf = pygame.surfarray.make_surface( self.model.navigate_field ).convert_alpha() + self.model.find_route = False self.model.goal = destination_pos # x,y if x < 0: diff --git a/src/dfp/game/model.py b/src/dfp/game/model.py index 6100244..620a3d6 100644 --- a/src/dfp/game/model.py +++ b/src/dfp/game/model.py @@ -26,6 +26,8 @@ class Model: GAME_TEXT_COLOR = pygame.Color("coral") MAX_SIZE = 480 auto_navigate = False + find_route = False + display_route = False goal = (0, 0) nu_auto_navigate = 2000 # repulsive d0_auto_navigate = 2