Commit 43ba61b2 authored by Karol Actun's avatar Karol Actun
Browse files

vispy mit pyopengl ersetzt

parent 8e93b5cf
......@@ -3,5 +3,5 @@
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6.2 (/usr/bin/python3.6)" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (swarm-sim)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
......@@ -2,7 +2,7 @@
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="Python 3.7 (swarm-sim)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TemplatesService">
......
......@@ -11,8 +11,8 @@ max_round = 100
particle_random_order = True
## Viewing window size in pixels
window_size_x = 600
window_size_y = 800
window_size_x = 1920
window_size_y = 1080
[Visualization]
# Visualization 1 = On, 0 = Off
......@@ -21,7 +21,24 @@ visualization = 1
#gui
gui = default_gui
# .obj (Wavefront) filenames in lib/visualization/models
particle_model_file = particle.obj
tile_model_file = tile.obj
marker_model_file = marker.obj
# matter colors (r,g,b,a)
particle_color = (1.0, 0.0, 0.0, 1.0)
tile_color = (0.0, 1.0, 0.0, 1.0)
marker_color = (0.0, 0.0, 1.0, 1.0)
grid_color = (1.0, 1.0, 1.0, 0.5)
[World]
## cubic = CubicGrid (3D - easy)
## hexagonal = HexagonalGrid (2D - original grid)
## ccp = CloseCubicPacking (3D - complex)
grid_class = cubic
grid_size = 10
## False = Unlimited world size
## True = limited world size
border = False
......@@ -32,7 +49,7 @@ size_x = 2000.0
size_y = 2000.0
## Maximum number of particles that can be created while simulating
max_particles = 10000
max_particles = 1000000
[Matter]
## with memory (mm) limitation 1=Yes 0=No
......
from pprint import pprint
from PyQt5.QtGui import QPalette, QColor
from PyQt5.QtWidgets import QVBoxLayout, QPushButton, QFormLayout, QLineEdit, QHBoxLayout, QRadioButton, \
QLabel, QCheckBox, QWidget, QTabWidget, QSlider, QSizePolicy, QStyle, QStyleFactory
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QVBoxLayout, QPushButton, QColorDialog, QRadioButton, QLabel, QWidget, QTabWidget, \
QSlider, QHBoxLayout
from PyQt5.QtCore import Qt
def define_gui(visualization, world):
def rgba_tuple_to_qcolor(color):
return QColor(int(color[0]*255),
int(color[1]*255),
int(color[2]*255),
int(color[3]*255))
def qcolor_to_rgba_tuple(qcolor):
return qcolor.red8() / 255.0, qcolor.green8() / 255.0, qcolor.blue8() / 255.0, qcolor.alpha8() / 255.0
def define_gui(world):
tabbar = QTabWidget()
tabbar.setMinimumWidth(800)
tabbar.addTab(sim_tab(visualization), "Simulation")
tabbar.addTab(vis_tab(visualization), "Visualization")
set_color(tabbar, QColor(0, 0, 0, 100))
tabbar.setMinimumWidth(100)
tabbar.addTab(sim_tab(world), "Simulation")
tabbar.addTab(vis_tab(world), "Visualization")
return tabbar
def sim_tab(visualization):
def sim_tab(world):
tab = QWidget()
layout = QVBoxLayout()
layout.addLayout(get_rps_slider(world))
layout.addStretch(0)
# start stop button
start_stop_button = QPushButton("start Simulation")
#rounds per second slider
hbox = QHBoxLayout()
desc = QLabel("rounds per second (%d) : " % visualization.rounds_per_second)
def start_stop_sim():
world.vis.running = not world.vis.running
if world.vis.running:
start_stop_button.setText("stop Simulation")
else:
start_stop_button.setText("start Simulation")
start_stop_button.clicked.connect(start_stop_sim)
layout.addWidget(start_stop_button)
tab.setLayout(layout)
return tab
def get_rps_slider(world):
hbox = QVBoxLayout()
desc = QLabel("rounds per second (%d) : " % world.vis.rounds_per_second)
hbox.addWidget(desc)
rps_slider = QSlider(Qt.Horizontal)
rps_slider.setTickInterval(10)
rps_slider.setTickPosition(2)
rps_slider.setMaximum(60)
rps_slider.setMinimum(1)
rps_slider.setSliderPosition(visualization.rounds_per_second)
rps_slider.setSliderPosition(world.vis.rounds_per_second)
def set_rps():
visualization.rounds_per_second = rps_slider.value()
desc.setText("rounds per second (%d): " % rps_slider.value())
world.vis.rounds_per_second = rps_slider.value()
desc.setText("rounds per second (%d) : " % world.vis.rounds_per_second)
rps_slider.valueChanged.connect(set_rps)
hbox.addWidget(rps_slider)
layout.addLayout(hbox)
return hbox
#start stop button
start_stop_button = QPushButton("start")
def start_stop_sim():
visualization.running = not visualization.running
if visualization.running:
start_stop_button.setText("stop")
else:
start_stop_button.setText("start")
def vis_tab(world):
tab = QWidget()
layout = QVBoxLayout()
#layout.addLayout(get_grid_alpha_slider(world))
layout.addLayout(get_projection_switch(world))
layout.addLayout(get_fov_slider(world))
layout.addLayout(get_drag_sens_slider(world))
layout.addLayout(get_zoom_sens_slider(world))
layout.addLayout(get_rota_sens_slider(world))
layout.addLayout(get_color_picker(world))
start_stop_button.clicked.connect(start_stop_sim)
layout.addWidget(start_stop_button)
layout.addStretch(0)
reset_position_button = QPushButton("reset position")
tab.setLayout(layout)
def reset_pos():
world.vis.viewer.x_offset = 0
world.vis.viewer.y_offset = 0
world.vis.viewer.radius = 10
world.vis.viewer.phi = 0
world.vis.viewer.theta = 0
world.vis.viewer.update_view()
return tab
reset_position_button.clicked.connect(reset_pos)
layout.addWidget(reset_position_button)
tab.setLayout(layout)
return tab
def vis_tab(visualization):
tab = QWidget()
main_layout = QVBoxLayout()
# fov slider
fov_layout = QHBoxLayout()
fov_desc = QLabel("field of view (%d): " % visualization.controller.fov)
fov_layout.addWidget(fov_desc)
def get_fov_slider(world):
hbox = QVBoxLayout()
desc = QLabel("(only for perspective projection)\nfield of view (%d°) : " % world.vis.viewer.fov)
hbox.addWidget(desc)
fov_slider = QSlider(Qt.Horizontal)
fov_slider.setMinimum(1)
fov_slider.setMaximum(120)
fov_slider.setTickInterval(10)
fov_slider.setTickPosition(2)
fov_slider.setSliderPosition(50)
fov_slider.setMaximum(120)
fov_slider.setMinimum(10)
fov_slider.setSliderPosition(world.vis.viewer.fov)
def set_fov():
visualization.controller.fov = fov_slider.value()
fov_desc.setText("field of view (%d): " % visualization.controller.fov)
visualization.controller.update_window()
world.vis.viewer.fov = fov_slider.value()
desc.setText("(only for perspective projection)\nfield of view (%d°) : " % world.vis.viewer.fov)
world.vis.viewer.update_view()
fov_slider.valueChanged.connect(set_fov)
fov_layout.addWidget(fov_slider)
main_layout.addLayout(fov_layout)
hbox.addWidget(fov_slider)
return hbox
# projection radio buttons
projection_layout = QHBoxLayout()
projection_layout.addWidget(QLabel("projection: "))
projection_layout.addWidget(QRadioButton("orthografic"))
persproj = QRadioButton("perspective")
def change():
if visualization.controller.projection_type == 'orth':
visualization.controller.projection_type = 'pers'
else:
visualization.controller.projection_type = 'orth'
persproj.setChecked(True)
persproj.toggled.connect(change)
projection_layout.addWidget(persproj)
main_layout.addLayout(projection_layout)
def get_drag_sens_slider(world):
hbox = QVBoxLayout()
desc = QLabel("drag sensitivity:")
hbox.addWidget(desc)
slider = QSlider(Qt.Horizontal)
slider.setTickInterval(500)
slider.setTickPosition(2)
slider.setMaximum(5000)
slider.setMinimum(100)
slider.setSliderPosition(5100-world.vis.viewer.drag_sensitivity)
def set_fov():
world.vis.viewer.drag_sensitivity = 5100-slider.value()
desc.setText("drag sensitivity:")
world.vis.viewer.update_view()
slider.valueChanged.connect(set_fov)
tab.setLayout(main_layout)
return tab
hbox.addWidget(slider)
return hbox
def get_zoom_sens_slider(world):
hbox = QVBoxLayout()
desc = QLabel("zoom sensitivity:")
hbox.addWidget(desc)
slider = QSlider(Qt.Horizontal)
slider.setTickInterval(100)
slider.setTickPosition(2)
slider.setMaximum(1000)
slider.setMinimum(1)
slider.setSliderPosition(1001-world.vis.viewer.zoom_sensitivity)
def set_fov():
world.vis.viewer.zoom_sensitivity = 1001-slider.value()
desc.setText("zoom sensitivity:")
world.vis.viewer.update_view()
slider.valueChanged.connect(set_fov)
hbox.addWidget(slider)
return hbox
def get_rota_sens_slider(world):
hbox = QVBoxLayout()
desc = QLabel("(only for 3D)\nrotation sensitivity:")
hbox.addWidget(desc)
slider = QSlider(Qt.Horizontal)
slider.setTickInterval(1)
slider.setTickPosition(2)
slider.setMaximum(10)
slider.setMinimum(1)
slider.setSliderPosition(11 - world.vis.viewer.rotate_sensitivity)
def set_fov():
world.vis.viewer.rotate_sensitivity = 11 - slider.value()
desc.setText("(only for 3D)\nrotation sensitivity:")
world.vis.viewer.update_view()
slider.valueChanged.connect(set_fov)
hbox.addWidget(slider)
return hbox
def get_projection_switch(world):
vbox = QVBoxLayout()
desc = QLabel("projection type:")
vbox.addWidget(desc)
o = QRadioButton("orthographic")
def orthotoggle():
if o.isChecked():
world.vis.viewer.projection = "ortho"
world.vis.viewer.update_view()
o.toggled.connect(orthotoggle)
p = QRadioButton("perspective")
p.setChecked(True)
def perstoggle():
if p.isChecked():
world.vis.viewer.projection = "perspective"
world.vis.viewer.update_view()
p.toggled.connect(perstoggle)
hbox = QHBoxLayout()
hbox.addWidget(o)
hbox.addWidget(p)
vbox.addLayout(hbox)
return vbox
def get_color_picker(world):
pc_button = QPushButton("particles")
def pc():
current = rgba_tuple_to_qcolor(world.vis.viewer.matter_program.particle_color)
world.vis.viewer.matter_program.particle_color = \
qcolor_to_rgba_tuple(QColorDialog.getColor(current).rgba64())
world.vis.viewer.update_view()
pc_button.clicked.connect(pc)
tc_button = QPushButton("tiles")
def tc():
current = rgba_tuple_to_qcolor(world.vis.viewer.matter_program.tile_color)
world.vis.viewer.matter_program.tile_color = \
qcolor_to_rgba_tuple(QColorDialog.getColor(current).rgba64())
world.vis.viewer.update_view()
tc_button.clicked.connect(tc)
mc_button = QPushButton("markers")
def mc():
current = rgba_tuple_to_qcolor(world.vis.viewer.matter_program.marker_color)
world.vis.viewer.matter_program.marker_color = \
qcolor_to_rgba_tuple(QColorDialog.getColor(current).rgba64())
world.vis.viewer.update_view()
mc_button.clicked.connect(mc)
gr_button = QPushButton("grid")
def gr():
current = rgba_tuple_to_qcolor(world.vis.viewer.grid_program.color)
new = qcolor_to_rgba_tuple(QColorDialog.getColor(current, options=QColorDialog.ShowAlphaChannel).rgba64())
world.vis.viewer.grid_program.set_color(new)
world.vis.viewer.update_view()
gr_button.clicked.connect(gr)
bg_button = QPushButton("background")
def bg():
current = rgba_tuple_to_qcolor(world.vis.viewer.background)
new = qcolor_to_rgba_tuple(QColorDialog.getColor(current).rgba64())
world.vis.viewer.set_background(new)
world.vis.viewer.update_view()
bg_button.clicked.connect(bg)
def set_color(widget, color):
widget.setAutoFillBackground(True)
p = widget.palette()
p.setColor(widget.backgroundRole(),color)
widget.setPalette(p)
\ No newline at end of file
vbox = QVBoxLayout()
desc = QLabel("change color of:")
vbox.addWidget(desc)
hbox1 = QHBoxLayout()
hbox1.addWidget(pc_button)
hbox1.addWidget(tc_button)
hbox1.addWidget(mc_button)
hbox2 = QHBoxLayout()
hbox2.addWidget(gr_button)
hbox2.addWidget(bg_button)
vbox.addLayout(hbox1)
vbox.addLayout(hbox2)
return vbox
\ No newline at end of file
import configparser
from datetime import datetime
from lib.visualization.grid_models import *
from ast import literal_eval as make_tuple
class ConfigData:
......@@ -17,9 +18,34 @@ class ConfigData:
try:
self.gui = config.get("Visualization", "gui")
except configparser.NoOptionError as noe:
print("no gui found?")
print("no gui option given. setting to default \"gui.py\"")
self.gui = "gui.py"
try:
self.grid_class = config.get("World", "grid_class")
except configparser.NoOptionError as noe:
raise RuntimeError("Fatal Error: no grid class defined in config.ini!")
try:
self.grid_size = config.getint("World", "grid_size")
except configparser.NoOptionError as noe:
raise RuntimeError("Fatal Error: no grid size defined in config.ini!")
if self.grid_class == "cubic":
self.grid = CubicGrid(self.grid_size)
elif self.grid_class == "hexagonal":
self.grid = HexagonalGrid(self.grid_size)
else:
raise RuntimeError("Fatal Error: unknown grid type \""+self.grid_class+"\"!")
self.particle_model_file = config.get("Visualization", "particle_model_file")
self.tile_model_file = config.get("Visualization", "tile_model_file")
self.marker_model_file = config.get("Visualization", "marker_model_file")
self.particle_color = make_tuple(config.get("Visualization", "particle_color"))
self.tile_color = make_tuple(config.get("Visualization", "tile_color"))
self.marker_color = make_tuple(config.get("Visualization", "marker_color"))
self.grid_color = make_tuple(config.get("Visualization", "grid_color"))
self.size_x = config.getfloat("World", "size_x")
self.size_y = config.getfloat("World", "size_y")
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
......@@ -9,7 +9,7 @@ TODO: Erase Memory
"""
import logging, math
import logging
from lib import csv_generator, matter
from lib.swarm_sim_header import *
......@@ -82,19 +82,16 @@ class Particle(matter.Matter):
def move_to(self, direction):
"""
Moves the particle to the given directionection
Moves the particle to the given direction
:param direction: The direction is defined by loaded grid class
:return: True: Success Moving; False: Non moving
"""
direction_coord = get_coordinates_in_direction(self.coordinates, direction)
direction, direction_coord = self.check_within_border(direction, direction_coord)
if grid.is_valid_location(direction_coord):
if self.coordinates in self.world.particle_map_coordinates:
del self.world.particle_map_coordinates[self.coordinates]
if self.world.grid.is_valid_location(direction_coord):
if not direction_coord in self.world.particle_map_coordinates:
del self.world.particle_map_coordinates[self.coordinates]
self.coordinates = direction_coord
self.world.particle_map_coordinates[self.coordinates] = self
logging.info("particle %s successfully moved to %s", str(self.get_id()), direction)
......@@ -103,6 +100,7 @@ class Particle(matter.Matter):
self.touch()
self.check_for_carried_tile_or_particle()
return True
return False
def check_for_carried_tile_or_particle(self):
......
......@@ -58,9 +58,6 @@ x_offset = [0.5, 1, 0.5, -0.5, -1, -0.5 ]
y_offset = [ 1, 0, -1, -1, 0, 1]
grid = CubicGrid(5)
def direction_number_to_string(direction):
"""
:param direction: the direction that should get converted to a string
......@@ -106,6 +103,7 @@ def get_coordinates_in_direction(coordinates, direction):
:param direction: The direction. Options: E, SE, SW, W, NW, or NE
:return: The coordinaiton of the pointed directions
"""
return coordinates[0] + direction[0], coordinates[1] + direction[1], coordinates[2] + direction[2]
......
import datetime, math, os, time
from pyglet.gl import *
from pyglet.window import mouse
import pyglet.window.key as key
# screenshot manager parameters
screenshot_directory = 'screenshots/'
screenshot_file_type = '.png'
# control parameters
zoom_enabled = True
zoom_min = 4
zoom_max = 128
zoom_init = 16
zoom_speed = 1 / 50
translation_enabled = True
translation_init = (0, 0)
# presentation parameters
window_width = 800
window_height = 600
window_resizable = True # set to False to force resolution even if window does not fit on screen
show_grid = True
rotate_thirty_degree = False # the grid is not drawn correctly if the view is rotated!
# rendering parameters
target_frame_rate = 10
busy_waiting_time = 1
print_frame_stats = False
# simulation parameters
rounds_per_second = 10
# tile_transparency = 0.6
particle_transparency = 1
marker_transparency = 1
def coordinates_to_sim(coordinates):
return coordinates[0], coordinates[1] * math.sqrt(3/4)
def sim_to_coordinates(x, y):
return x, round(y / math.sqrt(3/4), 0)
def window_to_sim(x, y, view):
x_coord = view.left + (view.right - view.left) * (x / view.width) # correct
y_coord = view.bottom + (view.top - view.bottom) * (y / view.height) # not correct
return x_coord, y_coord
class ScreenshotManager:
dt = datetime.datetime.now()
#prefix = dt.isoformat(sep = '_', timespec = 'seconds').replace(':', '') + '_'
prefix = dt.isoformat(sep='_').replace(':', '') + '_'
def takeScreenshot():
if not os.path.exists(screenshot_directory):
os.makedirs(screenshot_directory)
index = math.floor(time.monotonic() * 10**3)
file_name = screenshot_directory + ScreenshotManager.prefix + str(index) + screenshot_file_type
pyglet.image.get_buffer_manager().get_color_buffer().save(file_name)
class View:
def __init__(self):
self.focusPos = translation_init
self.zoom = zoom_init
halfZoomRec = 0.5 / self.zoom
def setDimensions(self, width, height):
self.width = width
self.height = height
self.update()
def drag(self, dx, dy):
if not translation_enabled:
return
self.focusPos = (self.focusPos[0] - dx / self.zoom, self.focusPos[1] - dy / self.zoom)
self.update()
def scroll(self, x, y, scroll_x, scroll_y):
if not zoom_enabled:
return
oldPos = (self.left + x / self.zoom, self.bottom + y / self.zoom)
self.zoom = self.zoom * math.exp(-scroll_y * zoom_speed)
self.zoom = max(self.zoom, zoom_min)
self.zoom = min(self.zoom, zoom_max)