-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmaze_gcode.py
More file actions
163 lines (126 loc) · 5.59 KB
/
Copy pathmaze_gcode.py
File metadata and controls
163 lines (126 loc) · 5.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import random
from pathlib import Path
def generate_maze_with_efficient_segments(nx, ny, seed=None):
if seed is not None:
random.seed(seed)
class Cell:
def __init__(self, x, y):
self.x = x
self.y = y
self.walls = {'N': True, 'S': True, 'E': True, 'W': True}
self.visited = False
grid = [[Cell(x, y) for x in range(nx)] for y in range(ny)]
segments = [] # Liste de listes de (x, y)
stack = []
start_cell = grid[0][0]
start_cell.visited = True
stack.append(start_cell)
current_segment = [(start_cell.x, start_cell.y)]
directions = [('N', 0, -1), ('S', 0, 1), ('E', 1, 0), ('W', -1, 0)]
while stack:
current = stack[-1]
neighbors = []
for dir_name, dx, dy in directions:
nx_ = current.x + dx
ny_ = current.y + dy
if 0 <= nx_ < nx and 0 <= ny_ < ny and not grid[ny_][nx_].visited:
neighbors.append((dir_name, nx_, ny_))
if neighbors:
dir_name, next_x, next_y = random.choice(neighbors)
next_cell = grid[next_y][next_x]
# Abattre les murs
grid[current.y][current.x].walls[dir_name] = False
opposite = {'N':'S', 'S':'N', 'E':'W', 'W':'E'}[dir_name]
grid[next_y][next_x].walls[opposite] = False
next_cell.visited = True
stack.append(next_cell)
current_segment.append((next_cell.x, next_cell.y))
else:
# Fin de branche → sauvegarder le segment
segments.append(current_segment[:])
stack.pop()
if stack:
# Nouvelle branche commence au point de bifurcation (déjà visité, mais pas dupliqué)
last_x, last_y = current_segment[-1] # inutile, juste pour clarté
current_segment = [(stack[-1].x, stack[-1].y)]
# Ouvrir entrée et sortie
grid[0][0].walls['N'] = False
grid[ny-1][nx-1].walls['S'] = False
return segments
def segments_to_gcode(segments, cell_size=10.0, tool_diameter=5.0,
cut_speed=1200, safe_z=5.0, cut_z=-1.0, spindle_speed=1000):
center_offset = cell_size / 2.0
entry_offset = tool_diameter / 2.0
gcode = []
gcode.append("; Labyrinthe 200x200 mm - VERSION CORRIGEE FINALE")
gcode.append("; Un seul passage usinant par connexion + G0 Z5 entre branches")
gcode.append("; Zero double passage - couverture complete")
gcode.append("G21 ; mm")
gcode.append("G90 ; absolu")
gcode.append(f"M3 S{spindle_speed} ; demarrage broche")
def coord(cx, cy):
return cx * cell_size + center_offset, cy * cell_size + center_offset
# Premier segment
first_seg = segments[0]
fx, fy = coord(*first_seg[0])
gcode.append("G0 Z5")
gcode.append(f"G0 X{fx:.3f} Y{fy + entry_offset:.3f}")
gcode.append(f"G1 Z{cut_z:.3f} F600 ; plongee")
for i in range(1, len(first_seg)):
x, y = coord(*first_seg[i])
gcode.append(f"G1 X{x:.3f} Y{y:.3f} F{cut_speed}")
# Segments suivants
for seg in segments[1:]:
if seg: # sécurité
start_x, start_y = coord(*seg[0])
gcode.append("G0 Z5 ; relevage entre branches")
gcode.append(f"G0 X{start_x:.3f} Y{start_y:.3f}")
gcode.append(f"G1 Z{cut_z:.3f} F600 ; redescente")
for i in range(1, len(seg)):
x, y = coord(*seg[i])
gcode.append(f"G1 X{x:.3f} Y{y:.3f} F{cut_speed}")
# Sortie finale
if segments:
last_seg = segments[-1]
if last_seg:
lx, ly = coord(*last_seg[-1])
gcode.append(f"G1 X{lx:.3f} Y{ly - entry_offset:.3f} F{cut_speed}")
gcode.append("G0 Z5 ; relevage final")
gcode.append("M5 ; arret broche")
gcode.append("M2 ; fin")
return "\n".join(gcode)
# ========================
# Programme principal
# ========================
if __name__ == "__main__":
plate_width = 200.0
plate_height = 200.0
step = 10.0
tool_dia = 5.0
nx = int(plate_width // step) # 20
ny = int(plate_height // step) # 20
print(f"Generation labyrinthe 200x200 mm ({nx}x{ny} cellules)")
print("→ Un seul passage usinant + transitions G0 Z5 optimisees")
# Pour reproductibilite (decommenter pour tests)
# random.seed(42)
segments = generate_maze_with_efficient_segments(nx, ny)
total_cells = sum(len(seg) - 1 for seg in segments) + 1 # connexions + point de depart
unique_cells = len(set(cell for seg in segments for cell in seg))
print(f"Nombre de branches : {len(segments)}")
print(f"Cellules couvertes (connexions usinees +1) : {total_cells}")
print(f"Cellules uniques visitees : {unique_cells} / {nx*ny} → {'OK' if unique_cells == nx*ny else 'ERREUR'}")
gcode = segments_to_gcode(segments,
cell_size=step,
tool_diameter=tool_dia,
cut_speed=1200,
safe_z=5.0,
cut_z=-1.0,
spindle_speed=1000)
output_dir = Path("NC")
output_dir.mkdir(exist_ok=True)
filename = "labyrinthe_200x200_final_corrige.gcode"
full_path = output_dir / filename
with open(full_path, "w", encoding="utf-8") as f:
f.write(gcode)
print(f"G-code genere : {full_path}")
print("Cette version est enfin correcte : couverture complete, zero doublon, temps optimise !")