MichaelRKessler commited on
Commit
b856ea5
·
1 Parent(s): 0359819

Add Travel and Print opacity sliders to G-Code visualization

Browse files
Files changed (2) hide show
  1. app.py +49 -9
  2. gcode_viewer.py +8 -2
app.py CHANGED
@@ -337,26 +337,28 @@ def render_toolpath(
337
  source: str,
338
  uploaded_path: str | None,
339
  shape1_path: str | None,
340
- ) -> tuple[Any, str]:
 
 
341
  if source == GCODE_SOURCE_UPLOAD:
342
  path = uploaded_path
343
  if not path:
344
- return None, "No G-code file uploaded yet."
345
  else:
346
  path = shape1_path
347
  if not path:
348
- return None, "No Shape 1 G-code available yet. Generate it on the TIFF Slices to GCode tab first."
349
 
350
  try:
351
  text = Path(path).read_text()
352
  except OSError as exc:
353
- return None, f"Failed to read G-code file: {exc}"
354
 
355
  parsed = parse_gcode_path(text)
356
  if parsed["point_count"] == 0:
357
- return None, "No G0/G1 movement lines found in the file."
358
 
359
- figure = build_toolpath_figure(parsed)
360
  (x_min, y_min, z_min), (x_max, y_max, z_max) = parsed["bounds"]
361
  summary = (
362
  f"**{parsed['point_count']} moves parsed** — "
@@ -366,7 +368,17 @@ def render_toolpath(
366
  f"Y ∈ [{y_min:.2f}, {y_max:.2f}], "
367
  f"Z ∈ [{z_min:.2f}, {z_max:.2f}] mm."
368
  )
369
- return figure, summary
 
 
 
 
 
 
 
 
 
 
370
 
371
 
372
  def shift_slice(state: ViewerState, index: float, delta: int) -> tuple[int, str, Image.Image | None]:
@@ -669,8 +681,24 @@ def build_demo() -> gr.Blocks:
669
  interactive=False,
670
  )
671
  render_button = gr.Button("Render Tool Path", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
672
  toolpath_plot = gr.Plot(label="Tool Path")
673
  toolpath_status = gr.Markdown("")
 
674
 
675
  gcode_source.change(
676
  fn=toggle_gcode_source,
@@ -680,8 +708,20 @@ def build_demo() -> gr.Blocks:
680
  )
681
  render_button.click(
682
  fn=render_toolpath,
683
- inputs=[gcode_source, gcode_upload, gcode_file_1],
684
- outputs=[toolpath_plot, toolpath_status],
 
 
 
 
 
 
 
 
 
 
 
 
685
  )
686
 
687
  return demo
 
337
  source: str,
338
  uploaded_path: str | None,
339
  shape1_path: str | None,
340
+ travel_opacity: float = 0.55,
341
+ print_opacity: float = 1.0,
342
+ ) -> tuple[Any, str, dict]:
343
  if source == GCODE_SOURCE_UPLOAD:
344
  path = uploaded_path
345
  if not path:
346
+ return None, "No G-code file uploaded yet.", {}
347
  else:
348
  path = shape1_path
349
  if not path:
350
+ return None, "No Shape 1 G-code available yet. Generate it on the TIFF Slices to GCode tab first.", {}
351
 
352
  try:
353
  text = Path(path).read_text()
354
  except OSError as exc:
355
+ return None, f"Failed to read G-code file: {exc}", {}
356
 
357
  parsed = parse_gcode_path(text)
358
  if parsed["point_count"] == 0:
359
+ return None, "No G0/G1 movement lines found in the file.", {}
360
 
361
+ figure = build_toolpath_figure(parsed, travel_opacity=travel_opacity, print_opacity=print_opacity)
362
  (x_min, y_min, z_min), (x_max, y_max, z_max) = parsed["bounds"]
363
  summary = (
364
  f"**{parsed['point_count']} moves parsed** — "
 
368
  f"Y ∈ [{y_min:.2f}, {y_max:.2f}], "
369
  f"Z ∈ [{z_min:.2f}, {z_max:.2f}] mm."
370
  )
371
+ return figure, summary, parsed
372
+
373
+
374
+ def update_toolpath_opacity(
375
+ parsed: dict,
376
+ travel_opacity: float,
377
+ print_opacity: float,
378
+ ) -> Any:
379
+ if not parsed or not parsed.get("point_count"):
380
+ return None
381
+ return build_toolpath_figure(parsed, travel_opacity=travel_opacity, print_opacity=print_opacity)
382
 
383
 
384
  def shift_slice(state: ViewerState, index: float, delta: int) -> tuple[int, str, Image.Image | None]:
 
681
  interactive=False,
682
  )
683
  render_button = gr.Button("Render Tool Path", variant="primary")
684
+ with gr.Row():
685
+ travel_opacity_slider = gr.Slider(
686
+ label="Travel (G0) opacity",
687
+ minimum=0.0,
688
+ maximum=1.0,
689
+ value=0.55,
690
+ step=0.05,
691
+ )
692
+ print_opacity_slider = gr.Slider(
693
+ label="Print (G1) opacity",
694
+ minimum=0.0,
695
+ maximum=1.0,
696
+ value=1.0,
697
+ step=0.05,
698
+ )
699
  toolpath_plot = gr.Plot(label="Tool Path")
700
  toolpath_status = gr.Markdown("")
701
+ parsed_state = gr.State({})
702
 
703
  gcode_source.change(
704
  fn=toggle_gcode_source,
 
708
  )
709
  render_button.click(
710
  fn=render_toolpath,
711
+ inputs=[gcode_source, gcode_upload, gcode_file_1, travel_opacity_slider, print_opacity_slider],
712
+ outputs=[toolpath_plot, toolpath_status, parsed_state],
713
+ )
714
+ travel_opacity_slider.release(
715
+ fn=update_toolpath_opacity,
716
+ inputs=[parsed_state, travel_opacity_slider, print_opacity_slider],
717
+ outputs=[toolpath_plot],
718
+ queue=False,
719
+ )
720
+ print_opacity_slider.release(
721
+ fn=update_toolpath_opacity,
722
+ inputs=[parsed_state, travel_opacity_slider, print_opacity_slider],
723
+ outputs=[toolpath_plot],
724
+ queue=False,
725
  )
726
 
727
  return demo
gcode_viewer.py CHANGED
@@ -117,7 +117,11 @@ def _segments_to_xyz(
117
  return xs, ys, zs
118
 
119
 
120
- def build_toolpath_figure(parsed: dict) -> go.Figure:
 
 
 
 
121
  print_xs, print_ys, print_zs = _segments_to_xyz(parsed["print_segments"])
122
  travel_xs, travel_ys, travel_zs = _segments_to_xyz(parsed["travel_segments"])
123
 
@@ -131,7 +135,8 @@ def build_toolpath_figure(parsed: dict) -> go.Figure:
131
  z=travel_zs,
132
  mode="lines",
133
  name="Travel (G0)",
134
- line=dict(color="rgba(150,150,150,0.55)", width=2, dash="dot"),
 
135
  hoverinfo="skip",
136
  )
137
  )
@@ -144,6 +149,7 @@ def build_toolpath_figure(parsed: dict) -> go.Figure:
144
  z=print_zs,
145
  mode="lines",
146
  name="Print (G1)",
 
147
  line=dict(color="#1f77b4", width=4),
148
  hovertemplate="X=%{x:.2f}<br>Y=%{y:.2f}<br>Z=%{z:.2f}<extra></extra>",
149
  )
 
117
  return xs, ys, zs
118
 
119
 
120
+ def build_toolpath_figure(
121
+ parsed: dict,
122
+ travel_opacity: float = 0.55,
123
+ print_opacity: float = 1.0,
124
+ ) -> go.Figure:
125
  print_xs, print_ys, print_zs = _segments_to_xyz(parsed["print_segments"])
126
  travel_xs, travel_ys, travel_zs = _segments_to_xyz(parsed["travel_segments"])
127
 
 
135
  z=travel_zs,
136
  mode="lines",
137
  name="Travel (G0)",
138
+ opacity=travel_opacity,
139
+ line=dict(color="rgb(150,150,150)", width=2, dash="dot"),
140
  hoverinfo="skip",
141
  )
142
  )
 
149
  z=print_zs,
150
  mode="lines",
151
  name="Print (G1)",
152
+ opacity=print_opacity,
153
  line=dict(color="#1f77b4", width=4),
154
  hovertemplate="X=%{x:.2f}<br>Y=%{y:.2f}<br>Z=%{z:.2f}<extra></extra>",
155
  )