Add center/scale post-processing, increase diffusion steps to 50
Browse files
app.py
CHANGED
|
@@ -419,6 +419,86 @@ def clean_gcode(gcode: str) -> str:
|
|
| 419 |
return result
|
| 420 |
|
| 421 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 422 |
def validate_gcode(gcode: str) -> str:
|
| 423 |
"""Clamp coordinates to machine bounds."""
|
| 424 |
lines = []
|
|
@@ -710,6 +790,8 @@ def generate(prompt: str, temperature: float, max_tokens: int, num_steps: int, g
|
|
| 710 |
# Clean up the gcode
|
| 711 |
gcode = clean_gcode(gcode)
|
| 712 |
|
|
|
|
|
|
|
| 713 |
gcode = validate_gcode(gcode)
|
| 714 |
line_count = len([l for l in gcode.split("\n") if l.strip()])
|
| 715 |
svg = gcode_to_svg(gcode)
|
|
@@ -830,10 +912,10 @@ with gr.Blocks(css=css, theme=gr.themes.Base()) as demo:
|
|
| 830 |
)
|
| 831 |
|
| 832 |
with gr.Accordion("settings", open=False):
|
| 833 |
-
temperature = gr.Slider(0.3, 1.2, value=0.
|
| 834 |
max_tokens = gr.Slider(256, 2048, value=2048, step=256, label="max tokens")
|
| 835 |
-
num_steps = gr.Slider(20,
|
| 836 |
-
guidance = gr.Slider(5.0, 20.0, value=
|
| 837 |
seed = gr.Number(value=-1, label="seed (-1 = random)", precision=0)
|
| 838 |
|
| 839 |
generate_btn = gr.Button("generate", variant="secondary")
|
|
|
|
| 419 |
return result
|
| 420 |
|
| 421 |
|
| 422 |
+
def center_and_scale_gcode(gcode: str) -> str:
|
| 423 |
+
"""Center the drawing on the workplane and scale to fill 80% of it."""
|
| 424 |
+
lines = gcode.split("\n")
|
| 425 |
+
|
| 426 |
+
# Extract all coordinates
|
| 427 |
+
coords = []
|
| 428 |
+
for line in lines:
|
| 429 |
+
x_match = re.search(r"X([-\d.]+)", line, re.IGNORECASE)
|
| 430 |
+
y_match = re.search(r"Y([-\d.]+)", line, re.IGNORECASE)
|
| 431 |
+
if x_match and y_match:
|
| 432 |
+
try:
|
| 433 |
+
x = float(x_match.group(1))
|
| 434 |
+
y = float(y_match.group(1))
|
| 435 |
+
coords.append((x, y))
|
| 436 |
+
except ValueError:
|
| 437 |
+
pass
|
| 438 |
+
|
| 439 |
+
if len(coords) < 2:
|
| 440 |
+
return gcode # Nothing to transform
|
| 441 |
+
|
| 442 |
+
# Find bounding box
|
| 443 |
+
xs = [c[0] for c in coords]
|
| 444 |
+
ys = [c[1] for c in coords]
|
| 445 |
+
min_x, max_x = min(xs), max(xs)
|
| 446 |
+
min_y, max_y = min(ys), max(ys)
|
| 447 |
+
|
| 448 |
+
# Current dimensions
|
| 449 |
+
width = max_x - min_x
|
| 450 |
+
height = max_y - min_y
|
| 451 |
+
|
| 452 |
+
if width < 1 or height < 1:
|
| 453 |
+
return gcode # Degenerate case
|
| 454 |
+
|
| 455 |
+
# Target: 80% of workplane, centered
|
| 456 |
+
target_width = (BOUNDS["right"] - BOUNDS["left"]) * 0.8
|
| 457 |
+
target_height = (BOUNDS["top"] - BOUNDS["bottom"]) * 0.8
|
| 458 |
+
|
| 459 |
+
# Scale to fit (maintain aspect ratio)
|
| 460 |
+
scale = min(target_width / width, target_height / height)
|
| 461 |
+
|
| 462 |
+
# Center of current drawing
|
| 463 |
+
cx = (min_x + max_x) / 2
|
| 464 |
+
cy = (min_y + max_y) / 2
|
| 465 |
+
|
| 466 |
+
# Center of workplane
|
| 467 |
+
target_cx = (BOUNDS["left"] + BOUNDS["right"]) / 2
|
| 468 |
+
target_cy = (BOUNDS["bottom"] + BOUNDS["top"]) / 2
|
| 469 |
+
|
| 470 |
+
print(f"Centering: bbox=({min_x:.0f},{min_y:.0f})-({max_x:.0f},{max_y:.0f}), scale={scale:.2f}")
|
| 471 |
+
|
| 472 |
+
# Transform each line
|
| 473 |
+
result = []
|
| 474 |
+
for line in lines:
|
| 475 |
+
new_line = line
|
| 476 |
+
x_match = re.search(r"X([-\d.]+)", line, re.IGNORECASE)
|
| 477 |
+
y_match = re.search(r"Y([-\d.]+)", line, re.IGNORECASE)
|
| 478 |
+
|
| 479 |
+
if x_match:
|
| 480 |
+
try:
|
| 481 |
+
x = float(x_match.group(1))
|
| 482 |
+
new_x = (x - cx) * scale + target_cx
|
| 483 |
+
new_x = max(BOUNDS["left"], min(BOUNDS["right"], new_x))
|
| 484 |
+
new_line = re.sub(r"X[-\d.]+", f"X{new_x:.2f}", new_line, count=1, flags=re.IGNORECASE)
|
| 485 |
+
except ValueError:
|
| 486 |
+
pass
|
| 487 |
+
|
| 488 |
+
if y_match:
|
| 489 |
+
try:
|
| 490 |
+
y = float(y_match.group(1))
|
| 491 |
+
new_y = (y - cy) * scale + target_cy
|
| 492 |
+
new_y = max(BOUNDS["bottom"], min(BOUNDS["top"], new_y))
|
| 493 |
+
new_line = re.sub(r"Y[-\d.]+", f"Y{new_y:.2f}", new_line, count=1, flags=re.IGNORECASE)
|
| 494 |
+
except ValueError:
|
| 495 |
+
pass
|
| 496 |
+
|
| 497 |
+
result.append(new_line)
|
| 498 |
+
|
| 499 |
+
return "\n".join(result)
|
| 500 |
+
|
| 501 |
+
|
| 502 |
def validate_gcode(gcode: str) -> str:
|
| 503 |
"""Clamp coordinates to machine bounds."""
|
| 504 |
lines = []
|
|
|
|
| 790 |
# Clean up the gcode
|
| 791 |
gcode = clean_gcode(gcode)
|
| 792 |
|
| 793 |
+
# Center and scale to fill workplane
|
| 794 |
+
gcode = center_and_scale_gcode(gcode)
|
| 795 |
gcode = validate_gcode(gcode)
|
| 796 |
line_count = len([l for l in gcode.split("\n") if l.strip()])
|
| 797 |
svg = gcode_to_svg(gcode)
|
|
|
|
| 912 |
)
|
| 913 |
|
| 914 |
with gr.Accordion("settings", open=False):
|
| 915 |
+
temperature = gr.Slider(0.3, 1.2, value=0.7, label="temperature", step=0.1)
|
| 916 |
max_tokens = gr.Slider(256, 2048, value=2048, step=256, label="max tokens")
|
| 917 |
+
num_steps = gr.Slider(20, 75, value=50, step=5, label="diffusion steps")
|
| 918 |
+
guidance = gr.Slider(5.0, 20.0, value=12.0, step=0.5, label="guidance")
|
| 919 |
seed = gr.Number(value=-1, label="seed (-1 = random)", precision=0)
|
| 920 |
|
| 921 |
generate_btn = gr.Button("generate", variant="secondary")
|