From 938e36ab29c7af19eaa1085315c86ce18133ee57 Mon Sep 17 00:00:00 2001 From: HSMarieK Date: Fri, 12 Dec 2025 17:13:56 +0100 Subject: [PATCH 01/10] new_visualization_library --- lineflow/simulation/line.py | 3 +- lineflow/simulation/visualization.py | 55 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 lineflow/simulation/visualization.py diff --git a/lineflow/simulation/line.py b/lineflow/simulation/line.py index 94990f1..88f0a2f 100644 --- a/lineflow/simulation/line.py +++ b/lineflow/simulation/line.py @@ -12,6 +12,7 @@ Station, Sink, ) +from lineflow.simulation.visualization import Viewpoint logger = logging.getLogger(__name__) @@ -226,7 +227,7 @@ def setup_draw(self): x.append(o.position[0]) y.append(o.position[1]) - return pygame.display.set_mode((max(x) + 100, max(y) + 100)) + return pygame.display.set_mode(flags=pygame.SCALED), Viewpoint(size=(max(x) + 100, max(y) + 100)) def teardown_draw(self): pygame.quit() diff --git a/lineflow/simulation/visualization.py b/lineflow/simulation/visualization.py new file mode 100644 index 0000000..e75b9ac --- /dev/null +++ b/lineflow/simulation/visualization.py @@ -0,0 +1,55 @@ +import pygame + +class Viewpoint: + + def __init__( + self, + position=None, + size=None, + zoom=1, + ): + + if size is None: + size = (1410, 1000) + + self.paper = pygame.Surface(size) + + if position is None: + position = (0, 0) + + self._view = pygame.Vector3(position[0], position[1], zoom) + + def check_view_update(self): + + if pygame.key.get_pressed()[pygame.K_PLUS]: + self._view.z += 0.1 + + if pygame.key.get_pressed()[pygame.K_MINUS]: + self._view.z -=0.1 + + if pygame.key.get_pressed()[pygame.K_UP]: + self._view.y += 10 + + if pygame.key.get_pressed()[pygame.K_DOWN]: + self._view.y -= 10 + + if pygame.key.get_pressed()[pygame.K_LEFT]: + self._view.x += 10 + + if pygame.key.get_pressed()[pygame.K_RIGHT]: + self._view.x -= 10 + + if self._view.z < 0.1: + self._view.z = 0.1 + + if self._view.z > 5: + self._view.z = 5 + + def clear_paper(self): + self.paper.fill('white') + + def _draw(self, screen): + screen.blit( + pygame.transform.smoothscale_by(self.paper, self._view.z), + (self._view.x,self._view.y), + ) \ No newline at end of file From 11b8ee0b6e97151a9dde634b3d42e4ef3041f80b Mon Sep 17 00:00:00 2001 From: HSMarieK Date: Sat, 13 Dec 2025 10:26:52 +0100 Subject: [PATCH 02/10] added_visualization_library_and_zoom_in_line --- lineflow/simulation/line.py | 34 +++++++++++++++++----------- lineflow/simulation/visualization.py | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lineflow/simulation/line.py b/lineflow/simulation/line.py index 88f0a2f..40bf4a7 100644 --- a/lineflow/simulation/line.py +++ b/lineflow/simulation/line.py @@ -175,7 +175,7 @@ def _register_objects_at_env(self): for o in self._objects.values(): o.register(self.env) - def _draw(self, screen, actions=None): + def _draw(self, screen, paper, actions=None): for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -191,15 +191,14 @@ def _draw(self, screen, actions=None): f'#Parts={self.get_n_parts_produced()}', True, 'black' ) - screen.blit(time, time.get_rect(center=(30, 30))) - screen.blit(n_parts, n_parts.get_rect(center=(30, 50))) - # Draw objects, first connectors, then stations - self._draw_connectors(screen) - self._draw_stations(screen) + self._draw_connectors(paper) + self._draw_stations(paper) if actions: - self._draw_actions(screen, actions) - pygame.display.flip() + self._draw_actions(paper, actions) + + screen.blit(time, time.get_rect(center=(30, 30))) + screen.blit(n_parts, n_parts.get_rect(center=(30, 50))) def _draw_actions(self, screen, actions): font = pygame.font.SysFont(None, 20) @@ -226,8 +225,7 @@ def setup_draw(self): if hasattr(o, "position"): x.append(o.position[0]) y.append(o.position[1]) - - return pygame.display.set_mode(flags=pygame.SCALED), Viewpoint(size=(max(x) + 100, max(y) + 100)) + return (max(x)+100,max(y)+100) def teardown_draw(self): pygame.quit() @@ -290,7 +288,9 @@ def run( if visualize: # Stations first, then connectors - screen = self.setup_draw() + screen = pygame.display.set_mode((1280, 720)) + Viewpoint1 = Viewpoint(size=self.setup_draw()) + # Register objects when simulation is initially started if len(self.env._queue) == 0: @@ -318,10 +318,18 @@ def run( self.apply(actions) if visualize: + + Viewpoint1.check_view_update() + Viewpoint1.clear_paper() + if actions is not None: - self._draw(screen, actions) + self._draw(screen, Viewpoint1.paper, actions) else: - self._draw(screen) + self._draw(screen, Viewpoint1.paper) + + Viewpoint1._draw(screen) + + pygame.display.flip() if capture_screen and visualize: pygame.image.save(screen, f"{self.name}.png") diff --git a/lineflow/simulation/visualization.py b/lineflow/simulation/visualization.py index e75b9ac..5ceda05 100644 --- a/lineflow/simulation/visualization.py +++ b/lineflow/simulation/visualization.py @@ -4,8 +4,8 @@ class Viewpoint: def __init__( self, - position=None, size=None, + position=None, zoom=1, ): From 6cdfcddc0c191f124a86f05ad256b57b40d6240f Mon Sep 17 00:00:00 2001 From: Tobias Windisch Date: Sat, 13 Dec 2025 20:45:14 +0100 Subject: [PATCH 03/10] fix test Signed-off-by: Tobias Windisch --- tests/test_line.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_line.py b/tests/test_line.py index c622290..4181462 100644 --- a/tests/test_line.py +++ b/tests/test_line.py @@ -157,7 +157,7 @@ def test_setup_draw(self): self.line.build() # Make sure the line is built before testing # Run the setup_draw method - screen = self.line.setup_draw() + (width, height) = self.line.setup_draw() # Validate screen dimensions x_positions = [o.position[0] for o in self.line._objects.values() if isinstance(o, Station)] @@ -166,5 +166,5 @@ def test_setup_draw(self): expected_width = max(x_positions) + 100 expected_height = max(y_positions) + 100 - self.assertEqual(screen.get_width(), expected_width) - self.assertEqual(screen.get_height(), expected_height) + self.assertEqual(width, expected_width) + self.assertEqual(height, expected_height) From b63db1d7d29253ff2a2f2872891314fe7ddb39be Mon Sep 17 00:00:00 2001 From: HSMarieK Date: Mon, 15 Dec 2025 16:40:39 +0100 Subject: [PATCH 04/10] changed_Viewpoint1_to_viewpoint_added_initial_zoom_option --- lineflow/simulation/line.py | 13 +++++++------ lineflow/simulation/visualization.py | 5 ++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lineflow/simulation/line.py b/lineflow/simulation/line.py index 40bf4a7..2824691 100644 --- a/lineflow/simulation/line.py +++ b/lineflow/simulation/line.py @@ -274,6 +274,7 @@ def run( show_status=True, visualize=False, capture_screen=False, + initial_zoom=None, ): """ Args: @@ -289,7 +290,7 @@ def run( if visualize: # Stations first, then connectors screen = pygame.display.set_mode((1280, 720)) - Viewpoint1 = Viewpoint(size=self.setup_draw()) + viewpoint = Viewpoint(size=self.setup_draw(), zoom=initial_zoom) # Register objects when simulation is initially started @@ -319,15 +320,15 @@ def run( if visualize: - Viewpoint1.check_view_update() - Viewpoint1.clear_paper() + viewpoint.check_view_update() + viewpoint.clear_paper() if actions is not None: - self._draw(screen, Viewpoint1.paper, actions) + self._draw(screen, viewpoint.paper, actions) else: - self._draw(screen, Viewpoint1.paper) + self._draw(screen, viewpoint.paper) - Viewpoint1._draw(screen) + viewpoint._draw(screen) pygame.display.flip() diff --git a/lineflow/simulation/visualization.py b/lineflow/simulation/visualization.py index 5ceda05..74db00a 100644 --- a/lineflow/simulation/visualization.py +++ b/lineflow/simulation/visualization.py @@ -6,7 +6,7 @@ def __init__( self, size=None, position=None, - zoom=1, + zoom=None, ): if size is None: @@ -17,6 +17,9 @@ def __init__( if position is None: position = (0, 0) + if zoom is None: + zoom = 1 + self._view = pygame.Vector3(position[0], position[1], zoom) def check_view_update(self): From dd71dba99d947471ab03382d4bc7cfea2427b42e Mon Sep 17 00:00:00 2001 From: HSMarieK Date: Mon, 15 Dec 2025 17:44:16 +0100 Subject: [PATCH 05/10] time_and_parts_produced_are_now_in_front_of_the_paper --- lineflow/simulation/line.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lineflow/simulation/line.py b/lineflow/simulation/line.py index 2824691..0cf85cd 100644 --- a/lineflow/simulation/line.py +++ b/lineflow/simulation/line.py @@ -183,7 +183,9 @@ def _draw(self, screen, paper, actions=None): sys.exit() screen.fill('white') - + + self.viewpoint.clear_paper() + font = pygame.font.SysFont(None, 20) time = font.render('T={:.2f}'.format(self.env.now), True, 'black') @@ -196,10 +198,13 @@ def _draw(self, screen, paper, actions=None): self._draw_stations(paper) if actions: self._draw_actions(paper, actions) - + + self.viewpoint._draw(screen) screen.blit(time, time.get_rect(center=(30, 30))) screen.blit(n_parts, n_parts.get_rect(center=(30, 50))) + pygame.display.flip() + def _draw_actions(self, screen, actions): font = pygame.font.SysFont(None, 20) actions = font.render(f'{actions}', True, 'black') @@ -290,7 +295,7 @@ def run( if visualize: # Stations first, then connectors screen = pygame.display.set_mode((1280, 720)) - viewpoint = Viewpoint(size=self.setup_draw(), zoom=initial_zoom) + self.viewpoint = Viewpoint(size=self.setup_draw(), zoom=initial_zoom) # Register objects when simulation is initially started @@ -320,17 +325,12 @@ def run( if visualize: - viewpoint.check_view_update() - viewpoint.clear_paper() + self.viewpoint.check_view_update() if actions is not None: - self._draw(screen, viewpoint.paper, actions) + self._draw(screen, self.viewpoint.paper, actions) else: - self._draw(screen, viewpoint.paper) - - viewpoint._draw(screen) - - pygame.display.flip() + self._draw(screen, self.viewpoint.paper) if capture_screen and visualize: pygame.image.save(screen, f"{self.name}.png") From b83ffc133c1fbe6bd331c551390c0ecee5ca4500 Mon Sep 17 00:00:00 2001 From: Tobias Windisch Date: Mon, 15 Dec 2025 19:24:19 +0100 Subject: [PATCH 06/10] add Marie as contributor Signed-off-by: Tobias Windisch --- VERSION | 2 +- docs/index.md | 22 ++++++++++++++-------- lineflow/examples/worker_assignment.py | 3 +-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/VERSION b/VERSION index 6e8bf73..0ea3a94 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0 +0.2.0 diff --git a/docs/index.md b/docs/index.md index c105f53..0724c97 100644 --- a/docs/index.md +++ b/docs/index.md @@ -24,15 +24,20 @@ If you use our work in your research, please consider citing us with ``` -@misc{müller2025lineflowframeworklearnactive, - title={LineFlow: A Framework to Learn Active Control of Production Lines}, - author={Kai Müller and Martin Wenzel and Tobias Windisch}, - year={2025}, - eprint={2505.06744}, - archivePrefix={arXiv}, - primaryClass={cs.LG}, - url={https://arxiv.org/abs/2505.06744}, +@InProceedings{pmlr-v267-muller25c, + title = {{L}ine{F}low: A Framework to Learn Active Control of Production Lines}, + author = {M\"{u}ller, Kai and Wenzel, Martin and Windisch, Tobias}, + booktitle = {Proceedings of the 42nd International Conference on Machine Learning}, + pages = {45212--45235}, + year = {2025}, + editor = {Singh, Aarti and Fazel, Maryam and Hsu, Daniel and Lacoste-Julien, Simon and Berkenkamp, Felix and Maharaj, Tegan and Wagstaff, Kiri and Zhu, Jerry}, + volume = {267}, + series = {Proceedings of Machine Learning Research}, + month = {13--19 Jul}, + publisher = {PMLR}, + url = {https://proceedings.mlr.press/v267/muller25c.html}, } + ``` ## Authors @@ -40,6 +45,7 @@ If you use our work in your research, please consider citing us with - [Kai Müller](https://mueller-kai.github.io) (University of Applied Sciences, Kempten) - [Tobias Windisch](https://www.tobias-windisch.de) (University of Applied Sciences, Kempten) - Martin Wenzel (University of Applied Sciences, Kempten) +- Marie Kraus (University of Applied Sciences, Kempten) ## Funding diff --git a/lineflow/examples/worker_assignment.py b/lineflow/examples/worker_assignment.py index 56ef5a7..b62313a 100644 --- a/lineflow/examples/worker_assignment.py +++ b/lineflow/examples/worker_assignment.py @@ -113,5 +113,4 @@ def build(self): line = WorkerAssignment(with_rework=True, realtime=False, n_assemblies=7, step_size=2) agent = make_random_agent(7) - line.run(simulation_end=1000, agent=agent, visualize=True, capture_screen=True) - print(line.get_n_parts_produced()) + line.run(simulation_end=1000, agent=agent, visualize=True, capture_screen=False) From 4f0c75786a6e2e76efe940c6c36e33bd8b8a631d Mon Sep 17 00:00:00 2001 From: Tobias Windisch Date: Mon, 15 Dec 2025 20:04:18 +0100 Subject: [PATCH 07/10] restructure a bit Signed-off-by: Tobias Windisch --- docs/userguide/visualization.md | 5 ++ lineflow/simulation/line.py | 78 ++++++++++++---------------- lineflow/simulation/visualization.py | 40 ++++++++------ tests/test_line.py | 17 ------ 4 files changed, 64 insertions(+), 76 deletions(-) diff --git a/docs/userguide/visualization.md b/docs/userguide/visualization.md index 4591d83..40201e5 100644 --- a/docs/userguide/visualization.md +++ b/docs/userguide/visualization.md @@ -75,3 +75,8 @@ This will: - Run the simulation in real-time (`realtime=True`). - Display the visualization (`visualize=True`) at normal speed (`factor=1.0`). + +## Zooming and Panning + +Using `+` and `-` keys, you can zoom in and out of the visualization. Moreover, using the arrow +keys, you can pan around the visualization area to explore different parts of the line. diff --git a/lineflow/simulation/line.py b/lineflow/simulation/line.py index 0cf85cd..7d245db 100644 --- a/lineflow/simulation/line.py +++ b/lineflow/simulation/line.py @@ -175,51 +175,51 @@ def _register_objects_at_env(self): for o in self._objects.values(): o.register(self.env) - def _draw(self, screen, paper, actions=None): + def _draw(self, actions=None): - for event in pygame.event.get(): - if event.type == pygame.QUIT: - self.teardown_draw() - sys.exit() + self.viewpoint.check_user_input() - screen.fill('white') + self.viewpoint.clear() - self.viewpoint.clear_paper() + # Draw objects, first connectors, then stations + self._draw_connectors() + self._draw_stations() + self.viewpoint._draw() + + if actions is not None: + self._draw_actions(actions) + + self._draw_info() + + pygame.display.flip() + + def _draw_info(self): + font = pygame.font.SysFont(None, 20) time = font.render('T={:.2f}'.format(self.env.now), True, 'black') n_parts = font.render( f'#Parts={self.get_n_parts_produced()}', True, 'black' ) + self.viewpoint.screen.blit(time, time.get_rect(center=(30, 30))) + self.viewpoint.screen.blit(n_parts, n_parts.get_rect(center=(30, 50))) - # Draw objects, first connectors, then stations - self._draw_connectors(paper) - self._draw_stations(paper) - if actions: - self._draw_actions(paper, actions) - - self.viewpoint._draw(screen) - screen.blit(time, time.get_rect(center=(30, 30))) - screen.blit(n_parts, n_parts.get_rect(center=(30, 50))) - - pygame.display.flip() - - def _draw_actions(self, screen, actions): + def _draw_actions(self, actions): font = pygame.font.SysFont(None, 20) actions = font.render(f'{actions}', True, 'black') - screen.blit(actions, actions.get_rect(center=(500, 30))) + self.viewpoint.screen.blit(actions, actions.get_rect(center=(500, 30))) - def _draw_stations(self, screen): - self._draw_objects_of_type(screen, Station) + def _draw_stations(self): + self._draw_objects_of_type(Station) - def _draw_connectors(self, screen): - self._draw_objects_of_type(screen, Connector) + def _draw_connectors(self): + self._draw_objects_of_type(Connector) - def _draw_objects_of_type(self, screen, object_type): - for name, obj in self._objects.items(): + def _draw_objects_of_type(self, object_type): + for _, obj in self._objects.items(): if isinstance(obj, object_type): - obj._draw(screen) + obj._draw(self.viewpoint.paper) def setup_draw(self): pygame.init() @@ -230,10 +230,9 @@ def setup_draw(self): if hasattr(o, "position"): x.append(o.position[0]) y.append(o.position[1]) - return (max(x)+100,max(y)+100) + + self.viewpoint = Viewpoint(size=(max(x)+100,max(y)+100)) - def teardown_draw(self): - pygame.quit() def apply(self, values): for object_name in values.keys(): @@ -279,7 +278,6 @@ def run( show_status=True, visualize=False, capture_screen=False, - initial_zoom=None, ): """ Args: @@ -293,9 +291,7 @@ def run( """ if visualize: - # Stations first, then connectors - screen = pygame.display.set_mode((1280, 720)) - self.viewpoint = Viewpoint(size=self.setup_draw(), zoom=initial_zoom) + self.setup_draw() # Register objects when simulation is initially started @@ -324,19 +320,13 @@ def run( self.apply(actions) if visualize: - - self.viewpoint.check_view_update() - - if actions is not None: - self._draw(screen, self.viewpoint.paper, actions) - else: - self._draw(screen, self.viewpoint.paper) + self._draw(actions) if capture_screen and visualize: - pygame.image.save(screen, f"{self.name}.png") + pygame.image.save(self.viewpoint.screen, f"{self.name}.png") if visualize: - self.teardown_draw() + self.viewpoint.teardown() def get_observations(self, object_name=None): """ diff --git a/lineflow/simulation/visualization.py b/lineflow/simulation/visualization.py index 74db00a..b5de182 100644 --- a/lineflow/simulation/visualization.py +++ b/lineflow/simulation/visualization.py @@ -1,28 +1,32 @@ import pygame +import sys class Viewpoint: + """ + A class to manage the viewpoint for rendering a 2D surface with zoom and pan capabilities. + """ def __init__( self, size=None, position=None, - zoom=None, + zoom=1, ): + if size is None: size = (1410, 1000) - self.paper = pygame.Surface(size) - if position is None: - position = (0, 0) - if zoom is None: - zoom = 1 + self.screen = pygame.display.set_mode((1280, 720)) + if position is None: + position = (0, 0) + self._view = pygame.Vector3(position[0], position[1], zoom) - def check_view_update(self): + def check_user_input(self): if pygame.key.get_pressed()[pygame.K_PLUS]: self._view.z += 0.1 @@ -42,17 +46,23 @@ def check_view_update(self): if pygame.key.get_pressed()[pygame.K_RIGHT]: self._view.x -= 10 - if self._view.z < 0.1: - self._view.z = 0.1 + for event in pygame.event.get(): + if event.type == pygame.QUIT: + self.teardown() - if self._view.z > 5: - self._view.z = 5 + self._view.z = max(self._view.z, 0.1) + self._view.z = min(self._view.z, 5) - def clear_paper(self): + def clear(self): + self.screen.fill('white') self.paper.fill('white') - def _draw(self, screen): - screen.blit( + def _draw(self): + self.screen.blit( pygame.transform.smoothscale_by(self.paper, self._view.z), (self._view.x,self._view.y), - ) \ No newline at end of file + ) + + def teardown(self): + pygame.quit() + sys.exit() diff --git a/tests/test_line.py b/tests/test_line.py index 4181462..1c56ea8 100644 --- a/tests/test_line.py +++ b/tests/test_line.py @@ -151,20 +151,3 @@ def test_step_function(self): state, terminated = self.line.step() # Check if another step_size is passed self.assertTrue(state.df()["T_end"].iloc[-1] == self.line.step_size * 2) - - def test_setup_draw(self): - self.line = ShowCase() - self.line.build() # Make sure the line is built before testing - - # Run the setup_draw method - (width, height) = self.line.setup_draw() - - # Validate screen dimensions - x_positions = [o.position[0] for o in self.line._objects.values() if isinstance(o, Station)] - y_positions = [o.position[1] for o in self.line._objects.values() if isinstance(o, Station)] - - expected_width = max(x_positions) + 100 - expected_height = max(y_positions) + 100 - - self.assertEqual(width, expected_width) - self.assertEqual(height, expected_height) From c7d1bb8fc3828f79b2e0c0718f1b7e027fcb187f Mon Sep 17 00:00:00 2001 From: Tobias Windisch Date: Mon, 15 Dec 2025 20:15:58 +0100 Subject: [PATCH 08/10] adjust version Signed-off-by: Tobias Windisch --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0ea3a94..6e8bf73 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 +0.1.0 From c5cf2ba32b89cac660e00cc92b082a7eccd3fe44 Mon Sep 17 00:00:00 2001 From: HSMarieK Date: Sat, 20 Dec 2025 11:35:03 +0100 Subject: [PATCH 09/10] fixed_negative_position_values_getting_out_of_bounds --- lineflow/simulation/line.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lineflow/simulation/line.py b/lineflow/simulation/line.py index 7d245db..dcfc8ae 100644 --- a/lineflow/simulation/line.py +++ b/lineflow/simulation/line.py @@ -230,7 +230,26 @@ def setup_draw(self): if hasattr(o, "position"): x.append(o.position[0]) y.append(o.position[1]) - + + if min(x) < 100: + delta_x = 100 - min(x) + for o in self._objects.values(): + if hasattr(o, "position"): + o.position[0] += delta_x + if min(y) < 100: + delta_y = 100 - min(y) + for o in self._objects.values(): + if hasattr(o, "position"): + o.position[1] += delta_y + + x = [] + y = [] + for o in self._objects.values(): + o.setup_draw() + if hasattr(o, "position"): + x.append(o.position[0]) + y.append(o.position[1]) + self.viewpoint = Viewpoint(size=(max(x)+100,max(y)+100)) From 17dee82c71af110fd80ae4c0d94421e3c4a6df17 Mon Sep 17 00:00:00 2001 From: Tobias Windisch Date: Sat, 20 Dec 2025 18:51:03 +0100 Subject: [PATCH 10/10] tiny beautification Signed-off-by: Tobias Windisch --- lineflow/examples/multi_process.py | 2 +- lineflow/simulation/line.py | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lineflow/examples/multi_process.py b/lineflow/examples/multi_process.py index b6bdf7d..0753683 100644 --- a/lineflow/examples/multi_process.py +++ b/lineflow/examples/multi_process.py @@ -95,7 +95,7 @@ def build(self): if __name__ == "__main__": - n_processes = 5 + n_processes = 10 line = MultiProcess(n_processes=n_processes, realtime=True, factor=0.1, alternate=False) agent = make_greedy_policy(n_processes) line.run(simulation_end=3000, agent=agent, visualize=True) diff --git a/lineflow/simulation/line.py b/lineflow/simulation/line.py index dcfc8ae..914c1ea 100644 --- a/lineflow/simulation/line.py +++ b/lineflow/simulation/line.py @@ -221,15 +221,17 @@ def _draw_objects_of_type(self, object_type): if isinstance(obj, object_type): obj._draw(self.viewpoint.paper) - def setup_draw(self): - pygame.init() + def _get_object_positions(self): x = [] y = [] for o in self._objects.values(): - o.setup_draw() if hasattr(o, "position"): x.append(o.position[0]) y.append(o.position[1]) + return x, y + + def _adjust_positions(self): + x, y = self._get_object_positions() if min(x) < 100: delta_x = 100 - min(x) @@ -242,16 +244,17 @@ def setup_draw(self): if hasattr(o, "position"): o.position[1] += delta_y - x = [] - y = [] + x, y = self._get_object_positions() + return max(x), max(y) + + def setup_draw(self): + pygame.init() + + max_x, max_y = self._adjust_positions() for o in self._objects.values(): o.setup_draw() - if hasattr(o, "position"): - x.append(o.position[0]) - y.append(o.position[1]) - - self.viewpoint = Viewpoint(size=(max(x)+100,max(y)+100)) + self.viewpoint = Viewpoint(size=(max_x+100, max_y+100)) def apply(self, values): for object_name in values.keys():