Publicly published: May 6, 2026 — the date this document first became publicly accessible, in the repository at https://github.com/MGunlogson/magma (repository created 2026-05-06; this file present from its first commit). Prior-art effect runs from this date, because prior art dates from public accessibility rather than from authorship.
Authored and revised: drafted February 9, 2026; revised March 16, June 23, June 25, August 17 and August 25, 2026. These are authorship dates taken from the project’s own history. They are recorded for completeness and carry no independent evidentiary weight — where the two differ, the publication date above governs.
Note (August 25, 2026): The body of this disclosure is preserved as published. Parts of it have since been superseded — by test-print evidence, and by an audit of the text against the shipping source. See Addendum A for what changed and what still stands, and Addendum B for mechanisms the original text failed to disclose at all. Superseded material is deliberately not removed: a defensive publication records what was disclosed on a date, and editing it after the fact would defeat its purpose. Sections 7.c, 7.g and 8 are the most heavily superseded; read Addendum A before implementing from any of them.
Where to start. This is a long document with a specific job, and the order below is not the order most readers want:
Authors: Mark Gunlogson
Status: Public Domain Disclosure under CC0 1.0 Universal
This defensive publication discloses a complete software system for vertical reinforcement of Fused Deposition Modeling (FDM) 3D printed parts. The system, named Magma, modifies open-source slicer software (OrcaSlicer) to generate a user-selectable lattice infill pattern – triangular, rectilinear (square), tri-hex (hexagon + triangle), or honeycomb (regular hexagon) – containing hollow channels (tubes) that are filled with injected molten plastic during printing on a per-layer basis – not as a post-print operation. The injection occurs as a dedicated print stage within each layer’s processing, using the printer’s existing extruder at elevated temperature.
The system requires no hardware modifications to standard FDM printers. It is implemented entirely as software modifications to the slicer’s infill generation, G-code output, and preview rendering subsystems.
Key technical innovations disclosed herein include:
A triangular lattice coordinate system using (a, b, c) integer coordinates with weak plane avoidance via CP-SAT cumulative scheduling constraints, enabling tube boundary placement that prevents weak Z-planes.
A three-constraint spiral offset system that creates helical, interlocking tubes by applying a circular translation to the entire lattice per layer, with displacement bounded by line overlap, tube area overlap, and helix angle constraints.
A coupled thermal-pressure injection depth model (designed and tested, currently replaced by user-configured tube height – see Section 10.e) where the volumetric injection speed variable drops out of the simultaneous equations, yielding an optimal tube height that self-adjusts to balance thermal freezing and extruder pressure limits.
A dual-identity lattice architecture where cell identity (for stable tube pairing across layers) uses a fixed reference lattice, while per-layer geometry checks (for boundary detection and rendering) use a spiral-offset lattice.
A two-stage tube assignment solver combining a greedy most-constrained-first heuristic (100-500ms) with optional CP-SAT constraint programming refinement, using integer micron arithmetic, discrete layer-boundary domains, spatial block partitioning, and cumulative scheduling constraints for weak plane avoidance.
A G-code comment protocol (MAGMA_TUBE) for embedding 3D tube visualization waypoints that enables preview rendering of filled tubes without modifying the G-code motion command structure.
A dual-zone architecture (“egg model”) using repurposed SLA hollowing algorithms for FDM inner shell boundary generation, with constrained mean curvature flow smoothing that prevents expansion into the shell zone.
A 5-tier safe park positioning system that finds optimal nozzle positions during injection temperature changes by classifying print surface regions (empty > support > sparse infill > solid infill > z-hop only).
An automatic, per-tube Z-slam sealing-depth model derived from nozzle cone geometry, in which each tube’s press-down depth is computed from that tube’s ACTUAL opening at its cap layer (the farthest point of the clipped opening from the injection point), the nozzle tip flat diameter, and the nozzle cone half-angle as depth = max(epsilon, (opening + margin - flat) / (2 * tan(half_angle))), so the widening cone above the tip flat reaches each individual opening’s width and seals it without manual tuning. Because the depth is derived per tube from the real (possibly boundary-clipped) opening rather than a single global ideal, smaller boundary openings receive a correspondingly shallower, non-over-pressed slam.
A global, per-print-layer thermal-aware injection ordering that, across all objects and instances on a layer, separates spatially-near injections in time to prevent combined heat from re-melting neighbouring cells. It is driven by a continuous decay field in which every prior injection is a heat source fading in both time and space (exp(-dt/tau) * exp(-dist/lambda)), built by a dispersion greedy that injects wherever is currently coolest-on-arrival and refined by a violation-directed local search; because dt is real elapsed injection time, inter-injection travel counts as cooling rather than opposing the spread. The solved order is cached in a dedicated slicing stage. (An equivalent exact CP-SAT routing formulation of the same objective was also implemented, measured, and is disclosed in Section 7.h as an alternative.)
A progressive-plunge (“slam-melt”) injection in which the sealing nozzle is ramped deeper into the tube top during extrusion, from the geometric seal depth to that depth plus a configured plunge, so the hot tip continuously sinks into the softening surface and maintains the seal under the rising channel pressure – driving plastic down the tube instead of letting it escape laterally around the nozzle – while the extrusion holds its commanded volumetric rate.
A neighbour-aware crater-ironing finishing move that, after each injection, spirals the nozzle inward over the injection point so the angled nozzle cone plows the displaced rim back into the crater (deflecting material both inward and downward by the cone-normal geometry) and irons it flat while scraping the nozzle clean; the nozzle hovers above layer height over neighbouring cells and only descends to press inside a geometrically-derived radius that keeps the flat clear of any neighbouring tube opening’s far vertex, guaranteeing a neighbour’s air-escape hole is never sealed.
A shape-generic lattice and geometry abstraction in which the tube grid, neighbour pairing, window placement, opening size, cell-area/volume, and injection geometry are all expressed through a per-shape strategy interface, so multiple infill patterns – triangular (equilateral cells), rectilinear (square cells), tri-hex (hexagon + triangle cells), and honeycomb (regular hexagon cells) – share a single tube-assignment solver, injection pipeline, and preview-rendering pipeline. Tri-hex additionally uses vent-based injection allocation (a single injection serving multiple connected vents) rather than only pairwise U-tube coupling. Any pattern may also serve as the outer-zone fill in the dual-zone architecture.
A dual cell-presence gate that admits a cell as a tube cell on a given layer only when BOTH (a) its clipped interior area is at least a fixed fraction (70%) of the ideal cell area AND (b) the injection point retains at least the nozzle-flat radius of clearance to the nearest opening boundary. The area test bounds how much of the cross-section survives clipping; the clearance test – evaluated at the actual injection point – rejects shapes where a spike or pinch intrudes toward the centre (which the area test alone would pass), guaranteeing the nozzle flat can seat. This unified per-layer gate supersedes a separate constriction-detection pass, and because injection volume is computed from each layer’s actual clipped area, admitted partial cells are dosed proportionally.
A clipped-cavity centroid injection point, in which the nozzle aims not at the ideal lattice cell centre but at the centroid of the cell’s actual (boundary-clipped) opening at the cap layer. For a regular polygon the centroid coincides with the inscribed-circle centre, so boundary-clipped cells inject at the point of greatest clearance from the part wall instead of at a centre that may sit near or past the clip – maximizing seal reliability – and it falls back to the lattice centre if a concave clip places the centroid outside the opening.
A one-to-many (“manifold”) injection unit and its vent-fill allocation, in which a single injection fills a hub cell plus multiple equal-length vent legs – windows pinned to the hub-tube’s bottom so every leg spans the hub-tube’s layer range – and a per-vent allocation maximizes filled volume by: (a) forming an unavailable-layer mask per vent = layers absent due to part geometry UNION layers already committed to other injections; (b) discarding any candidate hub-tube whose layer range crosses that mask (which would trap injected air); and (c) within each remaining present-run, selecting by weighted interval scheduling over the contained hub-tube ranges the non-overlapping set of tubes that fills the most layers, tie-broken toward the least-loaded hub. Each vent layer is filled exactly once and hubs are uncapped, so the allocation is independent per vent and yields the maximal fill achievable with windows aligned to real tube boundaries. The pairwise U-tube is the degenerate single-leg case.
A fourth reinforcement-cell tiling – Magma Honeycomb – a regular pointy-top hexagonal lattice (joining the triangular, rectilinear/square, and tri-hexagonal tilings on the shared shape-generic pipeline of claim 13) whose cell size is driven by the injection tube interior width (nozzle-derived), not by infill density. Its novel embodiment reuses a single continuous honeycomb sweep – one vertical zigzag per lane-pair, phased to the lattice – so the pattern prints fast; that sweep inherently traces every vertical cell wall DOUBLED (each vertical lane is swept by both adjacent lane-pairs) while the slanted walls stay single. To keep the open injectable tube a true regular hexagon despite the asymmetric wall thickness, the lattice is pre-expanded anisotropically – horizontal X pitch interior_width + 2*lw, top/bottom vertex height e + lw/sqrt(3), and row pitch 1.5*e + lw/sqrt(3) (with interior_width the requested open flat-to-flat, e = interior_width/sqrt(3) the OPEN hex edge, s = interior_width + line_width the centre-to-centre spacing, and lw the line width; note both e and the X pitch are derived from the interior width rather than from s, since deriving them from s leaves the open hexagon one line width too wide) – so that after the doubled verticals (each intruding lw) and single slants (each intruding lw/2) eat into the cell, the remaining open cross-section is a regular hexagon of edge e. U-tube pairing and shared-wall windows apply exactly as in the other patterns (6 edge-sharing neighbours, 2 cells per pair, no vents).
Measured injection-volume determination from the deposited toolpath, in which each U-tube’s injectable cavity volume is not estimated from closed-form cell geometry but MEASURED from the actually generated infill after the toolpath exists. For each layer of a pair’s run the injectable void = (the union of the pair’s cell polygons, intersected with the reinforcement zone) MINUS the footprint of the deposited walls (the polygons covered by the extrusion width), summed times layer height over the run. A single geometric measurement thereby captures – directly from the deposited footprint, with no per-pattern correction terms – side-by-side doubled walls (such as the honeycomb pattern’s doubled verticals), the window gap, and part-edge clipping. The one residual the union footprint cannot see – the extra material where lines CROSS and stack, which polygons_covered_by_width merges into a single union – is removed by the always-applied, self-scaling correction of claim 19. The measured cavity then drives the injected-plastic dose.
A single, self-scaling overlap correction that is ALWAYS applied to the measured injection volume of claim 18, sized to the ACTUAL deposited line width, so the line-crossing over-extrusion is corrected exactly once and never double-counted regardless of how the lines were printed. The system subtracts the over-extruded crossing material from the measured cavity, apportioned per cell from each shape’s vertex geometry evaluated at the effective (deposited) line width lw_eff (triangle (3*sqrt(3)/4)*lw_eff^2 per vertex, square lw_eff^2, tri-hex (2/sqrt(3))*lw_eff^2 charged to incident cells by corner count, honeycomb 0 – its degree-3 junctions are line ends, not crossings). The separate magma_overlap_line_correction setting (default off) is a print-quality lever, NOT a volume gate: it controls only how the lines PRINT, not whether the volume is corrected. When on, it reduces infill flow so the deposited lines print thinner (floored near 90% of nozzle width, magma_overlap_min_width, to avoid sub-nozzle-width lines), which makes lw_eff smaller so only the small RESIDUAL crossing overlap of the thinned lines is subtracted; when off (default), the lines print full width and the full overlap is subtracted. Because the subtraction always uses the width actually deposited – and because the deposited-footprint measurement (claim 18) merges crossing beads into one union, so the second crossing bead’s bulge into the void is never captured there – the overlap is compensated exactly once whatever the setting. (Implementation status: the magma_overlap_line_correction lever was subsequently removed from the shipping slicer for not being useful enough to carry — lines now always print full width and the full overlap is always subtracted. The code remains in git history; this claim is retained as prior art. See the note in Section 4.h.)
All algorithms, code, and structures described in this document are dedicated to the public domain to establish prior art and prevent patenting by third parties.
This section is contextual. It makes no new disclosure claim and does not alter the priority dates recorded in the Prior Art Declaration below.
Filling internal cavities with molten material during printing, to bridge layer interfaces, is not new. The relevant prior work, and how Magma relates to it:
ORNL Z-pinning — Duty, Failla, Kim, Smith, Lindahl, Kunc, “Z-Pinning approach for 3D printing mechanically isotropic materials”, Additive Manufacturing vol. 27 (2019), doi:10.1016/j.addma.2019.03.007; earlier work presented at the 2018 International Solid Freeform Fabrication Symposium. (An earlier revision of this section merged the two papers’ author lists into one citation.) Voids are intentionally aligned across n layers and back-filled continuously during deposition of layer n+1. Reported >3.5x increase in Z-direction tensile strength and toughness for PLA and CF-PLA, with strength rising as pin fill volume increased from 0% to 120%. The paper also reports the limiting failure: molten PLA failed to fully fill the holes, introducing excessive porosity. This is the closest published antecedent to the core concept and predates the AIM3D priority date below.
AIM3D Voxelfill – EP 4100235 B1 (priority DE 10 2021 106 037.0, 2021-03-12; granted 2023-08-09; family US 2024/0165874, CA 3213385; divisional EP 4238741 A1 pending). Claims a method in which a first work step produces an outer contour bounding a volume region containing at least one open volume chamber, and a following second work step at least partially fills that chamber with filler material. Commercialized through Create it REAL in REALvision Pro. The distinguishing feature in AIM3D’s published descriptions is a half-height offset of volume elements between successive layers, producing a brick-bond arrangement that displaces the yield plane. Reported results include up to 81% of XY tensile strength along Z on PETG-GF30. Note that the granted claim’s cited references do not include the ORNL work above.
US 12,539,664 B2 — “Thermoset injection into fused filament fabrication parts with discontinuous and/or continuous reinforcement”, assignee Markforged Inc, filed 2024-04-24, granted 2026-02-03. Claims pausing an FFF print, optionally inserting Z-direction reinforcement, and injecting thermoset or thermoplastic resin through designed inlet and outlet ports to fill internal infill patterns, for Z-strength and reduced warping.
Correction (August 25, 2026): an earlier revision of this section described this patent as covering “post-process infiltration” of “thermoset rather than nozzle-extruded thermoplastic”, and distinguished Magma on those two grounds. Both grounds were wrong: the patent covers thermoplastic resin as well as thermoset, and it injects during a pause in printing rather than after the print completes. This is a closer antecedent than the earlier text allowed, and it granted before this disclosure was published.
What differs mechanically, stated without any claim about legal scope: Magma injects with the printer’s existing extrusion nozzle, sealing the nozzle’s own tip geometry directly against the mouth of a printed channel, using the same thermoplastic the part is printed from and no separate resin system, ports, or added reinforcement. The sealing-by-nozzle-geometry mechanism and the channel-sizing that follows from it (Sections 7.c and 7.g as corrected by Addendum A, and the gates in Addendum B.1) are the substance of what is disclosed here. Whether that distinction has legal significance is a question for counsel, not for this document.
JanTec Engineering – published hobbyist experiments injecting molten plastic into infill channels with a hot end. Three practical findings are directly relevant: (a) molten plastic cools on leaving the nozzle and will not travel far down a deep hole, so cavities must be filled periodically rather than in one shot; (b) bottom-up filling substantially outperforms top-down, achieved by modifying the hot end with an airbrush nozzle for roughly 4mm of additional reach; (c) higher injection temperatures fill cavities more completely but the carried heat risks deforming the surrounding print.
OrcaSlicer discussion #4815 and related community threads – multi-year community discussion of G-code-level Z-pinning and 3D injection, without a working slicer implementation.
The core concept – printing internal cavities and filling them with nozzle-extruded molten thermoplastic mid-print to reinforce the Z axis – is common to ORNL, AIM3D, and Magma. No novelty is claimed for it here.
Each of JanTec’s three published constraints is answered in software and geometry rather than with modified hardware, which is what makes the system implementable in a slicer on a stock printer:
| Published constraint | Magma’s answer |
|---|---|
| Plastic will not travel far down a deep hole | Low-aspect-ratio channels – roughly 1:1 depth-to-width, ~3mm – sized from nozzle geometry rather than infill density. The travel distance is shortened instead of the nozzle being lengthened. |
| Bottom-up filling beats top-down, but requires a modified hot end | The U-tube pair (Section 2.3): injection into one cell flows down, through a shared-wall window at the base, and rises up the paired cell, with air escaping the partner’s open top. Fill-from-below is obtained from lattice topology, with no hardware change. The manifold generalization (claim 16) extends this to one hub plus N vent legs. |
| High injection temperature fills better but carried heat deforms the part | Heat-spread injection ordering (claim 10, Section 7.h): a global per-layer schedule over a continuous thermal decay field exp(-dt/tau) * exp(-dist/lambda), separating spatially-near injections in time, with real elapsed injection time as the temporal axis so inter-injection travel counts as cooling. |
Beyond these, the contributions for which prior art is established in the sections below are principally: the constrained-optimization formulation of tube placement (claims 1, 5; Sections 5.a-5.i), in which weak-plane avoidance is expressed as a soft cumulative capacity penalty subtracted from the objective rather than as a fixed geometric offset – so boundary spread adapts to real part geometry, presence runs, and height bounds instead of following a uniform brick-bond; the designated vent for air escape, which directly targets the porosity failure ORNL reported; the shape-generic multi-pattern lattice abstraction (claim 13); and the per-tube sealing, plunge, and crater-ironing models (claims 9, 11, 12).
Periodic fill is counterproductive with an unmodified nozzle. JanTec’s recommendation to fill a cavity in several doses over time was tested and rejected. With a stock nozzle, deposition is necessarily top-down: the first dose solidifies at the channel entry rather than at the base, forming a plug that subsequent injections cannot pass. Periodic filling and the extended-reach nozzle are not independent techniques – the former depends on the latter. Without the hardware modification, the correct approach inverts to a single injection per tube at elevated temperature and flow rate, with thermal load managed across the layer by injection ordering rather than within a tube by dose splitting.
The seal, not the flow, is the binding constraint at same-material. With the geometry and scheduling above resolving reach and thermal load, the remaining failure mode is melting of the tube-top rim during injection: the injectate and the cell wall are the same polymer, and the elevated temperature required for flow is the same temperature that softens the seal. Sections 7.c and 7.d (per-tube Z-slam with progressive plunge, and neighbour-aware crater ironing) mitigate but do not eliminate this. It is a materials constraint rather than a geometric or scheduling one, and the indicated resolution is a dissimilar-material pairing – a high-HDT shell (CF-Nylon, PC) with a lower-melt injectate – for which the multi-material path is implemented (claim in Section 7.e) but which the author has not been able to test for lack of dual-extruder hardware.
Hollow channels formed within the selected Magma lattice infill pattern. Each tube is defined by a single lattice cell’s interior space, bounded by the infill line walls and by the layers above and below. The interior cross-section depends on the chosen pattern – an equilateral triangle (Magma Triangle), a square (Magma Rectilinear), a hexagon or triangle (Magma Tri-hex), or a regular hexagon (Magma Honeycomb) – sized by the cell’s interior width (auto-calculated from nozzle geometry, or user-specified). Tubes span multiple layers vertically and are filled with injected plastic during printing.
Gaps intentionally left in the shared infill walls between two adjacent cells. A window is created by omitting a segment of the infill line that forms the shared edge between two cells, for a specified number of layers (the window height). Windows connect paired tubes to form U-tube pairs, allowing injected plastic to flow from one cell down through the window into the adjacent cell.
Two adjacent cells connected by a window at their shared edge. Plastic is injected into one cell (cell_a, the injection side) at the top of the tube, flows down through the tube, crosses through the window into the adjacent cell (cell_b, the vent side), and rises up. The resulting solidified plastic forms a U-shaped interlocking reinforcement column. Each U-tube pair has a defined start layer (bottom), end layer (top/cap), and injection volume.
Vertical offsets applied to tube boundary positions across different cells to prevent all boundaries from aligning at the same Z-height, which would create a weak horizontal plane. In the current implementation, stagger is achieved via the CP-SAT solver’s cumulative scheduling constraints for weak plane avoidance (Section 5.d), rather than algebraic coloring. The solver penalizes boundary clustering within each cell’s Ring-0 + Ring-1 neighborhood, producing a natural spread of tube boundaries across Z levels.
A coordinate system for identifying triangular cells using three integer coordinates. The triangular grid uses three axes at 60-degree angles. Cells are classified by the sum of their coordinates:
a + b + c == 2a + b + c == 1Each cell has exactly three neighbors, obtained by incrementing (for down triangles) or decrementing (for up triangles) one coordinate by 1. The coordinate system enables efficient neighbor lookup, deterministic stagger calculation, and consistent cell identification across layers.
The print volume is divided into concentric zones:
Three new surface types support this architecture: stZoneOuter (outer zone infill), stZoneFloor (inner shell floor – solid layer where zone begins), and stZoneCeiling (inner shell ceiling – solid layer where zone ends).
Implementation status: IMPLEMENTED and tested in software. All code excerpts are from the working implementation.
The triangular lattice uses (a, b, c) integer coordinates where up triangles have a + b + c == 2 and down triangles have a + b + c == 1. This coordinate system supports O(1) neighbor lookup, O(1) stagger level computation, and O(1) cell classification.
// src/libslic3r/Magma/MagmaTriangleCell.hpp
struct TriangleCell {
int a, b, c; // Triangle coordinates
TriangleCell() : a(0), b(0), c(0) {}
TriangleCell(int a_, int b_, int c_) : a(a_), b(b_), c(c_) {}
// Check if this is an upward-pointing triangle (△)
bool is_up() const { return (a + b + c) == 2; }
bool operator==(const TriangleCell& other) const {
return a == other.a && b == other.b && c == other.c;
}
bool operator<(const TriangleCell& o) const {
if (a != o.a) return a < o.a;
if (b != o.b) return b < o.b;
return c < o.c;
}
// Adjacent cells sharing an edge.
// Up triangle neighbors: decrement one coordinate by 1 → down triangles (sum=1).
// Down triangle neighbors: increment one coordinate by 1 → up triangles (sum=2).
std::array<TriangleCell, 3> neighbors() const {
if (is_up())
return {{ {a-1,b,c}, {a,b-1,c}, {a,b,c-1} }};
else
return {{ {a+1,b,c}, {a,b+1,c}, {a,b,c+1} }};
}
};
// Hash functor for TriangleCell, suitable for use in unordered containers.
struct TriangleCellHash {
size_t operator()(const TriangleCell &c) const {
size_t h = std::hash<int>()(c.a);
h ^= std::hash<int>()(c.b) + 0x9e3779b9 + (h << 6) + (h >> 2);
h ^= std::hash<int>()(c.c) + 0x9e3779b9 + (h << 6) + (h >> 2);
return h;
}
};
The lattice maps (a, b, c) coordinates to world (x, y) positions via a skewed coordinate system:
// src/libslic3r/Magma/MagmaTriangleCell.hpp
class TriangleLattice {
public:
explicit TriangleLattice(double cell_spacing, double offset_x = 0.0, double offset_y = 0.0)
: m_cell_spacing(cell_spacing)
, m_edge_length(triangle_side_length(cell_spacing))
, m_offset_x(offset_x)
, m_offset_y(offset_y)
{}
// Convert lattice coordinates to world coordinates
Vec2d to_world(double lx, double ly) const {
return Vec2d(
lx * m_edge_length + ly * m_edge_length * 0.5 + m_offset_x,
ly * m_cell_spacing + m_offset_y
);
}
// Convert world coordinates to lattice coordinates
std::pair<double, double> to_lattice(double px, double py) const {
double adjusted_x = px - m_offset_x;
double adjusted_y = py - m_offset_y;
double ly = adjusted_y / m_cell_spacing;
double lx = (adjusted_x - ly * m_edge_length * 0.5) / m_edge_length;
return {lx, ly};
}
// Get the triangle cell containing a world point
TriangleCell cell_at(double px, double py) const {
auto [lx, ly] = to_lattice(px, py);
int col = static_cast<int>(std::floor(lx));
int row = static_cast<int>(std::floor(ly));
double fx = lx - col;
double fy = ly - row;
// fx + fy < 1 means UP triangle, >= 1 means DOWN triangle
bool is_up = (fx + fy) < 1.0;
int c = is_up ? (2 - col - row) : (1 - col - row);
return TriangleCell(col, row, c);
}
private:
double m_cell_spacing;
double m_edge_length;
double m_offset_x;
double m_offset_y;
};
The cell spacing is derived from the physical geometry: cell_spacing = interior_width + line_width, representing the center-to-center distance between parallel infill lines. The triangle side length is cell_spacing * 2 / sqrt(3).
Note: The algebraic stagger coloring described below was the original design approach for weak plane avoidance. The mathematical property is correct, but the implementation now uses CP-SAT cumulative scheduling constraints (Section 5.d) instead, which provide more flexible stagger that adapts to variable tube heights and boundary conditions.
The stagger level formula (a - b) % n produces a perfect 3-coloring of the triangular lattice. This is a mathematical property of the coordinate system: for any cell with neighbors obtained by incrementing or decrementing exactly one of (a, b, c), the (a - b) value changes by exactly +1 or -1, guaranteeing that all three neighbors of any cell have distinct (a - b) mod 3 values. This eliminates the need for graph coloring algorithms – the coloring is computed in O(1) per cell from coordinates alone.
For num_levels >= 3, the stagger pattern ensures that no two adjacent cells have windows at the same Z-height, preventing horizontal weak planes. The formula generalizes to any number of stagger levels, though 3 is optimal (the chromatic number of the triangular lattice dual graph).
The spiral offset system translates the entire triangular lattice in a circular path per layer, creating helical tubes that interlock with adjacent tubes spiraling in the opposite rotational direction. The per-layer displacement is bounded by three independent constraints:
// src/libslic3r/Magma/MagmaSpiralOffset.cpp
SpiralParams compute_spiral_params(float interior_width, float line_width,
float layer_height, bool enabled)
{
SpiralParams params;
params.enabled = enabled;
if (!enabled) {
params.spiral_radius = 0.f;
params.angle_per_layer = 0.f;
return params;
}
// Constraint 1: Printability - 40% line overlap between layers
constexpr float target_line_overlap = 0.40f;
const float max_disp_line = (1.0f - target_line_overlap) * line_width;
// Constraint 2: Tube continuity - 75% tube area overlap between layers
constexpr float target_tube_overlap = 0.75f;
const float max_disp_tube = (1.0f - target_tube_overlap) * interior_width;
// Constraint 3: Maximum helix angle for injection flow.
// Cap so helix angle never exceeds ~27 degrees (tan(27) = 0.5).
constexpr float MAX_HELIX_TAN = 0.5f;
const float max_disp_helix = MAX_HELIX_TAN * layer_height;
// Use the most restrictive constraint
const float max_displacement = std::min({max_disp_line, max_disp_tube, max_disp_helix});
// Interlock: swept circles of adjacent tubes should touch
const float cell_spacing = static_cast<float>(
cell_spacing_from_geometry(interior_width, line_width));
params.spiral_radius = cell_spacing / 2.0f;
// Per-layer angle from radius and displacement
params.angle_per_layer = max_displacement / params.spiral_radius;
return params;
}
Vec2d compute_spiral_offset(const SpiralParams ¶ms, int layer_id)
{
if (!params.enabled)
return Vec2d(0.0, 0.0);
const float layer_angle = float(layer_id) * params.angle_per_layer;
return Vec2d(
params.spiral_radius * std::cos(layer_angle),
params.spiral_radius * std::sin(layer_angle)
);
}
The circular offset creates helical tubes: as the lattice translates in a circle, each cell’s center traces a helix through 3D space. Adjacent cells spiral in opposite rotational directions because they are on opposite sides of the shared lattice lines. This produces mechanical interlock between adjacent tube pairs, significantly increasing the shear strength of the reinforcement structure.
The three constraints ensure: (1) infill lines maintain 40% overlap between layers for reliable adhesion during printing, (2) tube cross-sections maintain 75% area overlap to preserve continuous channels for injection, and (3) the helix angle stays below 27 degrees to allow injected plastic to flow through the channel without excessive resistance.
A critical architectural decision separates cell identity from cell position. Cell identity (which cell a given (a,b,c) coordinate refers to) must be stable across all layers for tube pairing to work correctly – the same (a,b,c) cell on layer 5 must be the same tube as (a,b,c) on layer 50. However, the physical position of that cell shifts per layer due to spiral offset.
// src/libslic3r/Magma/MagmaTubeMap.cpp — scan_layers()
// FIXED reference lattice for cell IDENTITY (a,b,c coordinates).
// Cell identity must be stable across layers for tube pairing to work.
TriangleLattice ref_lattice(m_cell_spacing, 0.0, 0.0);
for (int i = 0; i < int(layers.size()); ++i) {
const Layer *layer = layers[i];
const int layer_id = static_cast<int>(layer->id());
// Spiral-offset lattice for this layer's actual cell positions.
// Pre-built per layer during build() and cached in m_layer_data[layer_id].lattice
// (eliminates repeated sin/cos + TriangleLattice construction).
const TriangleLattice &layer_lattice = m_layer_data[layer_id].lattice;
// ... enumerate cells using ref_lattice for identity,
// but use layer_lattice for position/containment checks ...
}
Lattices are pre-built per layer during build() and cached in m_layer_data[layer_id].lattice, eliminating repeated sin/cos computation and TriangleLattice construction during scan_layers().
The reference lattice (zero offset) is used to enumerate cells and assign (a,b,c) coordinates. The layer lattice (with spiral offset) is used for geometric checks: is the cell center inside the model boundary? What is the cell’s area after clipping to the model? This dual-lattice approach ensures that tube assignments are stable while geometric computations reflect the actual per-layer positions.
Historical note: the standalone two-tier constriction-detection pass below has been superseded by the dual cell-presence gate (Section 1, claim 14, and Section 3.f). A cell now counts as present on a layer only if its clipped area is at least 70% of the ideal cell area AND the injection point keeps at least the nozzle-flat radius of clearance to the nearest opening boundary. Because that per-layer gate already excludes any under-area or pinched layer from a cell’s presence, no separate constriction pass is run. The original algorithm is retained here for prior art.
Constriction detection identifies layers where a cell’s usable area drops sharply, indicating a geometric pinch point (e.g., where a model narrows) that would block injection flow. A tube should not bridge across such a constriction.
// src/libslic3r/Magma/MagmaTubeMap.cpp — detect_constrictions()
void MagmaTubeMap::detect_constrictions()
{
int constrictions_found = 0;
for (auto &[cell, presence] : m_cells) {
if (presence.first_layer == presence.last_layer)
continue;
for (int i = presence.first_layer; i < presence.last_layer; ++i) {
if (!presence.present(i) || !presence.present(i + 1))
continue;
double area_i = presence.area(i);
double area_ip1 = presence.area(i + 1);
if (area_i <= 0.0 || area_ip1 <= 0.0)
continue;
// Tier 1: Area ratio heuristic (fast)
double ratio = std::min(area_i, area_ip1) / std::max(area_i, area_ip1);
if (ratio > 0.7)
continue; // Healthy overlap, skip expensive check
// Tier 2: Severe constriction splits the cell
if (ratio < 0.3) {
int idx = i + 1 - presence.first_layer;
if (idx > 0 && idx < int(presence.layers.size())) {
presence.layers[idx] = false;
presence.areas[idx] = 0.0;
++constrictions_found;
}
}
}
}
}
Tier 1 is a fast area-ratio heuristic: if consecutive layers have area ratio > 0.7, the cell is healthy and no further check is needed. Tier 2 applies a stricter threshold (ratio < 0.3) to split the cell’s presence, preventing tubes from bridging across near-discontinuities. This two-tier approach avoids the cost of full polygon overlap computation for the majority of cells that pass the fast check.
For cells near the model boundary, the system uses a fast/slow dual-path approach:
// src/libslic3r/Magma/MagmaTubeMap.cpp — scan_layers()
// Interior inset: if cell center is this far inside the zone region,
// the tube inscribed circle fits entirely.
const coord_t interior_inset = scale_(m_interior_width * 0.5);
ExPolygons interior_region = offset_ex(zone_regions, -interior_inset);
for (const TriangleCell &cell : cells) {
Vec2d center_mm = layer_lattice.cell_center(cell);
Point center_pt(scale_(center_mm.x()), scale_(center_mm.y()));
// Fast path: center inside tube-clearance inset -> fully unobstructed
bool is_interior = false;
for (const ExPolygon &ep : interior_region) {
if (ep.contains(center_pt)) {
is_interior = true;
break;
}
}
if (is_interior) {
m_cells[cell].mark_present(layer_id, inset_area_scaled2);
continue;
}
// Slow path: boundary cell, compute actual clipped area
std::array<Vec2d, 3> corners = layer_lattice.cell_corners(cell);
Polygon triangle;
// ... build triangle polygon from corners ...
ExPolygons inset = offset_ex(triangle, -scale_(half_line_width));
ExPolygons clipped = intersection_ex(inset, zone_regions);
double area = 0.0;
for (const ExPolygon &ep : clipped)
area += std::abs(ep.area());
if (area < min_area_scaled2)
continue; // Too constricted for injection flow
m_cells[cell].mark_present(layer_id, area);
}
Interior cells (center inside the inset region by half the interior width) use the precomputed ideal cell area, avoiding polygon clipping entirely. Boundary cells undergo exact polygon intersection to determine their actual usable area. A cell is admitted on a layer only if that area is at least 70% of the ideal cell area AND the injection point retains at least the nozzle-flat radius of clearance to the nearest opening boundary (the dual presence gate of claim 14): the area term rejects cells too clipped to hold a useful tube, while the clearance term rejects spikes or pinches intruding toward the injection point that the area term alone would pass. Injection volume is then computed from each layer’s actual clipped area, so an admitted partial cell is dosed proportionally.
The system uses millimeter-based tube boundaries rather than fixed layer counts, enabling correct operation with variable layer heights (adaptive slicing). Per-layer heights are stored from the Layer objects (in m_layer_data indexed by layer ID, containing print_z, height, and the pre-built lattice for that layer), and all height comparisons operate in millimeters rather than layer counts. A helper function span_height_mm() computes the physical height of any layer range using these tables.
Historical note: The assign_default_tubes() function originally performed mm-based boundary placement using fmod alignment and per-layer height accumulation. This function was replaced by the two-stage solver (Section 5), which uses integer micron arithmetic for boundary placement. The mm-based boundary concept is preserved in the solver’s MicronTables (Section 5.a), but the implementation path changed.
Tube boundaries are placed at mm-based grid lines, with boundary crossings detected via accumulated layer heights:
// src/libslic3r/Magma/MagmaTubeMap.cpp — (historical: assign_default_tubes)
// How far into the current tube_h_mm period is span_bottom_z?
double into_period = std::fmod(span_bottom_z - stagger_offset_mm, tube_h_mm);
if (into_period < 0) into_period += tube_h_mm;
double first_target_mm = tube_h_mm - into_period;
if (first_target_mm < 1e-6) first_target_mm += tube_h_mm;
// Walk layers accumulating height to find boundary crossings
double accum = 0.0;
double target = first_target_mm;
for (int i = span.start; i <= span.end; ++i) {
accum += m_layer_heights[i];
if (accum >= target - 1e-6 && i < span.end) {
boundaries.push_back(i + 1);
target += tube_h_mm;
}
}
Magma Honeycomb is a fourth selectable reinforcement-cell tiling alongside Magma Triangle, Magma Rectilinear, and Magma Tri-hex. It is a regular pointy-top hexagonal (honeycomb) tiling: every cell is a hexagon with a vertical left and right edge and four slanted edges, bordering six edge-sharing neighbours. Unlike Tri-hex there are no triangular vents – two adjacent hexagons pair into an ordinary two-cell U-tube (window cut in their shared edge), exactly as triangle and rectilinear cells do. The cell size is driven by the injection tube interior width (auto-derived from nozzle geometry, or user-specified), not by an infill-density percentage: the center-to-center spacing is s = interior_width + line_width, and the open hexagon edge is e = interior_width / sqrt(3) – derived from the interior width, not from s, so that the printed open tube’s flat-to-flat is exactly interior_width (deriving e from s leaves the open hexagon one line width too wide).
Because a hexagon is the Tri-hex hub shape, the per-shape geometry strategy reuses the hub formulas (open area, seal opening, inscribed radius, auto-sizing). The differences from Tri-hex are only the hub-vs-vent specifics: the neighbour distance is hexagon-to-hexagon (one full spacing), the window feeds the paired hexagon rather than a vent, and the wall junction is the degree-3 honeycomb vertex (three walls meeting at 120 degrees, i.e. line ends, not a line crossing).
// src/libslic3r/Magma/MagmaHexCell.hpp — HexagonGeometry
// Open hexagon area. Open apothem a' = s/2 - lw/2 = (s - lw)/2 = interior/2.
// Regular hexagon area from apothem a: 2*sqrt3*a^2.
double inset_open_area(double spacing, double line_width) const override {
double a = (spacing - line_width) * 0.5; // open apothem
return a > 0.0 ? 2.0 * SQRT3 * a * a : 0.0;
}
// Seal opening = circumscribed circle of the open hexagon = 2*open circumradius,
// open circumradius = open_apothem / (sqrt3/2) = (s-lw)/sqrt3.
double opening_diameter(double spacing, double line_width) const override {
double s = spacing - line_width;
return s > 0.0 ? 2.0 * s * INV_SQRT3 : 0.0;
}
// Inverse of opening_diameter(): the interior whose hex opening is exactly `opening`.
// opening = 2*interior/sqrt3 -> interior = opening * sqrt3 / 2.
double interior_for_opening(double opening, double /*line_width*/) const override {
return opening > 0.0 ? std::max(0.1, opening * SQRT3 * 0.5) : 0.1;
}
// Degree-3 honeycomb junctions are line ENDS, not crossings -> no crossing overlap.
double vertex_overlap_excess_area(double /*line_width*/) const override { return 0.0; }
Continuous honeycomb sweep (the novel toolpath). Rather than tracing each hexagon’s perimeter – which forces many direction changes and short segments – the pattern reuses a single continuous honeycomb zigzag per lane-pair, the same fast, low-travel sweep used by ordinary honeycomb infill. The vertical hexagon edges fall on lanes spaced half the (stretched) flat-to-flat distance apart; one zigzag oscillates between two adjacent lanes k and k+1, drawing a vertical edge (length e), a slant up to the next lane’s vertical (whose bottom is a hexagon vertex), that vertical, and a slant back – a period of 2*row in Y, phased at oy + row*(k-1):
// src/libslic3r/Fill/FillMagma.cpp — FillMagmaHoneycomb::_fill_surface_single
const double s = this->tube_map->cell_spacing(); // centre-to-centre = interior + lw
const double iw = this->tube_map->interior_width(); // OPEN flat-to-flat (user spec)
const double lw = s - iw; // line width
const double e = iw * magma::INV_SQRT3; // OPEN hex edge = interior/sqrt3
const double row = 1.5 * e + lw * magma::INV_SQRT3; // lattice row spacing (Y)
const double half = (iw + 2.0 * lw) * 0.5; // lane pitch = m_sx/2 = (interior + 2lw)/2
for (int k = k_min; k <= k_max; ++k) {
const double xL = ox + double(k) * half + x_off;
const double xR = ox + double(k + 1) * half - x_off;
const double phi = oy + row * double(k - 1);
Polyline pl;
for (int j = j_min; j <= j_max; ++j) {
const double b = phi + 2.0 * row * double(j);
pl.points.push_back(Point(scale_(xL), scale_(b - e * 0.5)));
pl.points.push_back(Point(scale_(xL), scale_(b + e * 0.5)));
pl.points.push_back(Point(scale_(xR), scale_(b + row - e * 0.5)));
pl.points.push_back(Point(scale_(xR), scale_(b + row + e * 0.5)));
}
// ...
}
A consequence of this lane-pair sweep is that every vertical lane is traced by both of the lane-pairs that border it: the vertical cell walls are drawn doubled (two beads, total width 2*lw, centred on the edge, intruding lw into the open cell), while the slanted walls are drawn single (one bead, intruding lw/2). Left uncompensated, the open cross-section would come out skewed – its vertical edges effectively longer than its slants – and would not be a regular hexagon, defeating the round-nozzle seal that depends on a regular opening.
Anisotropic lattice pre-stretch. To make the open tube a true regular hexagon despite the asymmetric wall thickness, the lattice is pre-expanded on each affected axis by exactly the wall geometry, so that after the doubled verticals and single slants intrude, what remains is a regular hexagon of edge e:
// src/libslic3r/Magma/MagmaHexCell.hpp — HexLattice
// Built OUTWARD from the OPEN hexagon (interior = cell_spacing - line_width), so the
// printed open tube comes out at exactly the requested interior width:
// X pitch: interior + 2*lw (the doubled wall, lw each side) -> m_sx
// top/bottom vertex (Y): e + lw/sqrt3 (the slant inset lifts the apex) -> m_vtop
// row spacing (Y): 1.5*e + lw/sqrt3 (= keeps the tiling closed) -> m_row
explicit HexLattice(double cell_spacing, double offset_x = 0.0, double offset_y = 0.0,
double line_width = 0.0)
: m_cell_spacing(cell_spacing)
, m_edge(hex_edge_length(std::max(0.0, cell_spacing - std::max(0.0, line_width))))
// e = interior / sqrt3
, m_sx (cell_spacing + std::max(0.0, line_width)) // = interior + 2*lw
, m_vtop(m_edge + std::max(0.0, line_width) * INV_SQRT3) // extended top/bottom vertex
, m_row (1.5 * m_edge + std::max(0.0, line_width) * INV_SQRT3)// extended row spacing
, m_offset_x(offset_x), m_offset_y(offset_y)
{}
std::vector<Vec2d> cell_corners(const CellId &c) const override {
const Vec2d ctr = center(c.a, c.b);
const double hx = m_sx * 0.5; // half (stretched) flat-to-flat
const double hy = m_edge * 0.5; // half edge length (vertical edge stays e)
return { Vec2d(ctr.x() + hx, ctr.y() + hy), // 30 deg (upper right)
Vec2d(ctr.x(), ctr.y() + m_vtop),// 90 deg (top vertex, extended)
Vec2d(ctr.x() - hx, ctr.y() + hy), // 150 deg (upper left)
Vec2d(ctr.x() - hx, ctr.y() - hy), // 210 deg (lower left)
Vec2d(ctr.x(), ctr.y() - m_vtop),// 270 deg (bottom vertex, extended)
Vec2d(ctr.x() + hx, ctr.y() - hy) }; // 330 deg (lower right)
}
The vertical-edge length is held at e (the +-hy corners), while the horizontal span gains 2*lw and the top/bottom apexes and row pitch gain lw/sqrt(3). With all three adjustments, the open hexagon’s vertical and slanted edges come out exactly equal (both e): a regular open tube that the round/conical injection nozzle can seal as in the other patterns. The hexes are addressed by axial (q, r) coordinates packed into the shared CellId, with cube-rounding for point-to-cell lookup and the standard six pointy-top axial neighbours, so the same tube-assignment solver, U-tube pairing, window placement, injection, and preview pipeline (claim 13) operate unchanged.
Windows. Each open pair’s shared wall is removed by subtracting a rectangle laid over the shared edge, wide enough (x_off + lw half-width) to span both doubled verticals and shortened by a bead so the hexagon corners survive, then the swept polylines are clipped to the region and chained into continuous sweeps. Window height is auto-derived from the partner hexagon’s open cross-section (auto_window_height = open_area / open_edge), matching the cross-section flow area as in the triangle and square patterns.
Prior-art scope. This disclosure establishes prior art for: (a) a regular-hexagon (honeycomb) vertical-reinforcement injection-infill tiling whose cell size is set by the nozzle-derived tube interior width rather than an infill density; (b) generating its toolpath as a single continuous lane-pair honeycomb zigzag (rather than per-hexagon perimeters) for fast, low-travel printing; (c) the resulting doubled vertical walls / single slanted walls produced by that sweep; and (d) anisotropically pre-stretching the lattice outward from the open cross-section (X pitch = open flat-to-flat +2*lw for the doubled verticals, vertex +lw/sqrt(3) and row pitch +lw/sqrt(3) for the single slants) so that the open injectable cross-section is a regular hexagon of the requested interior width despite the asymmetric deposited wall thickness, with U-tube pairing and shared-wall windows as in the other Magma patterns.
Implementation status: IMPLEMENTED and tested in software.
Historical note: The deterministic pairing and salvage assignment described below were the original tube assignment algorithms. They have been superseded by the two-stage solver described in Section 5 (greedy warm start + CP-SAT refinement). The algorithms are disclosed here for completeness and prior art.
Default tube pairing iterates only up-triangles (sum=2), evaluating all three down-triangle neighbors and selecting the partner with the greatest total shared height in millimeters. The best-partner selection ensures optimal coverage at sloped boundaries where the default a-axis partner may only exist for a fraction of the cell’s height:
// src/libslic3r/Magma/MagmaTubeMap.cpp — assign_default_tubes()
// Only iterate up triangles -- each up-down pair considered once.
for (const auto &[cell, presence] : m_cells) {
if (!cell.is_up())
continue;
// Try all 3 DN neighbors, pick the one with the longest total shared span.
auto neighbors = cell.neighbors();
TriangleCell best_partner;
double best_total_shared_mm = 0.0;
for (const TriangleCell &neighbor : neighbors) {
auto nit = m_cells.find(neighbor);
if (nit == m_cells.end())
continue;
std::vector<SharedSpan> nspans = find_shared_spans(presence, nit->second);
double total_mm = 0.0;
for (const SharedSpan &s : nspans)
total_mm += span_height_mm(s.start, s.end);
if (total_mm > best_total_shared_mm) {
best_total_shared_mm = total_mm;
best_partner = neighbor;
// ...
}
}
// ... create tube pairs for best partner ...
}
The shared edge between two adjacent triangle cells is determined algebraically from their (a,b,c) coordinates. Since neighbors differ in exactly one coordinate, the differing coordinate identifies the edge type:
// src/libslic3r/Magma/MagmaTubeMap.hpp
enum class SharedEdge { Horizontal, Col60, Diag120 };
inline SharedEdge shared_edge(const TriangleCell &a, const TriangleCell &b) {
if (a.a != b.a) return SharedEdge::Col60; // differ in a -> 60 degree edge
if (a.b != b.b) return SharedEdge::Horizontal; // differ in b -> horizontal edge
return SharedEdge::Diag120; // differ in c -> 120 degree edge
}
This O(1) computation eliminates geometric edge-finding. The shared edge type determines which line family (horizontal, 60-degree, or 120-degree) the window gap appears on, and the exact lattice vertices bounding the shared edge.
Tube boundaries are placed at mm-based grid lines aligned with the stagger offset. After boundary placement, short leading and trailing segments are merged into their neighbors to prevent tubes that are too short for structural utility:
// src/libslic3r/Magma/MagmaTubeMap.cpp — assign_default_tubes()
// Merge short first/last segments into their neighbors (mm-based check)
while (boundaries.size() >= 3) {
double first_seg_h = span_height_mm(boundaries[0], boundaries[1] - 1);
if (first_seg_h >= m_min_tube_height_mm)
break;
boundaries.erase(boundaries.begin() + 1);
}
while (boundaries.size() >= 3) {
double last_seg_h = span_height_mm(
boundaries[boundaries.size() - 2], boundaries.back() - 1);
if (last_seg_h >= m_min_tube_height_mm)
break;
boundaries.erase(boundaries.end() - 2);
}
The minimum tube height is structurally derived: window_height_mm * 2 + 2 * min_layer_height in millimeters, ensuring sufficient solid wall material above and below each window for structural integrity.
For salvage tube assignment, the system computes which layers of a cell are NOT covered by existing tube pairs:
// src/libslic3r/Magma/MagmaTubeMap.cpp
static CellPresence uncovered_presence(
const CellPresence &presence,
const std::vector<int> &pair_indices,
const std::vector<UTubePair> &pairs)
{
if (pair_indices.empty())
return presence;
CellPresence result;
for (int layer = presence.first_layer; layer <= presence.last_layer; ++layer) {
if (!presence.present(layer))
continue;
bool covered = false;
for (int idx : pair_indices) {
const UTubePair &p = pairs[idx];
if (layer >= p.pair_start_layer && layer <= p.pair_end_layer) {
covered = true;
break;
}
}
if (!covered)
result.mark_present(layer, presence.area(layer));
}
return result;
}
This enables cells that are partially covered by default tubes to have their uncovered ranges assigned to salvage tubes, maximizing reinforcement coverage.
Salvage tube assignment maximizes shared uncovered height between a cell and its neighbors. It processes candidates sorted by first layer (bottom-up), evaluating all three neighbors for each unassigned or partially-uncovered cell:
// src/libslic3r/Magma/MagmaTubeMap.cpp — assign_salvage_tubes()
for (const TriangleCell &cell : candidates) {
// Get this cell's uncovered layers
CellPresence cell_uncovered = uncovered_presence(presence, cell_pairs, m_pairs);
if (cell_uncovered.first_layer > cell_uncovered.last_layer)
continue; // Fully covered
// Try all 3 neighbors, prefer longest shared uncovered height (in mm)
TriangleCell best_partner;
double best_height_mm = 0.0;
SharedSpan best_span{-1, -1};
for (const TriangleCell &neighbor : cell.neighbors()) {
auto nit = m_cells.find(neighbor);
if (nit == m_cells.end())
continue;
CellPresence nbr_uncovered = uncovered_presence(
neighbor_presence, nbr_pairs, m_pairs);
std::vector<SharedSpan> spans = find_shared_spans(
cell_uncovered, nbr_uncovered);
for (const SharedSpan &span : spans) {
double h_mm = span_height_mm(span.start, span.end);
if (h_mm >= m_min_tube_height_mm && h_mm > best_height_mm) {
best_partner = neighbor;
best_height_mm = h_mm;
best_span = span;
}
}
}
if (best_height_mm > 0) {
UTubePair pair;
pair.cell_a = cell;
pair.cell_b = best_partner;
pair.pair_start_layer = best_span.start;
pair.pair_end_layer = std::min(
layer_at_height_from(best_span.start, m_max_tube_height_mm),
best_span.end);
pair.is_salvaged = true;
// ... register pair ...
}
}
Salvage tubes are marked with is_salvaged = true to distinguish them from default deterministic pairs. Cells with no viable partner are marked as solid fill (empty pair index vector).
Historical note: the closed-form per-layer volume estimate below – accumulate ideal/clipped cell areas, add a geometric window-gap term, subtract a per-pattern vertex-overlap term – has been superseded by a direct measurement of the cavity from the deposited toolpath (Section 4.g), which captures the side-by-side doubled walls, the window gap, and part-edge clipping in one operation from the real footprint. The closed-form estimate is retained here for prior art; the overlap-excess reasoning it introduced lives on as the one residual that the footprint measurement cannot see – now applied as a single self-scaling, flow-correction-aware subtraction sized to the actual deposited line width (Section 4.h), rather than the conditional term used here.
Tube volume is computed by accumulating per-layer cell areas (in scaled squared units) multiplied by per-layer heights, then adding window gap volume and subtracting triangle vertex overlap excess:
// src/libslic3r/Magma/MagmaTubeMap.cpp — compute_volumes()
for (UTubePair &pair : m_pairs) {
double tube_volume_scaled2_mm = 0.0;
double window_height_mm = 0.0;
double overlap_excess_volume = 0.0;
for (int layer_id = pair.pair_start_layer; layer_id <= pair.pair_end_layer;
++layer_id) {
double area_a = /* cell_a area at layer_id */;
double area_b = /* cell_b area at layer_id */;
double lh = /* layer height at layer_id */;
tube_volume_scaled2_mm += (area_a + area_b) * lh;
// Accumulate window height using mm-based Z check
if (m_layer_data[layer_id].bottom_z() < pair.window_end_z)
window_height_mm += lh;
// Per-layer overlap excess: 2 cells per pair
overlap_excess_volume += excess_area_per_cell_mm2 * 2.0 * lh;
}
double tube_volume = tube_volume_scaled2_mm * SCALING_FACTOR * SCALING_FACTOR;
double window_volume = inset_side * m_line_width * window_height_mm;
double orig_volume = tube_volume + window_volume;
pair.volume_mm3 = std::max(0.0, orig_volume - overlap_excess_volume);
}
The window gap volume uses the inset side length (not the full edge) since interiors are smaller than the outer triangle. Window layer membership is checked via mm-based Z comparison (bottom_z() < pair.window_end_z) rather than layer counts, ensuring correct behavior with variable layer heights. The overlap excess subtraction accounts for triangle vertex overlap regions where 3 line families cross at 60 degrees, depositing material twice – this excess physically occupies tube interior space, so injection volume is reduced accordingly.
Rather than estimating each U-tube’s injectable cavity from closed-form cell geometry (Section 4.f), the shipping system measures that cavity from the actually generated infill. measure_volumes() runs after PrintObject::infill(), when each layer region’s fills hold the real extrusion paths. For each layer of a pair’s run, the injectable void at that layer is the union of the pair’s cell polygons (cell_a, cell_b, and any extra tri-hex vent legs) intersected with the reinforcement zone, minus the footprint of the deposited Magma walls (the polygons the extrusion physically covers, from polygons_covered_by_width). Summed over the run times each layer’s height, this is the dosed injection volume:
// src/libslic3r/Magma/MagmaTubeMap.cpp — measure_volumes()
//
// For each pair, the injected cavity at a layer is (cell_a u cell_b u vents) n zone minus
// the deposited magma walls. Summed over the run x layer height, that single measurement nets
// out the side-by-side doubled walls, the window gap, and part-edge clipping from the real
// footprint; the residual over-extrusion where lines cross is corrected separately (see 4.h).
// Runs after PrintObject::infill(), when fills hold the real paths.
// Per-layer cache (shared by all pairs on a layer): the magma zone + deposited walls.
for (int lid : used) {
const Layer *layer = /* layer with id lid */;
ExPolygons zone; Polygons walls;
for (const LayerRegion *lr : layer->regions()) {
const PrintRegionConfig &rc = lr->region().config();
if (!(rc.dual_infill_enabled || is_magma_pattern(rc.sparse_infill_pattern.value)))
continue;
for (const Surface &s : lr->fill_surfaces.surfaces)
if (s.surface_type == stInternal) zone.push_back(s.expolygon);
append(walls, lr->fills.polygons_covered_by_width(0.f)); // actual deposited footprint
}
zone_by_layer[lid] = union_ex(zone);
walls_by_layer[lid] = union_ex(walls);
}
// ... then per pair, per layer:
ExPolygons combined = intersection_ex(union_ex(cells), zone_by_layer[lid]);
const ExPolygons &walls = walls_by_layer[lid];
ExPolygons cavity = walls.empty() ? combined : diff_ex(combined, walls); // void = cells n zone − walls
double a2 = 0.0;
for (const ExPolygon &ep : cavity) a2 += std::abs(ep.area());
vol += unscale<double>(unscale<double>(a2)) * h_by_layer[lid];
Because the measurement uses the real deposited footprint, the same single operation accounts for effects that the closed-form estimate had to model with separate per-pattern terms: vertical walls that the toolpath draws doubled side by side (Section 3.h, which the footprint sees as a wider solid wall), the window gap (its missing wall simply leaves more void), and clipping of cells at the part edge. The one effect the footprint cannot see – the extra plastic where lines CROSS and stack, which polygons_covered_by_width merges into a single union so the second bead’s bulge into the void is never recorded – is removed by the companion self-scaling correction of Section 4.h. The per-layer zone and wall polygons are cached once per layer and reused across every pair touching that layer. The result is stored as pair.volume_mm3, and only pairs with positive measured volume contribute an injection cap layer.
Prior-art scope. This disclosure establishes prior art for determining the injected-material dose for an in-situ printed channel by measuring its per-layer cavity from the generated toolpath – (cell polygons intersected with the infill zone) minus the polygons covered by the deposited extrusion width, summed over the channel’s layer range times layer height – rather than from a closed-form cross-section, so that a single geometric difference captures side-by-side doubled walls, the window gap, and part-edge clipping with no pattern-specific correction terms (the residual stacking over-extrusion where lines cross being removed by the companion self-scaling correction of Section 4.h).
Implementation status. The
magma_overlap_line_correction/magma_overlap_min_widthprint-quality lever described in this section has since been removed from the shipping slicer — it was off by default, it was not useful enough to justify itself, and it was the only reason the tube map carried two different line widths, which in practice produced several code paths that disagreed about which width to use. Lines now always print at full nominal width and the full crossing overlap is always subtracted; anyone wanting thinner beads can set a lower sparse infill line width directly. The implementation remains in the project’s git history, and the disclosure below is retained in full as prior art — the mechanism was built and published, and its removal is a product decision, not an abandonment of the idea.
Where infill line families cross, the toolpath deposits material twice, over-extruding at each junction, and the second bead’s bulge squeezes into the cavity. Because the deposited-wall footprint of Section 4.g (polygons_covered_by_width) merges the two crossing beads into a single union, that bulge is never recorded by the measurement, so the injection volume is always corrected for it. The correction is a single self-scaling subtraction, sized to the actual deposited line width – not two mutually-exclusive levers, and not gated on any setting.
The magma_overlap_line_correction setting (default off) does not decide whether the volume is corrected; it only changes how the lines are PRINTED, and therefore what the deposited width is:
w. The effective width is w_eff = w, and the FULL per-cell crossing overlap is subtracted from the measured cavity.magma_overlap_min_width, default ~90% of nozzle diameter), so the lines do not vanish and the crossings still over-extrude a little. The effective width becomes w_eff = w_corrected, and only the small RESIDUAL crossing overlap of the thinned lines is subtracted.The deposited (effective) width is resolved once, in build(); the volume subtraction (below) then always evaluates the per-vertex excess at that width:
// src/libslic3r/Magma/MagmaTubeMap.cpp — build()
// Two correction levers:
// 1. Line width: reduce infill flow so deposited width shrinks from w to w_eff.
// 2. Injection volume: subtract per-layer excess from tube fill volume.
// ALWAYS applied, regardless of the line-width correction setting.
map->m_effective_line_width = map->m_line_width; // w (setting off)
double excess_frac = m_geometry->line_overlap_excess_fraction(S, w); // doubled fraction
if (m_overlap_line_correction && excess_frac > 0.0) {
double w_corrected = std::max(min_width, w * (1.0 - excess_frac)); // floored ~90% nozzle
map->m_overlap_flow_correction = w_corrected / w; // applied to infill flow
map->m_effective_line_width = w_corrected; // w_eff (setting on)
}
The per-vertex excess area is a shape constant supplied by the geometry strategy, evaluated at the deposited width lw_eff = m_effective_line_width and apportioned per cell:
| Pattern | Per-vertex excess area (at deposited width lw_eff) |
Apportionment |
|---|---|---|
| Triangle | (3*sqrt(3)/4) * lw_eff^2 |
per cell (2 cells/pair) |
| Rectilinear (square) | lw_eff^2 |
per cell (2 cells/pair) |
| Tri-hex | (2/sqrt(3)) * lw_eff^2 |
charged to incident cells by corner count: hub 6, vent 3, divided by 4 |
| Honeycomb | 0 (degree-3 junctions are line ends, not crossings) |
n/a |
// src/libslic3r/Magma/MagmaTubeMap.cpp — measure_volumes()
// The injection volume is ALWAYS corrected for vertex overlap, evaluated at the ACTUAL
// deposited width m_effective_line_width: residual when the flow correction is on (thinned
// lines), full when off. It is NOT double-counting the footprint — polygons_covered_by_width
// merges crossing lines into a single union, so the second line's deposit (which bulges into
// the void) is never captured there and must be subtracted here.
const double excess_unit = m_geometry->vertex_overlap_excess_area(m_effective_line_width);
// per pair: apportion the excess per cell ...
if (m_pattern == ipMagmaTriHex) {
auto charge = [&](const TriangleCell &c) {
return 0.25 * ((c.kind == THK_HEX) ? 6.0 : 3.0) * excess_unit; // corner count / 4
};
excess_rate = charge(pair.cell_a) + charge(pair.cell_b);
for (const TriangleCell &ev : pair.extra_vents) excess_rate += charge(ev);
} else {
excess_rate = excess_unit * double(2 + int(pair.extra_vents.size()));
}
// ... per layer: vol -= excess_rate * h_by_layer[lid]; (always; zero for honeycomb)
Because the subtraction is sized to whatever width was actually deposited, it is one self-scaling term: it shrinks to a residual when the lines were thinned and grows to the full overlap when they were not – corrected once in both cases, never double-counted. The novelty is precisely this: the overlap is corrected exactly once, sized to what was actually deposited, regardless of the flow-correction setting; the flow correction is a print-quality lever that shifts where the line-width reduction happens, not whether the volume is corrected. (Honeycomb’s vertex excess is zero, so it is unaffected – its doubled vertical walls run side by side, not stacked, so the footprint already captures them; only stacking line crossings need this term.)
Prior-art scope. This disclosure establishes prior art for correcting the over-extrusion at infill line crossings with a single, always-applied, self-scaling subtraction from a toolpath-measured cavity (Section 4.g), sized to the actual deposited line width – so the correction is a residual when an optional flow-reduction print-quality lever has thinned the lines and the full overlap when it has not – such that the crossing overlap is corrected exactly once and never double-counted regardless of the flow-correction setting, with the per-cell overlap area a shape-specific constant apportioned by incident-cell corner count (zero for the honeycomb pattern, whose junctions are line ends rather than crossings).
Implementation status: IMPLEMENTED and tested in software.
The default deterministic pairing (Section 4) is superseded by an optimized two-stage solver that significantly improves coverage and structural quality. The system operates in two modes: Basic (Stage 1 only, ~100-500ms) and Refined (Stage 1 + Stage 2, minutes).
MagmaTubeSolver::solve()
build_micron_tables() — layer boundaries in integer microns
build_edges() — adjacent cell pairs, shared presence runs
greedy_warm_start() — fast heuristic, populates m_committed
validate("GREEDY") — check constraints, log coverage
if (Refined mode) {
for each Z level:
solve_pass() — CP-SAT reads m_committed as warm start
validate("CPSAT") — check constraints, log coverage
}
extract_results() — microns → UTubePair layer indices
validate("FINAL") — final constraint check + coverage summary
All tube boundary positions are stored as 64-bit integer microns (µm), eliminating floating-point comparison errors in the constraint solver. Pre-computed once per object:
// src/libslic3r/Magma/MagmaTubeSolver.cpp
top_um[L] = llround(print_z * 1000) // authoritative layer top
bottom_um[0] = llround(bottom_z * 1000) // first layer bottom
bottom_um[L] = top_um[L-1] // exactly contiguous (no gap)
Since bottom_um[L+1] == top_um[L], all layer boundaries form a single sorted sequence. This property is exploited for discrete domain construction.
A fast deterministic heuristic that assigns tubes using a priority queue ordered by constraint tightness. Runs in 100-500ms for models with 1000+ cells.
// src/libslic3r/Magma/MagmaGreedyWarmStart.cpp
void greedy_warm_start(
const unordered_map<TriangleCell, CellPresence> &cells,
const vector<EdgeData> &edges,
const unordered_map<TriangleCell, vector<size_t>> &cell_edges,
const MicronTables &um,
int64_t min_h_um, int64_t max_h_um,
vector<vector<CommittedSegment>> &committed);
Scoring: For each unconsumed cell×layer, the score equals the sum of achievable tube heights across all unconsumed neighbors. Lower score = fewer/shorter options = more constrained. This naturally prioritizes boundary cells (1 neighbor, low score) over interior cells (3 neighbors, high score), preventing stranding.
Assignment: Pop the most constrained cell×layer from a min-heap. Find its most constrained neighbor (fewest unconsumed layers in their shared run at this Z). Expand the longest valid tube between them, respecting min/max height bounds, consumed intervals, and run boundaries. Mark consumed on both cells.
Periodic re-scoring: After every max(200, num_edges/3) assignments, rebuild the heap from scratch with fresh consumed state. As tubes are assigned, heap ordering becomes stale — cells that became more constrained due to neighbor consumption need re-prioritization. The floor of 200 prevents churn on small models. Typically triggers 3-10 re-scores per model.
Data structures:
CellConsumed: sorted non-overlapping micron intervals per cell with binary search overlap checking and insert-merge for additions. O(log n) per operation.CellLayerScore: min-heap entry with cell, layer, micron boundaries, and score.Key properties:
Optional second stage using Google’s CP-SAT (Constraint Programming with Satisfiability) solver from OR-Tools. Starts from the greedy solution and locally improves coverage while avoiding weak planes. Typically adds 3-7% absolute coverage.
Variables (per segment slot on each edge):
active : BoolVar — is this segment used?
start : IntVar — tube bottom in microns (discrete domain)
end : IntVar — tube top in microns (discrete domain)
size : IntVar — tube height in microns (discrete domain)
interval : OptionalIntervalVar(start, size, end, active)
Discrete domains from layer boundaries: All micron-space variables use Domain::FromValues() with the actual layer boundary positions, rather than continuous ranges. Since each boundary is both the end of one layer and the start of the next, a unified boundary list per edge run is computed:
// Unified boundary list: one value at each layer interface
std::vector<int64_t> boundaries;
boundaries.push_back(bottom_um[eff_start]);
for (int L = eff_start; L <= eff_end; ++L)
boundaries.push_back(top_um[L]);
// Feasible sizes: all achievable boundary-to-boundary heights within bounds
std::set<int64_t> size_set;
for (size_t i = 0; i < boundaries.size(); ++i)
for (size_t j = i + 1; j < boundaries.size(); ++j) {
int64_t s = boundaries[j] - boundaries[i];
if (s > max_h_um) break;
if (s >= min_h_um) size_set.insert(s);
}
This dramatically tightens the LP relaxation (the solver’s internal linear programming bound), improving solve quality by 10-30% compared to continuous ranges. The feasible-differences domain for size/contribution variables prevents the LP from considering non-achievable heights.
Constraints:
Objective function:
Maximize:
(W_COVERAGE + W_LENGTH) × Σ{ size × active } — coverage + length tiebreaker
- W_STAGGER_TIGHT × Σ{ tight_capacity_per_cell } — very close boundaries
- W_STAGGER_WIDE × Σ{ wide_capacity_per_cell } — moderate clustering
| Weight | Value | Purpose |
|---|---|---|
| W_COVERAGE | 1,000,000 | 1µm of coverage vastly outweighs all stagger penalty |
| W_LENGTH | 1 | Tiebreaker: prefer fewer, longer tubes |
| W_STAGGER_TIGHT | 2 | Penalize boundaries within dodge/2 of neighbors |
| W_STAGGER_WIDE | 1 | Penalize boundaries within full dodge distance |
When tube boundaries on nearby cells cluster at the same Z height, they create a horizontal “weak plane” — a layer with reduced reinforcement continuity. The stagger penalty discourages this using cumulative scheduling constraints.
For each cell, two AddCumulative constraints (tight + wide scale) measure peak boundary concentration in the cell’s Ring-0 + Ring-1 neighborhood:
Zone interval widths derive from the configurable dodge distance (default: 4 × max_layer_height). When dodge is 0 or very small, the entire stagger section is skipped.
Committed segments from the greedy stage become CP-SAT warm start hints:
SolutionHint(active=1, start, end, size)The warm start gives CP-SAT a complete initial solution, dramatically reducing search time compared to starting from scratch.
The model is spatially partitioned into independent blocks for bounded computation:
m_cell_edges) instead of scanning all edges — O(block cells × edges per cell) instead of O(total edges).tbb::this_task_arena::max_concurrency()) — the parallelism lives inside each block’s CP-SAT solve rather than across blocks.throw_if_canceled() (OrcaSlicer’s standard pattern). Current blocks finish their timeout before cancellation takes effect.Reusable validate_committed() function checks all constraints on committed segments. Called after each stage (GREEDY, CPSAT, FINAL):
| Model | Cells | Greedy | +CP-SAT (10s) | +CP-SAT (20s) |
|---|---|---|---|---|
| 20mm cube | 71 | 80.6% / 4ms | 90.6% / ~80s | — |
| Stanford bunny | 1056 | 76.5% / 503ms | 79.0% / ~197s | 80.5% / ~589s |
The greedy stage alone provides excellent coverage for quick iteration. CP-SAT refinement adds 3-7% coverage at significant time cost — best for final production slicing.
Implementation status: IMPLEMENTED and tested in software.
Window height is automatically calculated in mm to match the tube cross-section area to the window opening area, ensuring adequate flow between paired cells:
// src/libslic3r/Magma/MagmaTriangleCell.cpp
static double calculate_auto_window_height_mm(double interior_width, double line_width)
{
double cell_spacing = cell_spacing_from_geometry(interior_width, line_width);
double tube_area = inset_triangle_area(cell_spacing, line_width);
double side = triangle_side_length(cell_spacing);
double inset_side = side - line_width * SQRT3;
if (inset_side <= 0)
return 0.1;
// Geometric height: window cross-section equals tube interior (caller adds 1 layer)
double window_height_mm = tube_area / inset_side;
return std::max(0.1, window_height_mm);
}
The formula tube_area / inset_side derives from equating the tube interior cross-section area (the inset triangle area after accounting for line width eating into the interior) with the window opening area (inset_side * window_height), where inset_side = side - line_width * sqrt(3) is the gap length between two adjacent inset triangle interiors along the shared edge. The caller (from_config) then adds one layer height to this geometric value so the window reliably spans a full printed layer despite layer-registration accuracy. The result is in mm (not layers), supporting variable layer heights directly.
Window gaps are organized by line family (horizontal, 60-degree, 120-degree). Each line family uses a map from line index to sorted, merged intervals of world-coordinate ranges where lines should be interrupted:
// src/libslic3r/Magma/MagmaTubeMap.hpp
struct WindowGaps {
double cell_spacing;
double offset_x, offset_y;
std::map<int, std::vector<std::pair<double, double>>> horiz;
std::map<int, std::vector<std::pair<double, double>>> col60;
std::map<int, std::vector<std::pair<double, double>>> diag120;
};
// src/libslic3r/Magma/MagmaTubeMap.cpp — window_gaps()
// Sort and merge intervals per line index
for (auto &[key, intervals] : result.horiz)
merge_intervals(intervals);
for (auto &[key, intervals] : result.col60)
merge_intervals(intervals);
for (auto &[key, intervals] : result.diag120)
merge_intervals(intervals);
The merge function combines overlapping or adjacent intervals (within 0.01mm tolerance) into a single interval, preventing double-gap artifacts when multiple tube pairs share the same line segment.
Window gaps are subtracted during line generation, not clipped after the fact. This is more efficient than generating full lines and then clipping, and avoids numerical issues with post-hoc line splitting:
// src/libslic3r/Fill/FillMagma.cpp — _fill_surface_single()
// Horizontal lines with gaps built in
for (int b = row_min; b <= row_max; ++b) {
coord_t y_s = coord_t(scale_(b * cs + off_y));
auto it = gaps.horiz.find(b);
if (it == gaps.horiz.end()) {
all_lines.push_back(make_horiz_segment(x_min, x_max, y_s));
} else {
subtract_gaps(x_min, x_max, it->second, [&](double lo, double hi) {
all_lines.push_back(make_horiz_segment(lo, hi, y_s));
});
}
}
The subtract_gaps template function walks sorted gap intervals, emitting kept segments between gaps:
// src/libslic3r/Fill/FillMagma.cpp
template<typename EmitFn>
static void subtract_gaps(double lo, double hi,
const std::vector<std::pair<double, double>> &gaps,
EmitFn emit)
{
double cursor = lo;
for (const auto &gap : gaps) {
double gl = std::max(gap.first, lo);
double gr = std::min(gap.second, hi);
if (gr <= gl)
continue;
if (gl > cursor + 0.01)
emit(cursor, gl);
cursor = std::max(cursor, gr);
}
if (hi > cursor + 0.01)
emit(cursor, hi);
}
For 60-degree and 120-degree lines, window gaps are specified as Y-coordinate intervals. Since these lines are not horizontal, the Y intervals must be converted to parametric positions along the line segment:
// src/libslic3r/Fill/FillMagma.cpp
static void split_line_by_y_gaps(
const Vec2d &p0, const Vec2d &p1,
const std::vector<std::pair<double, double>> &y_gaps,
Polylines &out)
{
double dy = p1.y() - p0.y();
// Convert Y intervals to parametric t values along p0->p1
auto y_to_t = [&](double y) { return (y - p0.y()) / dy; };
auto t_to_point = [&](double t) -> Vec2d {
return Vec2d(p0.x() + t * (p1.x() - p0.x()),
p0.y() + t * dy);
};
std::vector<std::pair<double, double>> t_gaps;
for (const auto &gap : y_gaps) {
double gl = std::max(gap.first, y_lo);
double gr = std::min(gap.second, y_hi);
if (gr <= gl)
continue;
double t0 = y_to_t(gl);
double t1 = y_to_t(gr);
if (t0 > t1) std::swap(t0, t1);
t_gaps.push_back({t0, t1});
}
std::sort(t_gaps.begin(), t_gaps.end());
subtract_gaps(0.0, 1.0, t_gaps, [&](double t_lo, double t_hi) {
Vec2d a = t_to_point(t_lo);
Vec2d b = t_to_point(t_hi);
// ... emit polyline segment ...
});
}
The parametric conversion correctly handles both upward-sloping (60-degree) and downward-sloping (120-degree) lines by sorting t-values after conversion.
Tube height is clamped to a structural minimum ensuring sufficient solid wall material above and below each window. The minimum is now mm-based:
// src/libslic3r/Magma/MagmaTubeMap.cpp — build()
m_min_tube_height_mm = m_window_spec.window_height_mm * 2.0
+ 2.0 * double(m_min_layer_height);
The formula ensures: one window height of solid wall below the window, one window height of solid wall above the window, plus two minimum layers of padding. User-specified tube height is clamped to this minimum. Stagger is now handled by the CP-SAT solver’s cumulative scheduling constraints (Section 5.d) rather than explicit stagger level clamping.
Implementation status: IMPLEMENTED and tested in software. The injection system generates working G-code; multi-material filament switching is fully wired but not yet tested on multi-material hardware.
Injection occurs as a dedicated print stage within each layer’s processing, not as a post-print operation. The injection sequence for each layer:
Injection volumetric speed is user-configured via magma_injection_speed (default 10 mm^3/s), capped at filament_max_volumetric_speed. Tube height is user-specified via magma_tube_height (default 4.5mm).
// src/libslic3r/Magma/MagmaInjection.cpp
double vol_speed = std::max(1.0, injection_speed_vol);
double max_vol = config.filament_max_volumetric_speed.get_at(extruder_id);
if (max_vol > 0)
vol_speed = std::min(vol_speed, max_vol);
A coupled thermal-pressure model for automatic depth/speed calculation was designed, implemented, and tested but removed from the current release (see Section 10.e).
During stationary injection, the nozzle lowers into the surface to create a mechanical seal against the tube opening. This prevents plastic from escaping laterally during injection. The depth is configurable via magma_injection_z_slam (default 0.05mm), clamped to 3.5mm with a UI warning for large values. Set to 0 to disable.
// src/libslic3r/Magma/MagmaInjection.cpp (simplified)
double slam_depth = std::min(config.magma_injection_z_slam.value, 3.5);
// Lower the nozzle into the surface to seal against the opening
if (slam_depth > 0) {
sprintf(buf, "G1 Z%.3f F%d ; z-slam seal\n", layer_z - slam_depth, z_feedrate);
gcode += buf;
}
// ... injection extrusion (optionally with progressive plunge) ...
// Finish: crack the seal *before* retracting, so retraction can't pull the
// freshly injected plug back up through the still-sealed interface. A small
// fixed break-lift relieves the contact pressure regardless of plunge depth;
// the crater-iron wipe (Section 7.d) then returns the nozzle to layer height.
sprintf(buf, "G1 Z%.3f F%d ; injection break-lift\n",
layer_z - slam_depth - plunge_depth + 0.3, z_feedrate);
gcode += buf;
if (inj_retract)
gcode += gcodegen.writer().retract();
Small values (0.05mm) work with nozzles that have a wide flat tip. Nozzles with a narrow flat and tapered tip may need deeper values (0.5-1.0mm) so the taper widens enough to seal the tube opening. The slam/lift moves use the printer’s Z travel speed (travel_speed_z, firmware-capped) rather than a hardcoded feedrate, so the nozzle does not linger on the hot tube top.
Seal depth from nozzle cone geometry, and the immersion budget that governs it. A standard nozzle tip is a flat ring of diameter flat (the measured magma_nozzle_outer_diameter, “Nozzle tip flat”) with a cone of half-angle theta (magma_nozzle_cone_half_angle, default 30 degrees) widening above it. To seal a tube opening of diameter opening, the nozzle must descend until the cone has widened from flat to opening plus a small seal margin (MAGMA_SEAL_MARGIN, 0.1mm, so the cone clears the opening rather than just grazing it). Each unit of descent widens the cone by 2 * tan(theta), giving seal_depth = (opening + margin - flat) / (2 * tan(theta)), floored at zero when the flat already covers the opening. There is no user-facing manual depth: the slicer derives it per tube from that tube’s own clipped opening, so a tube whose top was clipped narrow gets the deeper press it needs.
The non-obvious part is what that depth costs. It is natural to assume the deformation around an injection scales with how hard the nozzle is pressed in, and therefore that the depth is the thing to limit. It is not. Because the solve targets opening + margin, the mechanical interference past first contact with the tube rim is always margin / (2 * tan(theta)) — the opening and the flat cancel out of the expression entirely, leaving a constant 0.0866mm at 30 degrees that is identical for every tube size and every nozzle. A wider tube does not press harder; it only moves the point at which contact begins further down.
What actually varies between a clean injection and a deformed one is how far the hot nozzle travels inside the tube before it seals. Two test prints differing only in that quantity (0.54mm and 1.08mm) had byte-identical interference and visibly different top surfaces. The disclosed system therefore exposes the immersion as the user-facing budget (magma_max_immersion, default 0.6mm) rather than exposing the depth, and consumes that budget in two directions:
max_opening_for_immersion(flat, theta, budget) = flat + 2 * budget * tan(theta) - margin gives the largest opening sealable within the budget, and the pattern’s own geometry strategy (MagmaGeometry::interior_for_opening) converts that opening into the interior width for that cell shape. The tube is thus made as large as the user’s tolerance for deformation permits, with no arithmetic by the user, and the depth cap never binds.// src/libslic3r/Magma/MagmaTriangleCell.hpp (shape-agnostic seal math)
inline double auto_slam_depth(double opening_dia, double flat, double cone_half_angle_deg,
double max_immersion, double press) {
press = std::max(0.0, press);
double needed = seal_depth_for_opening(opening_dia + MAGMA_SEAL_MARGIN, flat, cone_half_angle_deg);
double budget = std::max(press, std::max(0.0, max_immersion));
return std::min(std::min(std::max(press, needed), budget), MAGMA_SLAM_CLAMP);
}
When the flat already covers the opening outright, no descent is geometrically required and needed is zero; the nozzle still presses down by press (magma_auto_slam_press, default 0.1mm) so ordinary part-to-part variation cannot leave the seal open. The nozzle tip flat has no default and no fallback: it is a physical property of the user’s hardware that cannot be guessed from the nozzle’s bore diameter, so slicing fails with measurement instructions until it is provided.
Prior-art scope. This disclosure establishes prior art for governing an in-situ sealing plunge by a nozzle-immersion budget rather than a plunge depth — including the observation that, when the seal solve targets the opening plus a fixed margin, the mechanical interference past rim contact is invariant to both opening and tip flat, so depth is the wrong quantity to bound — and for inverting that budget to size the printed channel itself, so the channel is made the largest one sealable within the user’s deformation tolerance.
Progressive plunge (“slam-melt”). A single fixed seal depth can fail mid-injection: as channel pressure rises, plastic finds the lateral gap at the seal and mushrooms out around the nozzle instead of flowing down the tube. The plunge ramps the nozzle deeper while injecting — the extrusion is split into segments and the Z is stepped down between them from slam_depth to slam_depth + plunge_depth over the course of the injection, so the hot tip keeps sinking into the softening tube top and holds the seal shut as it fills:
// src/libslic3r/Magma/MagmaInjection.cpp -- per extrusion segment k of K
double z = layer_z - (slam_depth + plunge_depth * (k + 1) / K);
// emit: G1 Z<z> (sink the nozzle)
// G1 F<inj_feed> (re-assert injection feedrate; the Z move's feedrate
// must not leak into the stationary extrude)
// G1 X.. Y.. E<seg> (extrude this segment at the injection rate)
The volumetric injection rate is held constant across the plunge (re-asserted after each Z move, since a raw Z move’s feedrate is otherwise sticky). The total depth is clamped so slam + plunge stays within a safe intrusion.
Pressing a round/conical nozzle into a triangular tube opening necessarily displaces material into a raised rim around a central crater (the seal/plunge intrusion), and coats the nozzle in plastic that would otherwise string to the next injection. Crater ironing is a finishing move after each injection that redistributes the rim back into the crater and cleans the nozzle in one motion.
The sequence: (1) a small fixed break-lift cracks the seal before retracting (so retraction can’t pull the plug back up through the still-sealed interface); (2) retract; (3) an inward spiral over the injection centre.
The key mechanism is using the nozzle cone as a plow: with the flat hovering just above layer height and the nozzle positioned outside the rim, the cone’s flank — whose outward normal points (cos theta, -sin theta) = inward and downward — deflects rim material toward the centre and down into the crater as the nozzle spirals in. A flat vertical edge would only push laterally; the cone’s angle is what fills the depression.
crater_r = r_flat + (slam + plunge) * tan(theta) # intrusion footprint radius
start_R = crater_r + margin # begin spiral outside the rim
# Neighbour protection: only PRESS (descend to layer height) inside the radius
# where the flat's outer edge stays >= 0.5 mm short of a neighbour opening's far
# vertex, so a sliver of every neighbour air hole stays open:
D = neighbour-centroid distance (= cell_side / sqrt(3) for the triangle grid)
Ropen= neighbour opening vertex radius (inset triangle -- excludes cell walls)
cap = (D + Ropen) - 0.5 - r_flat
# spiral radius r: shrink start_R -> 0 over `turns` revolutions
# r > cap -> hover at layer_top + hover (never irons a neighbour shut)
# r <= cap -> descend hover -> layer_top (press/iron our own crater)
A short stroke across the centre flattens the gathered mound (only where cap > 0, i.e. the cell has room). The whole pass is non-extruding; the retraction performed at the break-lift keeps it from oozing. Inter-injection travel afterwards uses the slicer’s normal travel path (retraction, z-hop, avoid-crossing). Tunable: turns (cut depth), speed, hover height, and start margin; start radius, neighbour clearance, and the descent profile are derived from the cell and nozzle geometry.
The system supports a dedicated injection filament via magma_injection_filament, following OrcaSlicer’s existing support_filament pattern. This enables using a different material for injection (e.g., a higher-temperature material for stronger reinforcement).
Filament switching is handled upstream by ToolOrdering, which registers the injection filament extruder on layers that have tube caps (injection points). The injection code itself does not perform tool changes – by the time generate_injection_gcode() runs, the current extruder is already the injection filament:
// src/libslic3r/GCode/ToolOrdering.cpp
// Magma injection filament: register on cap layers so ToolOrdering
// schedules the tool change and wipe tower handles the transition.
if (object.config().magma_injection_filament.value > 0) {
if (const auto* tube_map = object.magma_tube_map()) {
unsigned int inj_ext = (unsigned int)object.config().magma_injection_filament.value;
for (int lid : tube_map->injection_layer_ids()) {
LayerTools < = this->tools_for_layer(object.layers()[lid]->print_z);
lt.extruders.push_back(inj_ext);
}
}
}
The configuration parameter uses 1-based indexing (0 = current filament, 1 = filament 1, etc.) matching the support_filament convention. The implementation is fully wired through config definitions (PrintConfig.hpp), UI (Tab.cpp, ConfigManipulation.cpp), preset serialization (Preset.cpp), and extruder collection (Print.cpp). Multi-material hardware testing has not been performed at time of publication, but code review confirms correct integration with the tool change system.
Injection volume is split into per-waypoint G1 E commands proportional to the 3D path segment length. This enables the preview slider to show progressive tube filling:
// src/libslic3r/Magma/MagmaInjection.cpp
double filament_length = volume * e_per_mm3;
if (waypoints.size() >= 2) {
double total_path_len = 0;
for (size_t i = 1; i < waypoints.size(); ++i)
total_path_len += (waypoints[i] - waypoints[i - 1]).norm();
for (size_t i = 1; i < waypoints.size(); ++i) {
double seg_len = (waypoints[i] - waypoints[i - 1]).norm();
double seg_e = (total_path_len > 0)
? filament_length * (seg_len / total_path_len)
: filament_length / double(waypoints.size() - 1);
gcode += gcodegen.writer().extrude_to_xy(
xy, seg_e, "injection segment");
}
}
Each G1 command receives a proportional share of the total extrusion amount, weighted by the 3D distance between consecutive waypoints along the U-tube path. This produces multiple G-code lines for a single stationary injection, each with its own slider position in the preview, enabling visual progressive fill animation.
Interior width and window height are derived rather than dialled in.
The interior width comes from the immersion budget, not from the nozzle bore. The largest
sealable opening is flat + 2 * max_immersion * tan(theta) - margin (Section 7.c above), and
each pattern converts that opening into an interior width through its own inverse of
opening_diameter(), reached polymorphically so no call site carries a shape-specific
formula:
// src/libslic3r/Magma/MagmaGeometry.hpp
// Inverse of opening_diameter(): the interior width whose seal opening is exactly
// `opening`. Auto tube sizing feeds this the largest opening the injection immersion
// budget allows, so the tube comes out as big as the deformation budget permits.
virtual double interior_for_opening(double opening, double line_width) const = 0;
There is deliberately no fallback for an unmeasured nozzle tip flat. An earlier revision defaulted it to three times the bore diameter; this is disclosed here because it is a plausible design and is being dedicated to the public domain, but it was removed as unsound. The flat is a physical property of a specific nozzle that does not track its bore — two 0.6mm nozzles can have visibly different flats — so a guessed value silently mis-sizes every tube in the print. Slicing instead fails with an error naming the setting and describing how to measure it, on the reasoning that a loud stop is cheaper than a part-sized batch of unsealed tubes.
Window height is auto-calculated from tube_area / inset_side (plus one layer height). This
equates the window opening cross-section to the tube interior cross-section, then adds one
layer height so the window reliably spans a full printed layer. The minimum window height is
0.1mm.
When two spatially-adjacent tubes are injected back-to-back, their combined heat can re-melt the thin wall between them and break the seal. The order in which injections are visited on a layer is selectable via magma_injection_ordering:
chain_points()). This is the default.The ordering is computed globally per print layer: all injection points from every object and every instance that fall on the same layer Z are collected and ordered together. A per-object order would be defeated on a plate of small parts, where each part’s tubes would still be injected as a tight cluster. Because injection happens as the last operation on a layer, the global set is well-defined at that point.
The order is solved once, ahead of G-code generation, in a dedicated slicing stage (psMagmaInjectionOrder) and cached by layer Z (the same merged-print_z bucketing OrcaSlicer uses for its per-layer tool ordering), so G-code export performs a lookup rather than a solve.
Decay model. The objective is to keep spatially-near injections far apart in real time. Each prior injection is treated as a heat source that fades with both elapsed time and distance, so the residual heat a candidate point sees is
heat(candidate) = sum over already-injected i of
exp(-dt_i / tau) * exp(-dist(candidate, i) / lambda)
where dt_i is the real elapsed injection time since i was injected, lambda ~ the median nearest-neighbour spacing (heat couples only to the immediate ring), and tau is derived from the layer’s own pace (tau = SEP_TARGET * median per-injection step time, SEP_TARGET ~ 8) so the time scale self-adjusts. dt comes from a real injection-phase timing model – travel distance / travel speed, plus per-injection extrude time (volume / volumetric rate), z-hops, and dwell – so a longer hop to a distant cell is extra cooling, coupling travel and thermal separation instead of opposing them.
Stage 1 – time-decay dispersion greedy. Maintain the residual-heat field over the not-yet-injected points. Starting from the travel-optimal tour’s first point, repeatedly:
heat(c) * exp(-travel_time(cur,c)/tau) plus a small travel tiebreak beta * travel_time(cur,c) so the nozzle prefers nearer cool spots;exp(-step_time/tau);This naturally round-robins across spatial clusters (e.g. instances on a multi-part plate) and stripes across a single dense lattice, while keeping travel bounded.
Stage 2 – violation-directed local-search polish. Hill-climb on a rank-gap proxy of the objective: immediate-ring pairs visited fewer than WINDOW = min(n, 8) injections apart are “crowded”. For each currently-crowded near pair, try swaps that increase its time separation; each swap’s delta touches only the two moved points’ neighbours, so it is O(degree). This dissolves residual clusters the greedy left behind – including end-of-pass “painted-into-a-corner” leftovers – converging to a local optimum.
The whole pipeline is deterministic and runs in O(n^2) (sub-millisecond per layer for typical counts) with no external solver dependency. Very large layers (above a few thousand simultaneous injections) fall back to travel-optimal order.
Alternative formulation (implemented, measured, removed – see git history). The same objective was first expressed and solved exactly as a Hamiltonian-circuit (travelling-salesman) routing problem with an added time-gap heat penalty:
arc[i][j] in {0,1} -- tour edge; rank[i] in [0,n) -- visiting position (MTZ)
minimize sum dist(i,j)*arc[i][j] (travel)
+ sum over near pairs of median_nn * w * max(0, WINDOW - |rank[i]-rank[j]|) (heat)
solved with CP-SAT (OR-Tools), warm-started from the travel-optimal tour (so it is never worse than travel order), over a sparse arc set (each node’s k-nearest neighbours plus the warm-start tour’s edges, guaranteeing a feasible circuit exists), with a distance-tiered penalty (immediately-adjacent pairs weighted 2x) and a short per-layer time budget. This was benchmarked against the greedy+polish pipeline on the real decay objective: warm-started from the polished order it returned the identical order at a multi-second cost, so it was removed from the shipping path. It is disclosed here as prior art alongside the greedy method.
Prior art scope. This disclosure establishes prior art for ordering in-situ mid-print injection events by: (a) a global, cross-object, per-layer schedule rather than per-object; (b) a continuous decay field combining temporal and spatial decay so each past injection’s thermal influence fades in both time and distance; (c) using real elapsed injection time (travel + extrude + z-hop + dwell) as the temporal axis, so inter-injection travel counts as cooling; (d) a dispersion greedy that selects the lowest-heat-on-arrival point with a travel tiebreak; (e) a violation-directed local search refining only currently-crowded near pairs; (f) the equivalent exact formulation as a travel-plus-heat-penalty Hamiltonian circuit solved by constraint programming, warm-started from the travel-optimal tour over a sparse candidate-edge set; and (g) caching the solved per-layer order in a dedicated slicing stage keyed by layer height.
Implementation status: IMPLEMENTED and tested in software.
Tube visualization data is embedded in G-code comments, preserving backward compatibility with G-code processors that do not understand the Magma extensions:
// src/libslic3r/Magma/MagmaInjection.cpp
static std::string format_tube_viz_comment(const std::vector<Vec3d>& waypoints,
float width)
{
std::ostringstream oss;
oss << "; MAGMA_TUBE n=" << waypoints.size() << " w=" << width << " pts=";
for (size_t i = 0; i < waypoints.size(); ++i) {
if (i > 0) oss << ';';
char buf[64];
snprintf(buf, sizeof(buf), "%.3f,%.3f,%.3f",
waypoints[i].x(), waypoints[i].y(), waypoints[i].z());
oss << buf;
}
oss << '\n';
return oss.str();
}
Example output:
; MAGMA_TUBE n=5 w=0.60 pts=1.234,5.678,10.000;1.234,5.678,5.000;2.345,6.789,5.000;2.345,6.789,5.000;2.345,6.789,10.000
The GCodeProcessor parses these comments and expands the single stationary injection extrusion into synthetic vertices tracing the U-tube spiral path: descend through cell A, cross through the window into cell B, ascend through cell B. The sequential slider animates tube filling progressively.
The U-tube spiral path through 3D space is simplified using the Ramer-Douglas-Peucker algorithm (via libigl) to reduce the number of waypoints while preserving the helical shape:
// src/libslic3r/Magma/MagmaInjection.cpp
static std::vector<Vec3d> build_tube_viz_waypoints(
const MagmaTubeMap& tube_map,
const UTubePair& pair,
double layer_z,
int window_center_layer)
{
// ... build full_path tracing descent A -> window -> ascent B ...
if (full_path.size() > 2) {
Eigen::MatrixXd P(full_path.size(), 3);
for (size_t i = 0; i < full_path.size(); ++i)
P.row(i) = full_path[i].transpose();
Eigen::MatrixXd S;
Eigen::VectorXi J;
igl::ramer_douglas_peucker(P, double(iw) * 0.1, S, J);
std::vector<Vec3d> simplified;
simplified.reserve(S.rows());
for (int i = 0; i < S.rows(); ++i)
simplified.push_back(S.row(i).transpose());
return simplified;
}
return full_path;
}
The tolerance is set to interior_width * 0.1, meaning simplification preserves features larger than 10% of the tube diameter. When spirals are disabled, RDP typically reduces 20-120 points down to approximately 5 key points (top of A, bottom of A, window crossing, bottom of B, top of B). With spirals enabled, additional points are retained where the helix curvature is significant.
A dedicated extrusion role erMagmaInjection is added to OrcaSlicer’s role system:
// src/libslic3r/ExtrusionEntity.hpp
erMagmaInjection, // Magma injection extrusion role
This role is rendered in lava-orange color (RGB 255, 25, 0) in the G-code preview:
// src/libvgcode/src/ViewerImpl.cpp
{ 255, 25, 0 }, // MagmaInjection - Molten Lava (brightest)
The dedicated role enables: distinct visual identification of injection extrusions in the preview, separate speed/flow settings for injection vs. normal printing, and correct classification of stationary extrusions (which would otherwise be classified as unretracts).
Three new surface types enable distinct rendering and per-zone settings:
// src/libslic3r/Surface.hpp
// Dual infill zone surface types
stZoneOuter, // Outer zone filled with Magma Triangle U-tube pattern
stZoneFloor, // Zone floor - propagates solid upward into zone
stZoneCeiling, // Zone ceiling - propagates solid downward into zone
With helper methods:
bool is_zone_outer() const { return this->surface_type == stZoneOuter; }
bool is_zone_floor() const { return this->surface_type == stZoneFloor; }
bool is_zone_ceiling() const { return this->surface_type == stZoneCeiling; }
bool is_zone_boundary() const { return is_zone_floor() || is_zone_ceiling(); }
bool is_zone() const { return is_zone_outer() || is_zone_boundary(); }
Zone boundaries are treated as solid surfaces for shell propagation (top/bottom shells propagate through zone boundaries), bridge detection, and overhang support computation.
Implementation status: IMPLEMENTED and tested in software.
The inner shell boundary is computed using OrcaSlicer’s existing SLA generate_interior() function, which was originally designed to hollow SLA (resin) prints for material savings. The system wraps this function with custom zone-specific processing:
// src/libslic3r/ZoneBoundary/ZoneInterior.hpp
// Regenerate mesh from grid after processing
void regenerate_mesh_from_grid(sla::Interior &interior);
// Apply constrained mean curvature smoothing
void smooth_interior(sla::Interior &interior, const TriangleMesh &original_mesh,
int iterations = 5);
// Filter thin sections via morphological reconstruction
void filter_thin_interior(sla::Interior &interior, double min_width);
The SLA hollowing function computes an interior mesh by offsetting the original mesh inward by a specified thickness, using OpenVDB level-set operations. This produces an inner shell mesh that follows the contours of the outer model at a consistent distance, forming the boundary between the outer zone (Magma infill) and the inner zone (standard infill or hollow).
The inner shell boundary undergoes smoothing to reduce stair-step artifacts while maintaining minimum shell thickness:
// src/libslic3r/ZoneBoundary/ZoneInterior.cpp
void smooth_interior(sla::Interior &interior, const TriangleMesh &original_mesh,
int iterations)
{
// Create valid zone grid: original mesh offset inward by thickness
double thickness_offset = interior.thickness;
auto valid_zone_grid = redistance_grid(*original_grid, -thickness_offset,
in_range, in_range);
const int smooth_passes_per_clamp = 5;
// Convergence detection via L1 energy
auto compute_l1_energy = [&]() -> double {
double energy = 0;
for (auto iter = interior.gridptr->cbeginValueOn(); iter; ++iter)
energy += std::abs(iter.getValue());
return energy;
};
double prev_energy = compute_l1_energy();
double prev_rel_change = 0;
for (int i = 0; i < iterations; ++i) {
openvdb::tools::LevelSetFilter<openvdb::FloatGrid> filter(*interior.gridptr);
// Apply multiple smoothing passes before clamping
for (int j = 0; j < smooth_passes_per_clamp; ++j) {
filter.meanCurvature();
}
// Clamp to valid zone using CSG intersection (preserves both inputs)
interior.gridptr = openvdb::tools::csgIntersectionCopy(
*interior.gridptr, *valid_zone_grid);
// Plateau detection
double curr_energy = compute_l1_energy();
double rel_change = (prev_energy > 0)
? std::abs(curr_energy - prev_energy) / prev_energy : 0;
if (i > 0 && prev_rel_change > 0 && rel_change >= 0.5 * prev_rel_change) {
break; // Converged
}
prev_rel_change = rel_change;
prev_energy = curr_energy;
}
}
The algorithm works as follows:
A valid zone grid is created by offsetting the original mesh inward by the shell thickness. This grid represents the boundary that the interior surface must not cross (to maintain minimum shell thickness).
Batched mean curvature passes (5 per iteration) smooth stair-step artifacts. Mean curvature flow shrinks convex bumps inward, which is the desired direction (away from the shell zone).
CSG intersection clamping prevents the smoothed interior from expanding outward into the shell zone. This is applied after each batch of smooth passes.
L1 energy convergence detection measures the total absolute SDF values. When the relative change between iterations plateaus (the change rate stops decreasing), smoothing has reached equilibrium and further iterations are skipped.
The batching strategy (5 smooth passes before clamping) is more effective than alternating single passes because mean curvature primarily shrinks convex features inward, which the clamping constraint does not block. Batching allows more effective smoothing per CSG operation.
Before smoothing, thin inner zone sections are removed using morphological reconstruction:
// src/libslic3r/ZoneBoundary/ZoneInterior.cpp
void filter_thin_interior(sla::Interior &interior, double min_width)
{
float threshold = float(min_width / 2.0 * interior.voxel_scale);
int threshold_voxels = int(std::ceil(threshold));
// 1. Extract thick core (SDF interior at threshold distance from boundary)
auto thick_mask = openvdb::tools::sdfInteriorMask(
*interior.gridptr, -threshold);
// 2. Dilate mask back to reach original surface
openvdb::tools::dilateActiveValues(thick_mask->tree(), threshold_voxels,
openvdb::tools::NN_FACE_EDGE_VERTEX,
openvdb::tools::PRESERVE_TILES);
// 3. Keep original SDF where mask is active, set to outside elsewhere
float background = interior.gridptr->background();
for (auto iter = interior.gridptr->beginValueOn(); iter; ++iter) {
openvdb::Coord coord = iter.getCoord();
if (!thick_mask->tree().isValueOn(coord)) {
iter.setValue(background);
}
}
openvdb::tools::pruneInactive(interior.gridptr->tree());
}
The algorithm is: erode the SDF to find a thick core (regions where the interior is at least min_width/2 from the boundary in all directions), dilate back to the original surface extent, then intersect with the original to keep only regions connected to the thick core. This removes small disconnected islands and thin protrusions that would create unusable infill zones.
Implementation status: These features were designed with detailed specifications. Several have since been implemented and are marked inline — Whirl Seal → Crater Ironing (9.c), Stagger-Level Ordering → thermal-aware ordering (9.d), Hexagonal → Magma Tri-hex (9.b), and Rectilinear (Grid) → Magma Rectilinear (9.f). The remainder (9.a Corner Width Optimization, 9.e Coupled Thermal-Pressure Depth Model) were not implemented for the stated reasons. All are disclosed here for defensive publication purposes to establish prior art.
Design: Increase infill line width near triangle corners to make the tube cross-section more circular, improving injection flow. The implementation would use distance-to-vertex calculation with a blend ratio to smoothly transition from normal line width to enhanced corner width. Per-point width values would be stored in ThickPolylines and rendered using OrcaSlicer’s existing variable_width() extrusion system.
Reason for removal: At Magma cell scales (approximately 1.27mm edge length with a 0.4mm nozzle), width transitions occur in approximately 4.4ms at 100mm/s print speed. However, extruder pressure advance response time is 20-60ms for direct drive extruders. The extruder cannot track flow changes fast enough for the feature to produce meaningful results at these scales. The design is sound for larger cell sizes but impractical for the current target geometry.
Status update: IMPLEMENTED as both Magma Tri-hex and Magma Honeycomb. The pure-hexagon lattice below was the original design. It now ships in two forms: (1) as the Magma Honeycomb pattern (Section 3.h), a direct regular-hexagon tiling whose continuous lane-pair sweep with anisotropic-stretch compensation resolves the print-speed trade-off that originally motivated the hybrid; and (2) as Magma Tri-hex, a hybrid lattice of hexagonal cells plus the triangular cells that tile the gaps between them. Tri-hex uses vent-based injection allocation (a single injection serving multiple connected vents) rather than only pairwise U-tube coupling, and runs on the shared per-shape lattice/solver/injection pipeline (claim 13). Mixing triangular cells between the hexagons recovers the triangular pattern’s continuous line families while keeping the hexagonal cells’ multi-neighbour pairing. The original pure-hex design is retained below for prior art.
How it works (Magma Tri-hex):
Lattice and toolpath. A trihexagonal tiling: hexagon cells (hubs) with up/down triangle cells filling the gaps. It is bipartite – a hex borders only triangles (6), a triangle borders only hexes (3), in a 2:1 triangle:hex ratio. The trihexagonal tiling is the rectified triangular grid, so its walls are exactly the triangular pattern’s three straight line families (0/60/120 degrees) shifted by one-half lattice index in each family. The toolpath is therefore generated by the SAME single-wall line generator as the triangular pattern – three families of full straight lines, clipped to the region and chained per direction into continuous sweeps – with each open hub<->vent window cut as a gap on whichever family carries that shared wall. The one-half-index shift is precisely what opens the hollow hexagons: at the shifted positions no line of any family passes through a hub vertex (integer index) or a vent centroid (thirds), so the hub and vent interiors stay open tubes while every wall lies on exactly one family. This discloses generating a trihexagonal vertical-reinforcement infill as three rectified (half-shifted) straight line families with per-family window interruptions.
Manifold injection unit. One injection fills a manifold: a hub cell over a layer range [start, cap] plus N vent legs, each a triangle cell spanning the SAME [start, cap]. Windows are pinned to the tube bottom, so all legs are equal length; plastic enters each leg at the bottom window, fills up to the cap, and air escapes at the cap (the print surface at injection time). The two-cell U-tube is the degenerate one-leg manifold.
Hub scheduling (reuses the existing solver unchanged). The bipartite hub<->vent adjacency is fed to the same tube-assignment solver (Section 5); ordinary per-cell exclusivity yields a hub<->vent matching that gives every hub-tube exactly one primary leg – which both schedules the hub-tube’s range, stagger, and height and guarantees the hub can inject (air escape).
Vent-fill allocation (maximize filled volume). A second per-vent pass adds further legs to maximize total filled vent volume. For each vent it forms an “unavailable” layer mask – the union of layers where the vent cell is absent due to part geometry AND layers already claimed by the primary matching – and discards any candidate hub-tube whose [start, cap] crosses that mask (a block or prior claim inside the range would trap injected air). The surviving layers split the vent into present-runs; within each run it selects, by weighted interval scheduling over the fully-contained hub-tube ranges, the non-overlapping set covering the most layers (tie-broken toward the least-loaded hub for even distribution), and attaches the vent to those tubes as extra legs. Because hubs are uncapped and each vent layer is filled exactly once, the passes are independent per vent and yield the maximal vent fill achievable with windows aligned to real tube bottoms.
Design (original pure-hex): A modified honeycomb pattern with 6 neighbors per cell, 120-degree corners, adapted for Magma tube formation. Each hexagonal cell would have 6 potential pairing partners, with window placement on any of the 6 shared edges.
Original trade-off (motivating the hybrid form): A pure-hexagon lattice prints more slowly than the triangular pattern due to more direction changes per unit area – the triangular pattern produces 3 sets of parallel lines (0, 60, 120 degrees), each printable in a single continuous sweep, whereas a hexagon perimeter requires more direction changes and shorter segments. The tri-hex form mixes triangular cells between hexagons to recover continuous sweeps.
Status update: This was the original design for a circular nozzle motion around the injection hole. It is now implemented and superseded by Crater Ironing (Section 7.d), which is a spiral (not a single circle) that additionally uses the nozzle cone to plow the displaced rim back into the crater and is neighbour-aware. The original single-circle design is retained below as disclosed prior art.
Design: A circular motion of the nozzle around the injection hole before and/or after injection. The nozzle would trace a circle of radius approximately equal to the interior width, flattening any loose plastic from previous printing operations and ensuring a clean surface for the Z-slam seal to press against. Specification included configurable radius, speed, and number of revolutions.
Status update: Thermal-aware injection ordering is now implemented – see Section 7.h, which orders injections globally per layer to spread spatially-near injections out in time. The stagger-level scheme described below was an earlier design for the same goal (preventing thermal cross-talk between simultaneously-filled neighbours); it is retained here as a disclosed alternative formulation within that family.
Design: Order injection within each layer so that U-tube pairs with the lowest floor (deepest tubes) are filled first. This ensures that deeper tubes solidify before shallower fills, preventing thermal interactions between adjacent tubes being filled simultaneously. The ordering would be: within each stagger level, sort by pair_start_layer ascending; across stagger levels, process the lowest stagger level first.
Why the spatial heat-spread order (6.h) was implemented instead: The stagger-level scheme orders by tube depth and stagger class, which only indirectly correlates with spatial proximity – two tubes at the same stagger level can still be physically adjacent. The implemented order penalises spatial time-proximity directly (and globally across objects), which targets the actual heat-coupling failure more precisely, while the TSP warm start keeps travel close to optimal. The stagger-level variant remains a simpler heuristic of interest for extremely dense single-object tube patterns, and is disclosed for prior-art purposes.
Design: Automatic computation of maximum achievable injection depth using a coupled thermal and pressure model. The tube is modeled as a hollow cylinder with triangular cross-section and equivalent hydraulic diameter.
Thermal constraint: The fill time t_fill = 2 * depth * A_cell / V_dot (U-tube path = 2x depth) must not exceed the freeze time t_freeze = D_h^2 / (4 * alpha) (thermal diffusion across the channel cross-section), where alpha is the thermal diffusivity of the plastic (~0.10 mm^2/s for typical FDM thermoplastics).
Pressure constraint (Hagen-Poiseuille, laminar flow): The pressure drop dP = 32 * mu * L * v / D_h^2 through the U-tube path (L = 2x depth) must not exceed the extruder’s maximum pressure dP_max (~15 MPa for direct-drive). The melt viscosity mu (~50 Pa*s at injection temperature, shear-thinned at ~1000 s^-1) is configurable per material.
Coupled solution: Setting t_fill = fudge * t_freeze and V_dot = V_dot_max simultaneously:
Variables:
A_cell = sqrt(3)/4 * iw^2 -- triangular channel cross-section (mm^2)
P_cell = 3 * iw -- triangular perimeter (mm)
D_h = 4 * A_cell / P_cell -- hydraulic diameter = 0.577 * iw (mm)
alpha = thermal diffusivity of plastic (mm^2/s, configurable)
mu = melt viscosity at injection temp (Pa*s, configurable)
dP_max = extruder max pressure (MPa, configurable)
fudge = tuning factor (configurable, absorbs hardware/material variation)
Coupled depth solution (V_dot drops out):
depth^2 = fudge * dP_max * D_h^4 / (512 * mu * alpha)
depth = D_h^2 * sqrt(fudge * dP_max / (512 * mu * alpha))
Implied injection speed (self-adjusting):
V_dot = dP_max * A_cell * D_h^2 / (64 * mu * depth)
Melt rate cap:
if V_dot > filament_max_volumetric_speed:
recompute depth using thermal-only at capped speed
depth = fudge * V_dot_cap * D_h^2 / (8 * A_cell * alpha)
Optimality: The coupled solution is the global maximum depth. For any injection speed V, achievable depth = min(thermal(V), pressure(V)). Since thermal depth increases with V and pressure depth decreases with V, their intersection maximizes the minimum. No speed choice can produce deeper tubes.
When user specifies injection speed: The system independently computes the thermal limit and pressure limit at that speed and uses the minimum:
depth_thermal = fudge * V_dot * D_h^2 / (8 * A_cell * alpha)
depth_pressure = dP_max * A_cell * D_h^2 / (64 * mu * V_dot)
max_depth = min(depth_thermal, depth_pressure)
Reason for removal: The model was implemented and produced physically reasonable results, but the material parameters (viscosity, thermal diffusivity) vary significantly between filament brands and are not available in standard slicer profiles. Tuning the fudge factor required test prints for each material, which was not practical for a general-purpose tool. The design is retained for future implementation when material databases include thermal/rheological properties, or when a calibration procedure can derive the parameters from test prints.
Prior art scope: This disclosure establishes prior art for: (a) using coupled Hagen-Poiseuille pressure and thermal diffusion models to automatically compute injection tube depth limits, (b) the mathematical property that volumetric speed drops out of the coupled solution, yielding a depth that depends only on geometry and material properties, (c) automatic injection speed derivation from the coupled solution, and (d) configurable material parameters (viscosity, thermal diffusivity, extruder pressure) for per-filament injection optimization.
Status update: IMPLEMENTED as Magma Rectilinear. Now shipping as a selectable pattern (square cells, two perpendicular single-wall line families, a window omitted from a shared edge). The original design and trade-off discussion below are retained for prior art.
Design: A grid lattice in which two families of parallel infill lines at 0 and 90 degrees form square (or, with unequal spacing, rectangular) cells. Each cell is a vertical channel with a square cross-section. As with the triangular pattern, cell spacing is derived from the nozzle and interior-width geometry, each cell is paired with an orthogonally adjacent neighbor sharing a wall, and a window gap omitted from the shared wall connects the pair into a U-tube. Stagger levels, spiral interlock, and per-layer volume computation apply directly, substituting the square-cell geometry (cross-section iw^2, perimeter 4 * iw, hydraulic diameter iw) into the same formulas. A 45-degree-rotated variant produces diamond cells with injection holes offset between layers.
Advantages: The two line families are long, continuous, orthogonal sweeps that print quickly with minimal direction changes (matching the speed characteristics of standard rectilinear/grid infill). The square cross-section presents a large flat sealing area and is straightforward to model and size.
Trade-offs vs. triangle: Square cells have 90-degree interior corners, which give somewhat poorer injection flow and are a little harder for a round nozzle to seal than the 120-degree corners of the triangular pattern; for equal wall material the grid produces fewer reinforcing tubes per unit area, and window placement is limited to the 4 cell edges. The triangular pattern remains the default for those reasons, but rectilinear is offered as an option where its long, continuous orthogonal sweeps and large flat sealing face are preferred.
Prior art scope: This disclosure establishes prior art for square-, rectangular-, and diamond-cross-section channel variants of the Magma tube system, including orthogonal grid cell pairing, window placement on grid cell edges, and the application of stagger, spiral interlock, and volume computation to grid-based Magma channels.
Implementation status: SPECULATIVE. These concepts are disclosed for broader defensive coverage. None have been implemented or tested. They represent reasonable extensions of the disclosed system that a person skilled in the art might pursue.
The Magma tube system could be extended to non-planar printing (curved-layer FFF) where the Z-height varies continuously across each layer. In this embodiment:
Beyond U-tube pairs, the channel network could employ:
The injection channels could be filled with materials other than the same thermoplastic used for printing:
A variant where the part consists primarily of form-following shells with injection channels between them, designed for curved or sloped surfaces where planar infill is inefficient. The shells would follow the part’s contour at varying offsets, with channels running between adjacent shells. This mode would be particularly effective for thin-walled parts, aerodynamic surfaces, and enclosures where the structural load follows the surface geometry.
Variable-density tube patterns where cell size varies across the part based on:
This document, and the concepts, methods, algorithms, data structures and embodiments it describes, are dedicated to the Public Domain under the Creative Commons CC0 1.0 Universal dedication.
This dedication covers the disclosure and the techniques, not the source code. The implementing code is a derivative work of OrcaSlicer and is necessarily licensed AGPL-3.0, inherited from upstream — see Source Code Availability. The two are independent: the AGPL governs copying the particular implementation, while the CC0 dedication and this disclosure’s prior-art effect place the underlying techniques beyond patenting by anyone, including the author.
To the extent possible under law, the author has waived all copyright and related or neighboring rights to this work. This work is published from the United States.
Full text of the CC0 dedication: https://creativecommons.org/publicdomain/zero/1.0/
This document serves as a Defensive Publication. The concepts, methods, algorithms and structures described herein are disclosed publicly to establish Prior Art, so that they cannot be patented by anyone.
Operative date. Everything in Sections 1-12 became publicly accessible on May 6, 2026, when this file was published in a public repository. That is the date from which the disclosure has prior-art effect. The authorship dates below record when each part was written; they are offered as history, not as evidence, and nothing here depends on them.
| Written | Material |
|---|---|
| Feb 9, 2026 | Sections 1-4 and 6-12 as originally drafted |
| Mar 16, 2026 | Section 5, Optimized Tube Assignment (two-stage solver) |
| Jun 23, 2026 | Multi-pattern lattice abstraction (Rectilinear, Tri-hex); dual cell-presence gate; per-tube actual-opening sealing model (claim 9); clipped-cavity centroid injection point (claims 13-15) |
| Jun 25, 2026 | Magma Honeycomb with continuous-sweep doubled-wall compensation (§3.h); measured injection volume from deposited toolpath (§4.g); self-scaling overlap compensation (§4.h) — claims 17-19 |
| Aug 17, 2026 | Heat-spread injection ordering (claim 10); progressive plunge (claim 11); crater ironing (claim 12); manifold injection with vent allocation (claim 16) |
| Aug 25, 2026 | Addendum A (superseded mechanisms) and Addendum B (further disclosure) |
Every numbered claim in Section 1 is covered by one of the rows above. An earlier revision of this section left the August 17 material undated and mislabelled the June 23 group; both are corrected here.
On scope. The list below indexes the subject matter this disclosure covers. It is an index into the body, not a claim set — a defensive publication anticipates what it actually describes and nothing more, so no “including but not limited to” language is used or intended. Whether any particular later application is anticipated is for an examiner or a court to decide against specific claims; this document simply puts the material in the public record on a fixed date.
Subject matter disclosed:
The complete source code implementing the IMPLEMENTED portions of this disclosure is public at
https://github.com/MGunlogson/OrcaSlicer (branch magma-infill).
It is licensed AGPL-3.0, inherited from OrcaSlicer, of which it is a derivative work. It cannot be CC0-dedicated, and an earlier revision of this section wrongly stated that it was. The techniques the code implements are dedicated to the public domain by this disclosure; the code itself carries upstream’s copyleft.
The disclosure above is unchanged from publication. This addendum records which of its mechanisms test prints have since superseded, so nobody implements a model its own author abandoned. Everything disclosed stays dedicated to the public domain either way. The point of the disclosure is that none of it can be enclosed by anyone.
Each entry below names the sections it applies to. An earlier version of this addendum did not, which left a reader no way to tell which passages above were still live. Entries A.6 through A.10 were added after an audit of the body against the shipping source, and cover drift the first version of this addendum missed entirely.
Applies to: Section 7.c (Z-Slam Sealing), Section 7.g (Auto-Sizing), and claim 9 in the Section 1 abstract.
Those sections describe a user-facing nozzle-immersion budget (magma_max_immersion), the
inversion of that budget to size the printed channel (magma_tube_width_mode = Auto), and
the auto slam press (magma_auto_slam_press). That design shipped and was then replaced.
All three settings no longer exist.
Section 7.g is superseded in whole: there is no auto-sizing path at all. Tube interior width is
now a plain user setting, and max_opening_for_immersion() survives in the source only as
uncalled dead code. Claim 9’s formula in the abstract carries a margin term that no longer
exists.
The model had the causality backwards. Immersion is what damages the part, so making it the input and deriving the tube from it left channel width, the thing a user actually wants, as a side effect. It also coupled the plunge to the tube, so pressing harder during an injection silently narrowed the channel it was sealing.
The current model takes tube interior width as the input:
seal depth = (opening - nozzle flat) / (2 * tan(cone half-angle)) + seal press
total depth = seal depth + plunge depth
corner grip = (seal press + plunge depth) * tan(cone half-angle)
There is no margin term; the earlier MAGMA_SEAL_MARGIN constant no longer exists. Seal press
and plunge are the same physical quantity — depth past first contact — applied before and
during the injection respectively.
Applies to: the project’s tuning guidance and slicer warnings, not to this document. An audit found no passage in Sections 1-12 that states this claim; it lived in the project’s calibration notes and in a slicer validation warning. The retraction is recorded here anyway so the public record is complete, and because the ratio still appears in the implementation.
The claim was that the nozzle cone widening past one cell pitch is the mechanism that distorts the surrounding lattice. Measured print evidence contradicts this in both directions: a sweep reached 135% of cell pitch with no lattice disruption, while another degraded at 106%.
The measurement behind the ceiling came from a sweep in which immersion sized the tube, so what varied across it was the channel and its injected volume rather than the cone. The damage was real and the attributed cause was wrong. The ratio survives in the implementation only as a geometric sanity bound.
Applies to: Section 1.1, which states this as a headline empirical finding, and to Section 7.b (Injection Speed and Volume). Note that Section 1.1 is the section this project’s README links to directly, so this correction matters more than its length suggests.
The disclosure states that at same-material injection the seal, rather than flow, is the binding constraint. Testing puts the binding constraint elsewhere: the duration of a single injection. Roughly 1.5 s or less prints cleanly, about 2 s begins to deform the lattice, and 3 s destroys the cells around the injection point. Since injection runs at the filament’s maximum volumetric rate, injection time is set by volume per tube, and therefore by channel width and tube height.
The mechanism behind that limit is not established. Two explanations fit every result and no test has separated them: the nozzle acting as a heat source for as long as it is sealed into a cell, or the melt freezing partway down the channel so backpressure forces it back out past the seal. Both worsen with duration. This is an open question, not a claim.
One approach that does not work, recorded so others do not spend prints on it: splitting a long injection into shorter bursts to let the walls cool between them. The melt solidifies into a plug and the rest of the injection has nowhere to go.
Applies to: Section 7.c, which frames a wide flat as the easy case needing only a token press, and to the tuning guidance that accompanied it.
The disclosure and its accompanying documentation suggested that a larger nozzle tip flat would help seal larger or taller channels. The opposite is the case, and this is the most consequential correction here.
The flat sets the minimum cell size that can be sealed reliably, because seal depth is governed by how much wider the cell is than the flat, and below roughly 0.4 mm of engagement the seal does not survive the unevenness of a printed rim. A smaller flat therefore permits smaller cells. Since each injection is bounded by duration rather than size, many small channels deliver more injected material than a few large ones.
Lattice generation, U-tube pairing and window placement, the tube-assignment solver, per-layer injection scheduling and heat-spreading order, the measured-cavity volume calculation, crater ironing and the progressive plunge during injection are all as disclosed. Every formula in Sections 5, 7.d and 9 was re-verified against the shipping source and matches.
Two corrections to the previous version of this entry. Safe parking was listed here as “unchanged”, but it was never actually described anywhere in the body — it appears only as a claim heading and an index item. It is disclosed properly in Addendum B.4. And Magma Honeycomb (Section 3.h) has a known failure mode not recorded above: on the one plate that tested it, it sealed poorly, most likely because each vertical wall is drawn as two adjacent beads, so the seam between them runs the full height of the tube. The sweep geometry is as disclosed; the sealing behaviour is worse than the disclosure implies.
Section 7.c documents a user-facing slam depth, magma_injection_z_slam, with a default of
0.05 mm, a 3.5 mm clamp, a code sample and a paragraph of tuning advice. No such setting has
ever existed in the shipping slicer. Seal depth is derived per tube from that tube’s own
measured cap opening; the only related knob is magma_seal_press. A reader following that
passage would tune a setting that is not there, toward a value eight times below the 0.40 mm
seal-depth floor established in A.4.
Section 7.c also contradicts itself: it states the depth is user-configurable, then states twenty-eight lines later that “there is no user-facing manual depth”. The second statement is the correct one.
Renamed since publication, with no change in substance: auto_slam_depth(opening, flat, cone,
max_immersion, press) is now auto_seal_depth(opening, flat, cone, seal_press) — four
arguments, no budget clamp. The clamp moved to a separate clamp_plunge_depth(). The
MAGMA_SEAL_MARGIN constant is gone.
Section 8.d and the abstract refer to a stZoneOuter surface type and an is_zone_outer()
helper. Both were removed; the outer zone is now identified as ordinary internal surface gated
on the presence of a zone boundary.
Section 8 is superseded in whole. Three specifics, because the section is detailed enough that someone could try to build from it:
MAGMA_TUBE comment carries a single
width and a flat point list. The shipping format carries a per-line count list and a per-point
width, and the parser returns immediately if the count list is absent. The documented format
would parse to nothing.build_tube_viz_waypoints() does
not exist, and Douglas-Peucker is explicitly wrong for this purpose — it collapses a straight
tube to its endpoints, which cannot animate. The shipping code subsamples to a fixed budget,
keeping evenly spaced intermediate points. Douglas-Peucker survives only on the crater-ironing
spiral, a different feature.Section 5.c documents a W_LENGTH tiebreaker said to prefer fewer, longer tubes. No such term
exists, and a linear length bonus cannot produce that preference: rewarding total covered length
scores one long tube and two half-length tubes identically. The shipping objective instead
charges a fixed activation cost per active tube segment, which makes one long tube strictly
cheaper than two short ones. The published term is not merely renamed; it could not have worked.
Section 7.b gives magma_injection_speed a default of 10 mm³/s. The default is 0, and 0
does not mean “no speed” — it means the filament’s maximum volumetric rate. The code sample in
that section would treat 0 as 1 mm³/s. Since slowing an injection is the single most damaging
change available (it lengthens the injection, which A.3 identifies as the binding constraint), a
reader implementing the published snippet gets the worst case rather than the intended one.
Section 7.b gives magma_tube_height a default of 4.5 mm. The default is 3.5 mm, chosen
because at the default tube width in PLA a 4.0 mm tube already exceeds the 1.5 s injection
ceiling. The published default violates this document’s own corrected guidance.
Section 7.h describes travel-minimising injection order as the default. The default is heat-spread ordering. The rest of Section 7.h is accurate.
None of these change a mechanism’s substance, but each would mislead someone reading the body as a specification:
Section 10 is titled “DESIGNED (SOME SINCE IMPLEMENTED)”. Its opening paragraph and each subsection’s status note do resolve which is which, so a careful reader is not misled. But two things sit under that heading that are neither designed-only nor superseded:
Both are disclosed as implemented for the avoidance of doubt.
Section 3’s header states that “all code excerpts are from the working implementation”. That is not true of Sections 3.b, 3.e and 4.f, each of which presents a superseded approach. Each carries its own accurate inline note, so the error is in the chapter header’s scope rather than in the subsections themselves.
Addendum A corrects the record. This addendum adds to it.
Auditing the body against the shipping source turned up mechanisms that are implemented, user-visible and absent from Sections 1-12. Two of them are the most load-bearing safety features the system has. They are disclosed here so they are covered by the same public-domain dedication as everything above, and so no one can enclose them. This extends the subject-matter index in Section 12.
The system computes, before printing, quantities that can only otherwise be discovered by ruining a print, and blocks or warns on them.
Prior art is established for deriving predicted in-situ injection duration from measured channel cavity volume and the filament’s maximum volumetric rate, and gating slicing on it; and for deriving a minimum nozzle-to-channel sealing engagement from nozzle cone geometry and channel opening, and gating slicing on it. Also disclosed: presenting both quantities as live readouts in the slicer’s settings interface, computed through the same resolver that emits the G-code, so the displayed value and the printed behaviour cannot drift apart.
Section 4.g discloses measuring the injectable cavity exactly. The shipping system then multiplies that measurement by a user-facing fill factor, default 0.9, and injects the reduced quantity. Measuring precisely and then deliberately under-filling is not an obvious combination — the reason is that a channel filled to its exact measured volume has nowhere to put thermal expansion or trapped air, and over-injection escapes past the seal. Prior art is established for scaling a measured in-situ channel dose by a user-controlled factor below unity.
Injection is bracketed by markers that override part-cooling fan speed for the duration of the injection and restore it afterwards, independently of the fan speed used for printing. Part cooling works against an injection: the melt must stay fluid long enough to reach the bottom of the channel and back up its partner. Prior art is established for overriding part-cooling fan speed for the duration of an in-situ injection within a layer, as a distinct fan regime from the one used for the surrounding printed material.
Claim 8 in the abstract names this and no section described it. Disclosed here.
When the nozzle must change temperature for injection, it cannot remain over the part — it would ooze onto the surface. The system selects a parking position by descending a tier list, taking the first that is available and reachable: positions outside the printed object but within the object’s own footprint region; positions elsewhere on the build plate clear of all objects and their skirts; a wipe tower or purge structure if one exists; a plate-edge position; and finally a fixed fallback. Selection accounts for other objects and instances on the plate, so a plate that is full does not silently park over a neighbour. Prior art is established for tiered fallback selection of a nozzle parking position during an in-print temperature change, ordered by proximity cost and validated against all objects on the build plate.
Section 7.a relies on injection being the final operation of the layer it belongs to. What makes that true is a distinct step: after tool ordering is computed, the injecting tool is rotated to the end of each cap layer’s extruder sequence. Without it the injecting tool could be scheduled mid-layer and subsequent printing would run over a freshly injected, still-soft cell top. Prior art is established for constraining the per-layer tool order so that the tool performing in-situ injection is scheduled last on any layer containing an injection.
Disclosed for completeness; each is implemented: