Pylon Injection V1 (WIP — libvgcode viewer integration in progress) - #6
Draft
jacobblitzer wants to merge 12 commits into
Draft
Pylon Injection V1 (WIP — libvgcode viewer integration in progress)#6jacobblitzer wants to merge 12 commits into
jacobblitzer wants to merge 12 commits into
Conversation
Adds the config surface for V1 of pylon injection. Per-region keys live on PrintRegionConfig so they can be overridden via a pylon ModelVolume's config. Global keys (filament selection, max nozzle descent) live on PrintConfig. No code reads these yet — wired up in subsequent commits. Defaults are chosen so the feature is a no-op until the user opts in: - pylon_enabled defaults false - pylon_max_descent_depth defaults 0 (safety: disables all injection) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ons() is_pylon() recognizes a ModelVolume as a pylon when it's NEGATIVE_VOLUME typed AND has pylon_enabled=true on its config — graceful degrade in older slicers (negative volumes carve as normal, injection step skipped). has_pylons() is the early-exit gate for the pylon pipeline steps so the cost is zero for prints with no pylons. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PrintObject::compute_pylon_footprints() walks (pylon volume × instance) pairs, approximates each as a vertical cylinder from its transformed AABB (radius = max(dx, dy) / 2, center XY = bbox center, Z extent = bbox Z), and stamps the resulting 32-segment polygon into every layer whose print_z is inside the Z extent — pre-intersected with Layer::lslices so the footprint is guaranteed to be inside the model. Called from PrintObject::infill() before the parallel make_fills loop so the cache is hot for Hook B subtraction in the next commit. Early-exits zero-cost when has_pylons() is false. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hook B from the recon. Inside Layer::make_fills, for each SurfaceFill, gate on internal-and-not-bridge-and-not-solid (i.e. sparse stInternal only, leaving stTop/stBottom/stInternalSolid/*Bridge alone so they cap and seal the pylon). Subtract the per-layer pylon footprint from surface_fill.expolygons before pattern instantiation; skip the pattern entirely if the void consumed the region. Top/bottom and solid surfaces are deliberately left unmodified so the existing shell logic produces the planar caps that contain the injected plug. Note: CLI slice-and-inspect verification skipped per branch's "do not run the slicer" constraint. Will be exercised by the Catch2 test in Task 10. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…descriptor CustomGCode::PylonInject is the new layer-boundary event type for pylon injection. Inserted before the Unknown sentinel to preserve string-keyed serialisation; added to the JSON read map. emit_custom_gcode_per_print_z gets a defensive early-return for PylonInject so its JSON payload is never written to G-code as text — the real emitter lands in Task 8. PylonInjection::Event is the serialised descriptor that rides inside CustomGCode::Item::extra. to_item / from_item are the round-trip helpers the scheduler (Task 6) and emitter (Task 8) will use. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lusion
Adds posSchedulePylonInjection step (between posContouring and
posSupportMaterial in the per-object pipeline). PrintObject::schedule
_pylon_injections() walks (pylon volume × instance) pairs, approximates
each as a vertical cylinder from its world AABB, runs three safety
gates (max-descent enabled, SUPPORT_ENFORCER overlap, floor below),
emits Z-spaced events using pylon_max_descent_depth as the step-aligned
event height with brick-bond 2-coloring stagger, snaps each event to
the nearest layer print_z, computes dE from cylinder volume ×
filament e_per_mm3, and writes batched CustomGCode::Items into
Model::plates_custom_gcodes[curr_plate_index].
Two deviations from the recon report (logged in summary):
1) Storage. Recon claimed Model::custom_gcode_per_print_z; actual
storage is the per-plate map plates_custom_gcodes (BBS multi-plate).
PrintBase gains a non-const model() accessor for this.
2) Per-layer multiplicity. assign_custom_gcodes consumes at most one
CustomGCode::Item per layer. Scheduler now batches all events at
the same snapped print_z into one Item; PylonInjection gains
to_item_batch / from_item_batch helpers.
V1 limitation logged at runtime: auto-generated overhang support is
warned about but not geometrically intersected against pylon footprints.
Only user-declared SUPPORT_ENFORCER volumes are checked.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ament change Adds LayerTools::pylon_filament(print_config, region) — resolves the global pylon_injection_filament; falls back to solid_infill_filament when unset, mirroring Jake's existing per-feature filament fork. Existing assign_custom_gcodes path is unmodified: PylonInject Items pass through the `pause_or_custom_gcode` branch (line 1561), get assigned to LayerTools::custom_gcode, and surface to the emitter. V1 limitation (documented): pylon-driven filament changes happen at the emitter without participation in wipe-tower partitioning. If pylon_injection_filament differs from the layer's active filament, expect an unpurged tool change at each pylon event. This avoids the deep ToolOrdering::fill_wipe_tower_partitions restructuring flagged in the spec; revisit if/when V2 wants clean wipe-tower interaction. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the defensive PylonInject early-return in emit_custom_gcode_per_print_z with the real synthesizer. For each event in the batched JSON payload: ;PYLON_INJECT_START id=… x=… y=… z_bottom=… z_top=… dE=… filament=… [optional set_extruder if event.filament_id differs from current] retract G1 X Y ; descent speed G1 Z<z_bottom> ; descent speed unretract G1 X Y Z<+step> E<dE_seg> ; extrude speed (looped to z_top) retract G4 P<dwell_ms> [optional set_extruder back to prior filament] ;PYLON_INJECT_END All moves go through GCodeWriter so its cached position, retract state, and feedrate stay coherent — the next normal extrusion picks up from a retracted, repositioned state and travels naturally. dE is distributed linearly across the ascent (dE * dz / total_dz per segment) so total dispensed equals the scheduler's pi*r^2*h volume. V1 limitation: tool change happens via set_extruder() without wipe- tower trip (consistent with Task 7's wipe-tower decision). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds an "Add Pylon (cylinder)" entry to the object's add-volume context menu. The handler delegates to ObjectList::load_generic_subobject to create a default cylinder primitive as a NEGATIVE_VOLUME, then sets pylon_enabled=true on the new volume's config so the slicer's schedule_pylon_injections() step picks it up. All pylon_* PrintRegionConfig keys surface automatically in the existing modifier-volume settings panel because region_config_from_model_volume() merges ModelVolume.config into the region's effective config. No new panel needed for V1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds tests/fff_print/test_pylon_injection.cpp with four scenarios:
1) Pylon volume + max_descent_depth > 0 → paired markers in output.
2) max_descent_depth == 0 → no markers (safe failure mode).
3) No pylon volume → no markers (early-exit gate).
4) Declared dE in each START marker matches pi*r^2*h * e_per_mm3
to within 1e-3 relative tolerance (validates scheduler arithmetic).
All test cases use the [.] tag so they're hidden by default (slicing
is expensive); run explicitly via "[PylonInjection]". Tests are
single-threaded and avoid Catch2 pitfalls per tests/CLAUDE.md
(WithinRel matcher, no Approx, no shared section names in loops).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User-facing guide for V1: setup workflow, config-key table, safety notes on pylon_max_descent_depth, brief "how it works" sketch with file pointers, G-code marker contract, V1 limitations, and 3MF backward-compat behaviour. Lives at repo root (no doc/ directory in this fork; matches the recon report's location). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…napshot, touchpoints doc Work-in-progress checkpoint of the pylon-injection feature. Not complete, in active development. Capturing current state before context switch. Highlights since last commit (dce4d13): - libvgcode: extend Types/Viewer/Settings/ViewerImpl for pylon injection event visualization in the G-code viewer - GUI: 3DScene, GCodeViewer, GUI_ObjectList, MainFrame, Tab wiring for pylon debug snapshot and viewer integration - PylonDebugSnapshot: new GUI component (522 lines) for visual debugging of pylon injection events - PrintObjectSlice, PrintApply, Model, ExtrusionEntity: plumbing updates - Recon, impl summary, and touchpoints docs added - AGENTS.md updated Builds clean on Windows Release (VS 2022). Tests not yet updated for new viewer/debug code. Known incomplete areas documented in pylon-injection-impl-summary.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pylon Injection — Work In Progress
Status: Active development. In flux. Not ready for review or merge.
What This Does
VoxelFill-style cylindrical pylon voids carved out of sparse infill and filled by periodic bottom-up extrusion events at layer boundaries. Creates reinforced structural columns embedded inside 3D prints.
V1 Scope (implemented)
WIP (this commit)
Safety
pylon_max_descent_depth = 0 (default) disables all injection — safe failure mode. Prevents nozzle crashes on unconfigured printers.
Build Status
Builds clean on Windows Release (VS 2022). CI not yet verified — this is the first push of this branch.
Draft PR to track work. Will mark ready for review when the libvgcode viewer integration and tests are complete.