Skip to content

Commit 1d771bf

Browse files
committed
New mesh analysis structure to allow only topological analysis and action validation.
There are still some issues that need to be corrected.
1 parent 7e9db50 commit 1d771bf

File tree

11 files changed

+832
-659
lines changed

11 files changed

+832
-659
lines changed

environment/actions/smoothing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from mesh_model.mesh_struct.mesh import Mesh
44
from mesh_model.mesh_struct.mesh_elements import Node
5-
from mesh_model.mesh_analysis.global_mesh_analysis import adjacent_darts, on_boundary
5+
from mesh_model.mesh_analysis.global_mesh_analysis import GlobalMeshAnalysis
66

77
def smoothing_mean(mesh: Mesh) -> True:
88
for i in range (20):
Lines changed: 86 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
from __future__ import annotations
22

3-
from mesh_model.mesh_struct.mesh import Mesh
4-
from mesh_model.mesh_struct.mesh_elements import Node
5-
from mesh_model.mesh_analysis.global_mesh_analysis import mesh_check
6-
from mesh_model.mesh_analysis.trimesh_analysis import isFlipOk, isCollapseOk, isSplitOk
3+
from mesh_model.mesh_analysis.trimesh_analysis import TriMeshTopoAnalysis, TriMeshGeoAnalysis
4+
from mesh_model.mesh_struct.mesh_elements import Node, Dart
5+
from view.mesh_plotter.mesh_plots import plot_mesh
76

7+
"""
8+
Actions triangulaires réalisées sur les maillages.
9+
Chaque fonction retourne trois booléens:
10+
* action_validity : Si l'action a été réalisée
11+
* topo : Si l'action est valide topologiquement
12+
* geo : si l'action est valide géométriquement
13+
"""
814

9-
def flip_edge_ids(mesh: Mesh, id1: int, id2: int) -> True:
10-
return flip_edge(mesh, Node(mesh, id1), Node(mesh, id2))
15+
def flip_edge_ids(mesh_analysis, id1: int, id2: int) -> True:
16+
return flip_edge(mesh_analysis, Node(mesh_analysis.mesh, id1), Node(mesh_analysis.mesh, id2))
1117

1218

13-
def flip_edge(mesh: Mesh, n1: Node, n2: Node) -> True:
14-
found, d = mesh.find_inner_edge(n1, n2)
19+
def flip_edge(mesh_analysis, n1: Node, n2: Node) -> True:
20+
found, d = mesh_analysis.mesh.find_inner_edge(n1, n2)
21+
1522
if found:
16-
topo, geo = isFlipOk(d)
23+
topo, geo = mesh_analysis.isSplitOk(d)
1724
if not geo or not topo:
1825
return False, topo, geo
1926
else:
20-
return False, False, False
27+
return False, False, True # the geometrical criteria is True because if the dart is not found, it means it's a boundary dart
28+
2129

22-
d2, d1, d11, d21, d211, n1, n2, n3, n4 = mesh.active_triangles(d)
30+
d2, d1, d11, d21, d211, n1, n2, n3, n4 = mesh_analysis.mesh.active_triangles(d)
2331

2432
f1 = d.get_face()
2533
f2 = d2.get_face()
@@ -46,27 +54,29 @@ def flip_edge(mesh: Mesh, n1: Node, n2: Node) -> True:
4654
d2.set_node(n4)
4755
d211.set_face(f1)
4856
d11.set_face(f2)
57+
58+
check_mesh(mesh_analysis)
4959
return True, topo, geo
5060

5161

52-
def split_edge_ids(mesh: Mesh, id1: int, id2: int) -> True:
53-
return split_edge(mesh, Node(mesh, id1), Node(mesh, id2))
62+
def split_edge_ids(mesh_analysis, id1: int, id2: int) -> True:
63+
return split_edge(mesh_analysis, Node(mesh_analysis.mesh, id1), Node(mesh_analysis.mesh, id2))
5464

5565

56-
def split_edge(mesh: Mesh, n1: Node, n2: Node) -> True:
57-
found, d = mesh.find_inner_edge(n1, n2)
66+
def split_edge(mesh_analysis, n1: Node, n2: Node) -> True:
67+
found, d = mesh_analysis.mesh.find_inner_edge(n1, n2)
5868

5969
if found:
60-
topo, geo = isSplitOk(d)
70+
topo, geo = mesh_analysis.isSplitOk(d)
6171
if not geo or not topo:
6272
return False, topo, geo
6373
else:
64-
return False, True, False
74+
return False, False, True # the geometrical criteria is True because if the dart is not found, it means it's a boundary dart
6575

66-
d2, d1, _, d21, _, n1, n2, n3, n4 = mesh.active_triangles(d)
76+
d2, d1, _, d21, _, n1, n2, n3, n4 = mesh_analysis.mesh.active_triangles(d)
6777

6878
# create a new node in the middle of [n1, n2]
69-
N5 = mesh.add_node((n1.x() + n2.x()) / 2, (n1.y() + n2.y()) / 2)
79+
N5 = mesh_analysis.mesh.add_node((n1.x() + n2.x()) / 2, (n1.y() + n2.y()) / 2)
7080

7181
# modify existing triangles
7282
d1.set_node(N5)
@@ -75,64 +85,83 @@ def split_edge(mesh: Mesh, n1: Node, n2: Node) -> True:
7585
d2.set_beta(1, d21)
7686

7787
# create 2 new triangles
78-
F3 = mesh.add_triangle(n2, n3, N5)
79-
F4 = mesh.add_triangle(N5, n1, n4)
88+
F3 = mesh_analysis.mesh.add_triangle(n2, n3, N5)
89+
F4 = mesh_analysis.mesh.add_triangle(N5, n1, n4)
8090

8191
# update beta2 relations
82-
mesh.set_face_beta2(F3, [d1, d2])
83-
d2b2 = d2.get_beta(2)
84-
d2b21 = d2b2.get_beta(1)
85-
mesh.set_beta2(d2b21)
86-
mesh.set_face_beta2(F4, [d, d21])
87-
db2 = d.get_beta(2)
88-
db21 = db2.get_beta(1)
89-
mesh.set_beta2(db21)
92+
mesh_analysis.mesh.set_face_beta2(F3, [d1, d2, d1.get_beta(2)])
93+
mesh_analysis.mesh.set_face_beta2(F4, [d, d21, d21.get_beta(2)])
94+
95+
check_mesh(mesh_analysis)
9096
return True, topo, geo
9197

9298

93-
def collapse_edge_ids(mesh: Mesh, id1: int, id2: int) -> True:
94-
return collapse_edge(mesh, Node(mesh, id1), Node(mesh, id2))
99+
def collapse_edge_ids(mesh_analysis, id1: int, id2: int) -> True:
100+
return collapse_edge(mesh_analysis, Node(mesh_analysis.mesh, id1), Node(mesh_analysis.mesh, id2))
101+
95102

103+
def collapse_edge(mesh_analysis, n1: Node, n2: Node) -> True:
104+
found, d = mesh_analysis.mesh.find_inner_edge(n1, n2)
96105

97-
def collapse_edge(mesh: Mesh, n1: Node, n2: Node) -> True:
98-
found, d = mesh.find_inner_edge(n1, n2)
99106
if found:
100-
topo, geo = isCollapseOk(d)
107+
topo, geo = mesh_analysis.isCollapseOk(d)
101108
if not geo or not topo:
102109
return False, topo, geo
103110
else:
104-
return False, False, False
111+
return False, False, True # the geometrical criteria is True because if the dart is not found, it means it's a boundary dart
105112

106-
_, d1, d11, d21, d211, n1, n2, _, _ = mesh.active_triangles(d)
113+
_, d1, d11, d21, d211, n1, n2, n3, n4 = mesh_analysis.mesh.active_triangles(d)
107114

108115
d212 = d21.get_beta(2) #T1
109116
d2112 = d211.get_beta(2) #T2
110117
d12 = d1.get_beta(2) #T3
111118
d112 = d11.get_beta(2) #T4
112119

113120
#Delete the darts around selected dart
114-
mesh.del_adj_triangles(d)
121+
mesh_analysis.mesh.del_adj_triangles(d)
115122

116123
#Move n1 node in the middle of [n1, n2]
117124
n1.set_xy((n1.x() + n2.x()) / 2, (n1.y() + n2.y()) / 2)
125+
i = 0
126+
127+
#Check if nodes n3 and n4 are not linked to deleted dart
128+
129+
if n3.get_dart().id == d11.id:
130+
if d12 is not None:
131+
n3.set_dart(d12)
132+
else:
133+
n3.set_dart(d112.get_beta(1))
134+
if n4.get_dart().id == d211.id:
135+
if d212 is not None:
136+
n4.set_dart(d212)
137+
else:
138+
n4.set_dart(d2112.get_beta(1))
118139

119140
#Update node relations
120141
if d12 is not None:
121142
d121 = d12.get_beta(1)
122143
d121.set_node(n1)
123144
ds = d121
124145
while ds is not None and ds != d2112:
146+
i+=1
125147
d2s = ds.get_beta(2)
126148
if d2s is None:
127149
ds = d2112
128150
while ds is not None:
151+
i+=1
129152
ds.set_node(n1)
130153
ds1 = ds.get_beta(1)
131154
ds11 = ds1.get_beta(1)
132155
ds = ds11.get_beta(2)
156+
if i > 30:
157+
i = 0
158+
plot_mesh(mesh_analysis.mesh)
133159
else:
134160
ds = d2s.get_beta(1)
135161
ds.set_node(n1)
162+
if i>30:
163+
i=0
164+
plot_mesh(mesh_analysis.mesh)
136165
"""
137166
elif d12 is None and d2112 is not None:
138167
d2112.set_node(n1)
@@ -155,6 +184,24 @@ def collapse_edge(mesh: Mesh, n1: Node, n2: Node) -> True:
155184
d2112.set_beta(2, d212)
156185

157186
#delete n2 node
158-
mesh.del_node(n2)
187+
mesh_analysis.mesh.del_node(n2)
188+
189+
check_mesh(mesh_analysis)
190+
return True, topo, geo
159191

160-
return mesh_check(mesh), topo, geo
192+
def check_mesh(mesh_analysis):
193+
for dart_info in mesh_analysis.mesh.active_darts():
194+
#Check beta2 relation
195+
d = dart_info[0]
196+
d2 = dart_info[2]
197+
if d2 >= 0 and mesh_analysis.mesh.dart_info[d2, 0] < 0:
198+
raise ValueError("error beta2")
199+
elif d2 >= 0 and mesh_analysis.mesh.dart_info[d2, 2] != d:
200+
raise ValueError("error beta2")
201+
202+
#Check beta1
203+
d = Dart(mesh_analysis.mesh, d)
204+
d1 = d.get_beta(1)
205+
d11 = d1.get_beta(1)
206+
if d11.get_beta(1)!=d :
207+
raise ValueError("error beta1")

environment/gymnasium_envs/quadmesh_env/envs/quadmesh.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from mesh_model.random_quadmesh import random_mesh
1515
from mesh_model.mesh_struct.mesh_elements import Dart
16-
from mesh_model.mesh_analysis.global_mesh_analysis import global_score
16+
from mesh_model.mesh_analysis.global_mesh_analysis import GlobalMeshAnalysis
1717
from mesh_model.mesh_analysis.quadmesh_analysis import isTruncated
1818
from environment.gymnasium_envs.quadmesh_env.envs.mesh_conv import get_x
1919
from environment.actions.quadrangular_actions import flip_edge_cntcw, flip_edge_cw, split_edge, collapse_edge, cleanup_edge
@@ -70,10 +70,10 @@ def __init__(
7070
else :
7171
self.config = {"mesh": None}
7272
self.mesh = random_mesh()
73-
73+
self.mesh_analysis = GlobalMeshAnalysis(self.mesh)
7474
#self.mesh_size = len(self.mesh.nodes)
7575
#self.nb_darts = len(self.mesh.dart_info)
76-
self._nodes_scores, self._mesh_score, self._ideal_score, self._nodes_adjacency = global_score(self.mesh)
76+
self._nodes_scores, self._mesh_score, self._ideal_score, self._nodes_adjacency = self.mesh_analysis.global_score()
7777
self._ideal_rewards = (self._mesh_score - self._ideal_score)*10 #arbitrary factor of 10 for rewards
7878
self.next_mesh_score = 0
7979
self.n_darts_selected = n_darts_selected
@@ -137,7 +137,7 @@ def reset(self, seed=None, options=None):
137137
else:
138138
self.mesh = random_mesh()
139139
#self.nb_darts = len(self.mesh.dart_info)
140-
self._nodes_scores, self._mesh_score, self._ideal_score, self._nodes_adjacency = global_score(self.mesh)
140+
self._nodes_scores, self._mesh_score, self._ideal_score, self._nodes_adjacency = self.mesh_analysis.global_score()
141141
self._ideal_rewards = (self._mesh_score - self._ideal_score) * 10
142142
self.nb_invalid_actions = 0
143143
self.close()
@@ -230,7 +230,7 @@ def step(self, action: np.ndarray):
230230

231231
if valid_action:
232232
# An episode is done if the actual score is the same as the ideal
233-
next_nodes_score, self.next_mesh_score, _, next_nodes_adjacency = global_score(self.mesh)
233+
next_nodes_score, self.next_mesh_score, _, next_nodes_adjacency = self.mesh_analysis.global_score()
234234
terminated = np.array_equal(self._ideal_score, self.next_mesh_score)
235235
if terminated:
236236
mesh_reward = (self._mesh_score - self.next_mesh_score)*10

0 commit comments

Comments
 (0)