22import pygame
33import imageio
44import sys
5+ import os
56
67import numpy as np
78import gymnasium as gym
1516
1617from mesh_model .random_trimesh import random_mesh
1718from mesh_model .mesh_struct .mesh_elements import Dart
18- from mesh_model .mesh_analysis .trimesh_analysis import TriMeshQualityAnalysis
19+ from mesh_model .mesh_analysis .trimesh_analysis import TriMeshQualityAnalysis , TriMeshOldAnalysis
1920from environment .gymnasium_envs .trimesh_full_env .envs .mesh_conv import get_x
2021from environment .actions .triangular_actions import flip_edge , split_edge , collapse_edge , check_mesh
2122from view .mesh_plotter .mesh_plots import plot_mesh
@@ -40,19 +41,28 @@ def __init__(
4041 mesh = None ,
4142 mesh_size = 9 ,
4243 max_episode_steps = 20 ,
43- n_darts_selected = 20 ,
44+ n_darts_selected = 7 ,
4445 deep = 6 ,
4546 with_quality_obs = False ,
4647 action_restriction = False ,
47- render_mode = None
48+ render_mode = None ,
49+ analysis_type = "quality"
4850 ) -> None :
4951
5052 assert render_mode is None or render_mode in self .metadata ["render_modes" ]
5153 self .render_mode = render_mode
5254
53- self .mesh_size = mesh_size
54- self .mesh = mesh if mesh is not None else random_mesh (mesh_size )
55- self .m_analysis = TriMeshQualityAnalysis (self .mesh )
55+ # If a mesh has been entered, it is used, otherwise a random mesh is generated.
56+ if mesh is not None :
57+ self .config = {"mesh" : mesh }
58+ self .mesh = copy .deepcopy (mesh )
59+ self .mesh_size = 0
60+ else :
61+ self .config = {"mesh" : None }
62+ self .mesh_size = mesh_size
63+ self .mesh = random_mesh (mesh_size )
64+ self .analysis_type = analysis_type
65+ self .m_analysis = TriMeshQualityAnalysis (self .mesh ) if self .analysis_type == "quality" else TriMeshOldAnalysis (self .mesh )
5666 self ._nodes_scores , self ._mesh_score , self ._ideal_score , self ._nodes_adjacency = self .m_analysis .global_score ()
5767 self ._ideal_rewards = (self ._mesh_score - self ._ideal_score )* 10
5868 self .next_mesh_score = 0
@@ -69,6 +79,12 @@ def __init__(
6979 self .darts_selected = []
7080 self .max_steps = max_episode_steps
7181
82+ self .actions_info = {
83+ "n_flip" : 0 ,
84+ "n_split" : 0 ,
85+ "n_collapse" : 0 ,
86+ }
87+
7288 self .observation_space = spaces .Box (
7389 low = - 15 , # nodes min degree : 15
7490 high = 15 , # nodes max degree : 15
@@ -100,15 +116,19 @@ def __init__(
100116
101117 self .recording = False
102118 self .frames = []
119+ self ._render_frame ()
103120
104121 def reset (self , seed = None , options = None ):
105122 # We need the following line to seed self.np_random
106123 super ().reset (seed = seed )
107124 if options is not None :
108125 self .mesh = options ['mesh' ]
126+ elif self .config ["mesh" ] is not None :
127+ self .mesh = copy .deepcopy (self .config ["mesh" ])
109128 else :
110129 self .mesh = random_mesh (self .mesh_size )
111- self .m_analysis = TriMeshQualityAnalysis (self .mesh )
130+
131+ self .m_analysis = TriMeshQualityAnalysis (self .mesh ) if self .analysis_type == "quality" else TriMeshOldAnalysis (self .mesh )
112132 self ._nodes_scores , self ._mesh_score , self ._ideal_score , self ._nodes_adjacency = self .m_analysis .global_score ()
113133 self ._ideal_rewards = (self ._mesh_score - self ._ideal_score ) * 10
114134 self .nb_invalid_actions = 0
@@ -117,9 +137,15 @@ def reset(self, seed=None, options=None):
117137 self .observation = self ._get_obs ()
118138 info = self ._get_info (terminated = False ,valid_act = (None ,None ,None ), action = (None ,None ), mesh_reward = None )
119139
140+ self .actions_info = {
141+ "n_flip" : 0 ,
142+ "n_split" : 0 ,
143+ "n_collapse" : 0 ,
144+ }
145+
120146 if self .render_mode == "human" :
121- self ._render_frame ()
122147 self .recording = True
148+ self ._render_frame ()
123149 else :
124150 self .recording = False
125151
@@ -173,10 +199,13 @@ def step(self, action: np.ndarray):
173199 # before_mesh = deepcopy(self.mesh)
174200 if action [0 ] == Actions .FLIP .value :
175201 valid_action , valid_topo , valid_geo = flip_edge (self .m_analysis , n1 , n2 )
202+ self .actions_info ["n_flip" ] += 1
176203 elif action [0 ] == Actions .SPLIT .value :
177204 valid_action , valid_topo , valid_geo = split_edge (self .m_analysis , n1 , n2 )
205+ self .actions_info ["n_split" ] += 1
178206 elif action [0 ] == Actions .COLLAPSE .value :
179207 valid_action , valid_topo , valid_geo = collapse_edge (self .m_analysis , n1 , n2 )
208+ self .actions_info ["n_collapse" ] += 1
180209 else :
181210 raise ValueError ("Action not defined" )
182211
@@ -214,7 +243,14 @@ def step(self, action: np.ndarray):
214243 #Saving episode rendering as gif
215244 if terminated or self .ep_len >= self .max_steps :
216245 if self .recording and self .frames :
217- imageio .mimsave (f"training/episode_recording/episode_{ self .episode_count } .gif" , self .frames , fps = 1 )
246+ base_path = f"training/episode_recording/del/episode_star_{ self .episode_count } "
247+ filename = base_path + ".gif"
248+ index = 1
249+ while os .path .exists (filename ):
250+ filename = f"{ base_path } _{ index } .gif"
251+ index += 1
252+
253+ imageio .mimsave (filename , self .frames , fps = 1 )
218254 print ("Image recorded" )
219255 self .episode_count += 1
220256
0 commit comments