Commit 03a6f9f4 authored by Karol Actun's avatar Karol Actun
Browse files

marker renamed to location, grid's locations renamed to coordinates

parent c3a91e1f
...@@ -29,7 +29,7 @@ gui = default_gui ...@@ -29,7 +29,7 @@ gui = default_gui
;# .obj (Wavefront) filenames in lib/visualization/models ;# .obj (Wavefront) filenames in lib/visualization/models
;particle_model_file = 2d_particle.obj ;particle_model_file = 2d_particle.obj
;tile_model_file = 2d_quad_tile.obj ;tile_model_file = 2d_quad_tile.obj
;marker_model_file = 2d_marker.obj ;location_model_file = 2d_location.obj
;grid_size = 1000 ;grid_size = 1000
; end of Quadratic grid configs ; end of Quadratic grid configs
...@@ -39,7 +39,7 @@ gui = default_gui ...@@ -39,7 +39,7 @@ gui = default_gui
;# .obj (Wavefront) filenames in lib/visualization/models ;# .obj (Wavefront) filenames in lib/visualization/models
;particle_model_file = 2d_particle.obj ;particle_model_file = 2d_particle.obj
;tile_model_file = 2d_hex_tile.obj ;tile_model_file = 2d_hex_tile.obj
;marker_model_file = 2d_marker.obj ;location_model_file = 2d_location.obj
;grid_size = 100 ;grid_size = 100
; end of Triangular grid configs ; end of Triangular grid configs
...@@ -48,7 +48,7 @@ gui = default_gui ...@@ -48,7 +48,7 @@ gui = default_gui
;grid_class = CubicGrid ;grid_class = CubicGrid
;particle_model_file = 3d_particle_low_poly.obj ;particle_model_file = 3d_particle_low_poly.obj
;tile_model_file = 3d_cube_tile.obj ;tile_model_file = 3d_cube_tile.obj
;marker_model_file = 3d_marker.obj ;location_model_file = 3d_location.obj
;grid_size = 10 ;grid_size = 10
; end of cubic grid configs ; end of cubic grid configs
...@@ -57,14 +57,14 @@ gui = default_gui ...@@ -57,14 +57,14 @@ gui = default_gui
grid_class = CCPGrid grid_class = CCPGrid
particle_model_file = 3d_particle.obj particle_model_file = 3d_particle.obj
tile_model_file = 3d_ccp_tile.obj tile_model_file = 3d_ccp_tile.obj
marker_model_file = 3d_marker.obj location_model_file = 3d_location.obj
grid_size = 10 grid_size = 10
# end of ccp grid configs # end of ccp grid configs
# matter default colors (rgba) # matter default colors (rgba)
particle_color = (0.8, 0.3, 0.3, 1.0) particle_color = (0.8, 0.3, 0.3, 1.0)
tile_color = (0.3, 0.3, 0.8, 1.0) tile_color = (0.3, 0.3, 0.8, 1.0)
marker_color = (0.3, 0.8, 0.3, 1.0) location_color = (0.3, 0.8, 0.3, 1.0)
grid_color = (0.0, 0.0, 0.0, 1.0) grid_color = (0.0, 0.0, 0.0, 1.0)
cursor_color = (0.5, 0.5, 0.5, 0.5) cursor_color = (0.5, 0.5, 0.5, 0.5)
center_color = (1.0, 0.0, 0.0, 0.5) center_color = (1.0, 0.0, 0.0, 0.5)
...@@ -77,12 +77,12 @@ line_color = (0.0, 0.0, 0.0, 1.0) ...@@ -77,12 +77,12 @@ line_color = (0.0, 0.0, 0.0, 1.0)
line_scaling = (1.0, 1.0, 1.0) line_scaling = (1.0, 1.0, 1.0)
# flag for showing the lines # flag for showing the lines
show_lines = True show_lines = True
# color of grid locations (rgba) # color of grid coordinates (rgba)
location_color = (0.0, 0.0, 0.0, 1.0) coordinates_color = (0.0, 0.0, 0.0, 1.0)
# size/scaling of the location model. wouldn't make it bigger than 0.2, 0.2, 0.2 # size/scaling of the coordinate model. wouldn't make it bigger than 0.2, 0.2, 0.2
location_scaling = (0.05, 0.05, 0.05) coordinates_scaling = (0.05, 0.05, 0.05)
# flag for showing the location models # flag for showing the coordinate models
show_locations = True show_coordinates = True
# flag for showing the center of the grid # flag for showing the center of the grid
show_center = True show_center = True
# camera focus color # camera focus color
...@@ -119,11 +119,11 @@ memory_limitation = False ...@@ -119,11 +119,11 @@ memory_limitation = False
## mm size in quantity ## mm size in quantity
## Works only with memory_limitation flag set on 1 ## Works only with memory_limitation flag set on 1
marker_mm_size = 2 location_mm_size = 2
particle_mm_size = 2 particle_mm_size = 2
tile_mm_size = 2 tile_mm_size = 2
[File] [File]
scenario = rings_of _matter scenario = lonely_particle
solution = random_walk_with_take_and_drop solution = random_walk_with_take_and_drop
...@@ -32,15 +32,15 @@ class CCPGrid(Grid): ...@@ -32,15 +32,15 @@ class CCPGrid(Grid):
for x in range(-int(width / 2), int(width / 2)): for x in range(-int(width / 2), int(width / 2)):
for y in range(-int(width / 2), int(width / 2)): for y in range(-int(width / 2), int(width / 2)):
for z in range(-int(width / 2), int(width / 2)): for z in range(-int(width / 2), int(width / 2)):
if self.is_valid_location((x, y, z)): if self.are_valid_coordinates((x, y, z)):
locations.append((x, y, z)) locations.append((x, y, z))
return locations return locations
def is_valid_location(self, location): def are_valid_coordinates(self, coordinates):
x = location[0] x = coordinates[0]
y = location[1] y = coordinates[1]
z = location[2] z = coordinates[2]
if y % 2.0 == 0: if y % 2.0 == 0:
if x % 2.0 == z % 2.0 == 0 or x % 2.0 == z % 2.0 == 1: if x % 2.0 == z % 2.0 == 0 or x % 2.0 == z % 2.0 == 1:
return True return True
...@@ -49,7 +49,7 @@ class CCPGrid(Grid): ...@@ -49,7 +49,7 @@ class CCPGrid(Grid):
return True return True
return False return False
def get_nearest_location(self, coordinates): def get_nearest_valid_coordinates(self, coordinates):
x = round(coordinates[0]) x = round(coordinates[0])
y = round(coordinates[1]) y = round(coordinates[1])
z = round(coordinates[2]) z = round(coordinates[2])
......
...@@ -28,13 +28,13 @@ class CubicGrid(Grid): ...@@ -28,13 +28,13 @@ class CubicGrid(Grid):
locations.append((x, y, z)) locations.append((x, y, z))
return locations return locations
def is_valid_location(self, location): def are_valid_coordinates(self, coordinates):
if location[0] % 1 == 0 and location[1] % 1 == 0 and location[2] % 1 == 0: if coordinates[0] % 1 == 0 and coordinates[1] % 1 == 0 and coordinates[2] % 1 == 0:
return True return True
else: else:
return False return False
def get_nearest_location(self, coordinates): def get_nearest_valid_coordinates(self, coordinates):
return (round(coordinates[0]), return (round(coordinates[0]),
round(coordinates[1]), round(coordinates[1]),
round(coordinates[2])) round(coordinates[2]))
......
...@@ -14,20 +14,20 @@ class Grid(ABC): ...@@ -14,20 +14,20 @@ class Grid(ABC):
pass pass
@abstractmethod @abstractmethod
def is_valid_location(self, location): def are_valid_coordinates(self, coordinates):
""" """
checks if given location is a valid location for matter in this grid checks if given coordinates are valid for this grid
:param location: (float, float, float) :param coordinates: (float, float, float)
:return: true = location is valid, false = location invalid :return: true = coordinates are valid, false = coordinates invalid
""" """
pass pass
@abstractmethod @abstractmethod
def get_nearest_location(self, coordinates): def get_nearest_valid_coordinates(self, coordinates):
""" """
calculates the nearest location to given coordinates calculates the nearest valid coordinates to given coordinates
:param coordinates: (float, float, float) :param coordinates: (float, float, float)
:return: valid location :return: valid coordinates
""" """
pass pass
...@@ -71,7 +71,7 @@ class Grid(ABC): ...@@ -71,7 +71,7 @@ class Grid(ABC):
@abstractmethod @abstractmethod
def get_box(self, width): def get_box(self, width):
""" """
calculates locations in a box calculates all valid coordinates in a box
:return: list of 3d coordinates: [(x_start_l0, y_start_l0), (x_end_l0, y_end_l0), (x_start_l1, y_start_l1), ...) :return: list of 3d coordinates: [(x_start_l0, y_start_l0), (x_end_l0, y_end_l0), (x_start_l1, y_start_l1), ...)
""" """
pass pass
...@@ -88,19 +88,19 @@ class Grid(ABC): ...@@ -88,19 +88,19 @@ class Grid(ABC):
def get_distance(self, start, end): def get_distance(self, start, end):
""" """
the metric or distance function for this grid the metric or distance function for this grid
:param start: location, (float, float, float) tuple, start of path :param start: coordinates, (float, float, float) tuple, start of path
:param end: location, (float, float, float) tuple, end of path :param end: coordinates, (float, float, float) tuple, end of path
:return: integer, minimal amount of steps between start and end :return: integer, minimal amount of steps between start and end
""" """
pass pass
@staticmethod @staticmethod
def get_location_in_direction(position, direction): def get_coordinates_in_direction(position, direction):
""" """
calculates a new position from current position and direction calculates a new position from current position and direction
:param position: location, (float, float, float) tuple, current position :param position: coordinates, (float, float, float) tuple, current position
:param direction: location, (float, float, float) tuple, direction :param direction: coordinates, (float, float, float) tuple, direction
:return: location, (float, float, float) tuple, new position :return: coordinates, (float, float, float) tuple, new position
""" """
new_pos = [] new_pos = []
for i in range(len(position)): for i in range(len(position)):
...@@ -110,7 +110,7 @@ class Grid(ABC): ...@@ -110,7 +110,7 @@ class Grid(ABC):
def get_center(self): def get_center(self):
""" """
returns the center of the grid. usually (0,0,0) returns the center of the grid. usually (0,0,0)
:return: location, (float, float, float) tuple :return: coordinates, (float, float, float) tuple
""" """
return 0.0, 0.0, 0.0 return 0.0, 0.0, 0.0
...@@ -121,75 +121,75 @@ class Grid(ABC): ...@@ -121,75 +121,75 @@ class Grid(ABC):
""" """
return 1.0, 1.0, 1.0 return 1.0, 1.0, 1.0
def get_adjacent_locations(self, location): def get_adjacent_coordinates(self, coordinates):
""" """
calculates a set of adjacent locations of the given location calculates a set of adjacent coordinates of the given coordinates
:param location: the location of which the neighboring locations should be calculated :param coordinates: the coordinates of which the neighboring coordinates should be calculated
:return: a set of locations :return: a set of coordinates
""" """
n = set() n = set()
for d in self.get_directions_list(): for d in self.get_directions_list():
n.add(self.get_location_in_direction(location, d)) n.add(self.get_coordinates_in_direction(coordinates, d))
return n return n
def _get_adjacent_locations_not_in_set(self, location, not_in_set): def _get_adjacent_coordinates_not_in_set(self, coordinates, not_in_set):
""" """
the same as 'get_neighboring_locations', but doesn't return locations which are in the given 'not_in_set'. the same as 'get_neighboring_coordinates', but doesn't return coordinates which are in the given 'not_in_set'.
:param location: the location of which the neighboring locations should be calculated :param coordinates: the coordinates of which the neighboring coordinates should be calculated
:param not_in_set: set of locations, which should not be included in the result :param not_in_set: set of coordinates, which should not be included in the result
:return: a set of locations :return: a set of coordinates
""" """
result = set() result = set()
for d in self.get_directions_list(): for d in self.get_directions_list():
n = self.get_location_in_direction(location, d) n = self.get_coordinates_in_direction(coordinates, d)
if n not in not_in_set: if n not in not_in_set:
result.add(n) result.add(n)
return result return result
def get_n_sphere(self, location, radius): def get_n_sphere(self, coordinates, radius):
""" """
calculates the n-sphere of this grid calculates the n-sphere of this grid
:param location: center of the circle/sphere :param coordinates: center of the circle/sphere
:param radius: radius of the circle/sphere :param radius: radius of the circle/sphere
:return: set of locations :return: set of coordinates
""" """
result = set() result = set()
ns = self.get_adjacent_locations(location) ns = self.get_adjacent_coordinates(coordinates)
current_ns = ns current_ns = ns
result.update(ns) result.update(ns)
for i in range(radius): for i in range(radius):
tmp = set() tmp = set()
for n in current_ns: for n in current_ns:
ns = self._get_adjacent_locations_not_in_set(n, result) ns = self._get_adjacent_coordinates_not_in_set(n, result)
tmp.update(ns) tmp.update(ns)
result.update(ns) result.update(ns)
current_ns = tmp current_ns = tmp
return result return result
def get_n_sphere_border(self, location, radius): def get_n_sphere_border(self, coordinates, radius):
""" """
calculates the border of an n-sphere around the center with the given radius calculates the border of an n-sphere around the center with the given radius
:param location: center of the ring :param coordinates: center of the ring
:param radius: radius of the ring :param radius: radius of the ring
:return: set of locations :return: set of coordinates
""" """
if radius == 0: if radius == 0:
r = set() r = set()
r.add(location) r.add(coordinates)
return r return r
seen = set() seen = set()
ns = self.get_adjacent_locations(location) ns = self.get_adjacent_coordinates(coordinates)
current_ns = ns current_ns = ns
seen.update(ns) seen.update(ns)
seen.add(location) seen.add(coordinates)
for i in range(radius-1): for i in range(radius-1):
tmp = set() tmp = set()
for n in current_ns: for n in current_ns:
ns = self._get_adjacent_locations_not_in_set(n, seen) ns = self._get_adjacent_coordinates_not_in_set(n, seen)
seen.update(ns) seen.update(ns)
tmp.update(ns) tmp.update(ns)
current_ns = tmp current_ns = tmp
......
...@@ -25,13 +25,13 @@ class QuadraticGrid(Grid): ...@@ -25,13 +25,13 @@ class QuadraticGrid(Grid):
locations.append((x, y, 0.0)) locations.append((x, y, 0.0))
return locations return locations
def is_valid_location(self, location): def are_valid_coordinates(self, coordinates):
if location[0] % 1 == 0 and location[1] % 1 == 0: if coordinates[0] % 1 == 0 and coordinates[1] % 1 == 0:
return True return True
else: else:
return False return False
def get_nearest_location(self, coordinates): def get_nearest_valid_coordinates(self, coordinates):
return (round(coordinates[0]), return (round(coordinates[0]),
round(coordinates[1]), 0.0) round(coordinates[1]), 0.0)
......
...@@ -33,18 +33,18 @@ class TriangularGrid(Grid): ...@@ -33,18 +33,18 @@ class TriangularGrid(Grid):
return locs return locs
def is_valid_location(self, location): def are_valid_coordinates(self, coordinates):
if not location[2] == 0.0: if not coordinates[2] == 0.0:
return False return False
if location[1] % 2.0 == 0.0: if coordinates[1] % 2.0 == 0.0:
if location[0] % 1.0 == 0.0: if coordinates[0] % 1.0 == 0.0:
return True return True
else: else:
if location[0] % 1.0 == 0.5: if coordinates[0] % 1.0 == 0.5:
return True return True
return False return False
def get_nearest_location(self, coordinates): def get_nearest_valid_coordinates(self, coordinates):
nearest_y = round(coordinates[1]) nearest_y = round(coordinates[1])
if nearest_y % 2 == 0: if nearest_y % 2 == 0:
nearest_x = round(coordinates[0]) nearest_x = round(coordinates[0])
......
from PyQt5.QtGui import QColor, QIntValidator from PyQt5.QtGui import QColor, QIntValidator, QFont
from PyQt5.QtWidgets import (QVBoxLayout, QPushButton, QColorDialog, QRadioButton, QLabel, QTabWidget, from PyQt5.QtWidgets import (QVBoxLayout, QPushButton, QColorDialog, QRadioButton, QLabel, QTabWidget,
QSlider, QHBoxLayout, QCheckBox, QTabBar, QTextEdit, QLineEdit, QStyle) QSlider, QHBoxLayout, QCheckBox, QTabBar, QLineEdit, QComboBox)
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from OpenGL.GL import glGetFloatv, GL_LINE_WIDTH_RANGE from OpenGL.GL import glGetFloatv, GL_LINE_WIDTH_RANGE
from lib.vis3d import Visualization
from lib.visualization.utils import eprint
def create_slider(tick_interval: int, tick_position: int, max_position: int, min_position: int, from lib.swarm_sim_header import eprint
slider_position: int, callback, orientation=Qt.Horizontal): from lib.vis3d import Visualization
"""
helper function for creating a slider
"""
slider = QSlider(orientation)
slider.setTickInterval(tick_interval)
slider.setTickPosition(tick_position)
slider.setMaximum(max_position)
slider.setMinimum(min_position)
slider.setSliderPosition(slider_position)
slider.valueChanged.connect(callback)
return slider
def create_gui(world, vis: Visualization): def create_gui(world, vis: Visualization):
...@@ -30,6 +16,7 @@ def create_gui(world, vis: Visualization): ...@@ -30,6 +16,7 @@ def create_gui(world, vis: Visualization):
tabbar.addTab(vis_tab(vis), "Visualization") tabbar.addTab(vis_tab(vis), "Visualization")
tabbar.addTab(grid_tab(vis), "Grid") tabbar.addTab(grid_tab(vis), "Grid")
tabbar.addTab(matter_tab(vis), "Matter") tabbar.addTab(matter_tab(vis), "Matter")
tabbar.addTab(help_tab(), "Help")
return tabbar return tabbar
...@@ -39,6 +26,51 @@ def key_handler(key, world, vis): ...@@ -39,6 +26,51 @@ def key_handler(key, world, vis):
vis.start_stop() vis.start_stop()
def help_tab():
vcontrols = QLabel("view controls:")
lmd = QLabel("\tmouse dragging with left mouse button:\n\t\trotation (only in 3D)")
rmd = QLabel("\tmouse dragging with right mouse button:\n\t\tdragging the view")
mw = QLabel("\tscrolling:\n\t\tzooming")
ccontrols = QLabel("\ncursor controls:")
sc = QLabel("\tholding 'CTRL':\n\t\tshow cursor")
mcc = QLabel("\tleft mouse button click while holding 'CTRL':\n\t\tadding/removing matter at cursors position")
mwc = QLabel("\tscrolling while holding 'CTRL':\n\t\tmoving the cursor in the relative z-direction")
scontrols = QLabel("\nsimulation controls:")
sss = QLabel("\tspacebar:\n\t\tstart / stop the simulation")
vbox = QVBoxLayout()
vbox.addWidget(vcontrols)
vbox.addWidget(lmd)
vbox.addWidget(rmd)
vbox.addWidget(mw)
vbox.addWidget(ccontrols)
vbox.addWidget(sc)
vbox.addWidget(mcc)
vbox.addWidget(mwc)
vbox.addWidget(scontrols)
vbox.addWidget(sss)
vbox.addStretch(0)
tabbar = QTabBar()
tabbar.setLayout(vbox)
return tabbar
def create_slider(tick_interval: int, tick_position: int, max_position: int, min_position: int,
slider_position: int, callback, orientation=Qt.Horizontal):
"""
helper function for creating a slider
"""
slider = QSlider(orientation)
slider.setTickInterval(tick_interval)
slider.setTickPosition(tick_position)
slider.setMaximum(max_position)
slider.setMinimum(min_position)
slider.setSliderPosition(slider_position)
slider.valueChanged.connect(callback)
return slider
def sim_tab(vis, world): def sim_tab(vis, world):
tab = QTabBar() tab = QTabBar()
layout = QVBoxLayout() layout = QVBoxLayout()
...@@ -109,7 +141,7 @@ def grid_tab(vis: Visualization): ...@@ -109,7 +141,7 @@ def grid_tab(vis: Visualization):
layout = QVBoxLayout() layout = QVBoxLayout()
layout.addLayout(get_grid_width_slider(vis)) layout.addLayout(get_grid_width_slider(vis))
layout.addLayout(get_grid_lines_scale_slider(vis)) layout.addLayout(get_grid_lines_scale_slider(vis))
layout.addLayout(get_grid_locations_scale_slider(vis)) layout.addLayout(get_grid_coordinates_scale_slider(vis))
layout.addLayout(get_show_checkboxes(vis)) layout.addLayout(get_show_checkboxes(vis))
layout.addLayout(recalculate_grid(vis)) layout.addLayout(recalculate_grid(vis))
layout.addLayout(get_color_picker(vis)) layout.addLayout(get_color_picker(vis))
...@@ -121,14 +153,34 @@ def grid_tab(vis: Visualization): ...@@ -121,14 +153,34 @@ def grid_tab(vis: Visualization):
def matter_tab(vis): def matter_tab(vis):
tab = QTabBar() tab = QTabBar()
layout = QVBoxLayout() layout = QVBoxLayout()
layout.addLayout(get_matter_combo(vis))
layout.addStretch(1)
layout.addLayout(get_particle_scaler(vis)) layout.addLayout(get_particle_scaler(vis))
layout.addLayout(get_marker_scaler(vis)) layout.addStretch(1)
layout.addLayout(get_location_scaler(vis))
layout.addStretch(1)
layout.addLayout(get_tile_scaler(vis)) layout.addLayout(get_tile_scaler(vis))
layout.addStretch(0) layout.addStretch(1)
tab.setLayout(layout) tab.setLayout(layout)
return tab return tab
def get_matter_combo(vis):
combo = QComboBox()
combo.addItems(["particle", "tile", "location"])
combo.setCurrentIndex(1)