Releases: jgphilpott/polyslice
v26.4.0
First release of April 2026, covering PR #189 merged since v26.3.1.
Version
package.json: 26.3.1 → 26.4.0
CHANGELOG highlights
Added
- Configurable
supportGap(PR #189) — shared by normal and tree support; replaces the previously hardcodednozzleDiameter / 2lateral gap. Default0.2mm preserves existing behaviour. - Configurable
supportDensity(PR #189) — normal support grid density as a percentage (0–100). Default50matches the previously hardcoded spacing equivalent;0short-circuits to no support lines. - Configurable
supportRootsEnabled(PR #189) — boolean toggle for tree-support root structures. Defaulttrue. - Configurable
supportRootCount(PR #189) — number of radial roots at the trunk base (1–8). Default4. - Configurable
supportBranchAngle(PR #189) — angle (degrees, (0°, 90°)) of branches rising from the trunk. Default45. - Configurable
supportTwigAngle(PR #189) — angle (degrees, (0°, 90°)) of twigs rising from branch nodes to contact tips. Default45.
All six options default to the values previously hardcoded, so no existing behaviour is affected.
v26.3.1
Second release of March 2026, covering 4 PRs (#184–#187) merged since v26.3.0.
Version
package.json: 26.3.0 → 26.3.1
CHANGELOG highlights
Added
- Visualizer: Persist folder states (#184) —
saveFolderStates/loadFolderStatesinstate.js;trackFolderhelper avoids private lil-gui internals; cleared on full reset - Visualizer: Reset icon UX (#184) — confirm prompt + one-shot
@keyframes spin-oncewithanimationendcleanup - Visualizer: Build-plate-centered model positioning (#185) —
positionMeshOnBuildPlate()called on load, rotation drag-end, and printer change;getBuildPlateDimensions()with localStorage + preset table fallback;updateBuildVolume()rebuilds axes/grid in-place preserving event listeners
Fixed
- G-code metadata version always
"Unknown"(#186) —require('../../package.json')→require('../../../package.json')incoders.coffee; metadata test now asserts actualpkg.version - Dome zenith skin infill suppressed (#187) — even-odd nesting-parity check in
findCoveredRegions(cavity.coffee) skips candidates whose bbox centre has odd containment count (i.e. hole paths); preserves lego-stud detection from #182
v26.3.0
First release of March 2026, covering 19 PRs (#164–#182) merged since v26.2.2.
Version
package.json:26.2.2→26.3.0
CHANGELOG highlights
Added
- Tree support roots (#178) — 45° root structures for base stability; broadened ray-cast (
ROOT_RAY_SAMPLE_FRACTIONS) for curved surfaces; hanging roots suppressed ineverywheremode - Sequential wall printing for nested objects (#170) — outer-to-inner level ordering with nearest-neighbour within each level
Changed
- Lightning infill (#169) — asymmetric fork positions (35–45% / 55–65%) + zig-zag kinks via
addKinkedLine - Tree support cross-sections (#172) — circular O+X shape, size varies by type, single shared trunk segment, translation-independent clustering
- Raft per-region separation (#176) — independent raft per contact region; default margin 5mm → 3mm;
edgeEpsilon = 0.001for boundary float imprecision
Fixed
- Gizmo visibility on first model click (#164)
- Smart wipe never activating (
_meshBoundsvsmeshBounds) (#165) - Inverted pyramid covered-region detection (below-case in
findCoveredRegions) (#166) - Concentric infill bleeding into holes (edge-by-edge
clipLineWithHoles) (#167) - String setters silently ignoring valid mixed-case input (
setSupportPlacement,setSpeedUnit, etc.) (#168) - Nested object middle layers spuriously getting skin (#171)
- Oversized covered-area skin wall exclusion gap (should be
infillGap, notnozzleDiameter) (#173) - Test suite broken by
three-mesh-bvh@0.9.9circular reference; replacedthree-bvh-csgwithExtrudeGeometry(#174) - Sphere poles generating full-circle skin (raised
candidateRatio0.9→0.97, filter threshold 0.9→0.99) (#175) - Orphaned tree twig segments; weak twig/branch joint (
TWIG_OVERLAP_LAYERS = 1) (#177) - Lego brick non-parallel skin lines — removed separate Phase 1 skin wall section; explicit G0 correction after combing (#179)
- Tree support trunk relocation false-negative on upright arch/dome (
maxZ-awareisTrunkAccessible) (#180) - Sibling nested structures not printing sequentially (precomputed
directChildHolesOf/directChildStructuresOf) (#181) - Small covered regions (~2% area, e.g. lego studs) failing detection — removed 10% lower bound from
findCoveredRegions(#182)
v26.2.2
Release v26.2.2 — 2026-02-27
Second release of February's second half. This release is heavy on correctness fixes — particularly for complex geometry (sideways dome, flipped arch) — plus a full tree support implementation and a significantly expanded visualizer.
New Features
Tree Support Type (#151)
A fully functional tree support algorithm is now available as an alternative to the normal grid supports:
- Convergence algorithm: dense contact points near the overhang naturally thin into sparse trunk columns toward the build plate
- Two zones determined per-point via barycentric interpolation of the overhang face Z:
- Branch zone (within 8mm of overhang): fine 1.5× nozzle spacing
- Trunk zone (>8mm from overhang): coarse 4× nozzle spacing with convergence snapping
- Uses less material and produces smaller contact footprints for easier post-print removal
- Enable with
supportType: 'tree'
Visualizer: Extended Slicer Settings (#159)
The Slicer panel in the visualizer now exposes the full set of slicing options:
- Adhesion: type selector + all skirt / brim / raft settings
- Support: type, placement, and threshold
- Temperatures: nozzle and bed temperature sliders
- Fan speed slider
- Shell: wall and skin thickness controls (moved to top of the section)
- All 7 infill patterns now selectable in the GUI
Visualizer: Model Rotation Controls (#162)
A new Model Rotation folder in the Slicer panel:
- X / Y / Z sliders (−180° to +180°, 1° steps), persisted to localStorage
- Three.js
TransformControlsgizmo: click a mesh to attach arc handles, drag to rotate, click off to dismiss OrbitControlspaused automatically during gizmo drag to prevent conflicts- Bidirectional sync between sliders and gizmo
Improvements
- Adhesion examples expanded —
slice-adhesion.jsnow demonstrates all 4 adhesion types against cube, cylinder, torus, and arch geometries (#150) - Visualizer camera — camera no longer refocuses on every file upload; only on the first upload per type (model or G-code), and resets when Slice is clicked (#159)
- Visualizer sliders — numeric sliders use
onFinishChangeto avoid excessive localStorage writes while dragging (#159) - Visualizer layout —
AdhesionandSupportfolders collapsed by default (#162)
Bug Fixes
Support Generation
| PR | Fix |
|---|---|
| #148 | Support no longer generated on layer 0 when solid geometry blocks the position (<= blocking check) |
| #148 | everywhere mode: for i in [1..0] CoffeeScript pitfall guarded when layersToCheck = 0 |
| #148 | Spurious ; TYPE: SUPPORT comments no longer emitted when all candidate points are blocked |
| #149 | Barycentric isPointInSupportWedge check restricts fill to the actual overhang wedge, preventing support on the wrong side of slanted surfaces |
Wall / Infill / Skin Geometry
| PR | Fix |
|---|---|
| #152 | WALL-INNER and FILL/SKIN now generated on all layers with C-shaped cross-sections (sideways dome was missing both on 41 + 33 layers respectively) |
| #153 | clipLineToPolygon epsilon reduced 0.3 → 0.001; skin and infill lines no longer cross the inner wall boundary on circular cross-sections |
| #153 | Redundant G0 travel commands removed when nozzle is already at the infill start point |
| #154 | Cavity detection no longer mistakes arch structural columns for interior cavity features, eliminating spurious skin walls on flipped arch layers 22–25 |
| #155 | Regression tests tightened (±0.5mm → ±0.05mm) confirming regular infill also stays within wall boundary |
| #156 | numLinesUp now computed from boundary corner extents relative to pattern center; fixes missing infill with infillPatternCentering: 'global' in grid, triangles, and spiral patterns |
| #158 | createInsetPath backtracking-vertex removal replaced with O(n) index-scan loop handling cascading near-reversal vertices (fixes jagged inner wall spikes at arc-rectangle junctions) |
| #160 | createInsetPath now applies removeBacktrackingVertices as a post-processing pass on its output, fixing wall endpoints extending past expected positions at concave arc junctions |
| #161 | generateSkinGCode pre-checks infill boundary feasibility before emitting ; TYPE: SKIN, eliminating degenerate skin-wall-only blocks on narrow ribbon polygon layers (sideways dome layers 14–18 and 108–112) |
PRs in This Release
#148 · #149 · #150 · #151 · #152 · #153 · #154 · #155 · #156 · #158 · #159 · #160 · #161 · #162
v26.2.1
Release v26.2.1
Release Date: February 19, 2026
Second release of February 2026, addressing critical support generation improvements.
Highlights
🏗️ Complete Support Generation Overhaul - Revamped support generation with face-based grouping and modular architecture for better coverage, density, and maintainability.
🔧 Fixed Over-Extrusion - Support structures now use correct line width, making them 25% easier to remove.
🎨 Improved Visualizer Support - TYPE comments now added on every layer for proper color coding in G-code visualizers.
Support Generation Architecture
Sub-Module Organization
The support generation system has been reorganized into a clean, maintainable architecture:
src/slicer/support/
├── support.coffee # Main dispatcher + shared utilities
├── support.test.coffee # 19 integration tests
├── normal/
│ ├── normal.coffee # Grid-based support implementation (499 lines)
│ └── normal.test.coffee # 5 focused tests
└── tree/
├── tree.coffee # Tree support template (future)
└── tree.test.coffee # 2 placeholder tests
Benefits:
- Clean separation - Main module delegates all operations to specialized sub-modules
- No duplication - 640 lines of duplicate code removed
- Extensible - Easy to add new support types (tree, organic, etc.)
- Maintainable - Focused modules with single responsibility
- Well-tested - 26 total tests (19 main + 5 normal + 2 tree)
Dispatcher Pattern
The main support.coffee module acts as a dispatcher:
# Import specialized sub-modules
normalSupportModule = require('./normal/normal.coffee')
# Delegate based on support type
generateSupport: (slicer, ...) ->
switch slicer.getSupportType()
when 'normal'
normalSupportModule.generateSupport(slicer, ...)
when 'tree'
# Future: tree support implementation
else
# Validation errorOnly shared utilities remain in the main module:
buildLayerSolidRegions()- Caches solid geometry for collision detection- Cache management for
_overhangFaces,_supportRegions,_layerSolidRegions
Support Algorithm Improvements
Face-Based Grouping
Old Approach (Point-Based):
- Detected overhang face centers as isolated points
- Generated separate support column for each point
- Ignored face area (only center mattered)
- Result: Arch had 50 separate structures, dome had 376 overlapping pillars
New Approach (Face-Based):
- Stores complete face data (all 3 vertices)
- Groups adjacent faces that share edges (union-find algorithm)
- Calculates collective bounding box from all vertices
- Generates coordinated grid pattern covering entire grouped area
- Result: Arch has 1-2 unified regions, dome has coordinated structure
Edge Matching Algorithm
edgesMatch: (v1a, v1b, v2a, v2b, tolerance = 0.001) ->
# Check if two edges share the same vertices
# Works in both directions (forward and reverse)
# 0.001mm tolerance for floating-point precisionUnion-Find Grouping
# Initialize each face in its own group
parent = {}
for i in [0...faces.length]
parent[i] = i
# Find all adjacent pairs and union them
for i in [0...faces.length]
for j in [i+1...faces.length]
if facesAreAdjacent(faces[i], faces[j])
union(i, j)
# Group faces by root parent
groups = {}
for i in [0...faces.length]
root = find(i)
groups[root].push(faces[i])Coordinated Grid Patterns
For each grouped region:
- Calculate collective bounding box (minX, maxX, minY, maxY)
- Apply support gap (
nozzleDiameter / 2) to prevent overlap - Generate grid points at
supportSpacingintervals (2× nozzle diameter) - Alternate X/Y direction per layer (even layers: horizontal, odd: vertical)
- Check collision for each point (even-odd winding rule)
- Group valid points into continuous lines
- Generate G-code with proper extrusion
Critical Fixes
1. Support Extrusion Calculation
Problem:
# Old code - used full nozzle diameter
extrusionDelta = slicer.calculateExtrusion(distance, nozzleDiameter)
# Result: 25% over-extrusion, difficult to removeFix:
# New code - uses support line width
supportLineWidth = nozzleDiameter * 0.8 # Thinner for easier removal
extrusionDelta = slicer.calculateExtrusion(distance, supportLineWidth)
# Result: Correct material flow, easy removalImpact:
- Eliminates 25% over-extrusion in all support structures
- Supports are easier to remove as designed
- Better surface quality on supported areas
2. Support Coverage
Arch Geometry (Upright):
- Old: 50 overhang face centers → 50 isolated pillars
- New: Adjacent bottom faces grouped → 1-2 unified regions → complete coverage
Dome Geometry (Upright):
- Old: 376 face centers → 376 overlapping pillars
- New: Connected faces pooled → fewer coordinated regions → no redundancy
3. Support Visualization
Problem: TYPE comments only added on first layer
G1 X10 Y10 E0.5 F1200 ; Layer 0 - has TYPE comment
G1 X10 Y10 E0.5 F1200 ; Layer 1 - no TYPE comment (wrong)Fix: TYPE comments added on every layer
; TYPE: SUPPORT ; Layer 0
G1 X10 Y10 E0.5 F1200
; TYPE: SUPPORT ; Layer 1
G1 X10 Y10 E0.5 F1200Impact:
- G-code visualizers can properly color-code support structures
- Consistent with other feature type annotations (WALL-OUTER, SKIN, FILL)
4. Support Gap
Problem: Supports generated too close to printed part
# Old code - no gap, used full bounds
grid covers: [minX, maxX] × [minY, maxY]Fix: Added proper clearance gap
supportGap = nozzleDiameter / 2 # e.g., 0.2mm with 0.4mm nozzle
minX = region.minX + supportGap # Shrink inward
maxX = region.maxX - supportGap # Shrink inward
# Grid covers smaller area with gapImpact:
- Prevents support from adhering to printed part
- Easier support removal
- Better surface quality
- Follows same gap convention as infill
Code Quality Improvements
Dead Code Removal
Removed:
- 640 lines of duplicate code from main
support.coffee - Never-called
clusterOverhangRegions()method - Old point-based clustering implementation
- Outdated region merging logic
Result:
- Main module: 151 lines (down from ~800 lines)
- Clear single responsibility per module
- Easier to understand and maintain
Test Coverage
All 26 support tests passing:
- 19 main tests - Integration testing of support generation
- 5 normal tests - Face grouping, edge matching, grid patterns
- 2 tree tests - Template placeholders for future implementation
Full test suite: 747 tests passing across 38 test suites
Breaking Changes
None. This release is fully backward compatible with v26.2.0.
Upgrade Guide
From v26.2.0
No code changes required. Simply update your package:
npm install @jgphilpott/polyslice@26.2.1Support generation will automatically benefit from:
- Better coverage (face-based grouping)
- Easier removal (correct extrusion)
- Improved visualization (TYPE comments)
Configuration
All existing support configuration options remain unchanged:
const slicer = new Polyslice({
supportEnabled: true,
supportType: 'normal', // Only 'normal' implemented
supportPlacement: 'buildPlate', // or 'everywhere'
supportThreshold: 45 // degrees
});Performance Impact
Memory:
- Similar memory usage (face data vs point data)
- Additional caching for grouped regions (minimal overhead)
Speed:
- Face grouping: O(n²) edge comparisons, but n is typically small (< 1000 faces)
- Grid generation: Same complexity, more efficient paths
- Overall: Negligible impact on slicing time
G-code Size:
- Similar or slightly smaller (coordinated patterns vs isolated pillars)
- Better travel paths reduce total G-code size
Known Limitations
Tree Support
Tree support type is defined but not yet implemented:
// Will be implemented in future release
const slicer = new Polyslice({
supportType: 'tree' // NOT YET IMPLEMENTED
});Current status:
- Template module created (
tree/tree.coffee) - Placeholder tests added (
tree.test.coffee) - Will be implemented in future release
Support Types
Currently supported types:
- ✅ normal - Grid-based support with face grouping
- ❌ tree - Tree-like branching (planned)
- ❌ organic - Smooth organic supports (future consideration)
Migration from Older Versions
From v26.1.x
Update package.json:
{
"dependencies": {
"@jgphilpott/polyslice": "^26.2.1"
}
}Run:
npm update @jgphilpott/polysliceReview the CHANGELOG for all changes between v26.1.x and v26.2.1.
Documentation Updates
Updated Files
CHANGELOG.md- Added v26.2.1 release notes.github/instructions/slicer/support/overview.instructions.md- Updated architecture docsdocs/slicer/support/SUPPORT.md- Updated support generation guide
New Documentation
All documentation now reflects the sub-module architecture and face-based grouping algorithm.
Testing
Pre-Release Validation
All checks passed:
- ✅
npm run compile- CoffeeScript compilation successful - ✅
npm test- All 747 tests passing (38 suites) - ✅
npm run build- All distributions built successfully - ✅
npm run lint- Code s...
v26.2.0
Release v26.2.0 - February 2026
Release Date: February 14, 2026
Previous Release: v26.1.2 (January 28, 2026)
🎉 Highlights
This release brings major infill pattern improvements to Polyslice! We've added four new infill patterns, fixed critical issues with existing patterns, and introduced a new pattern centering system for better control over infill placement.
Key Improvements
- 4 New Infill Patterns: Concentric, Gyroid, Spiral, and Lightning
- Gyroid Pattern Completely Revised: Single rotating direction for better performance and layer adhesion
- Concentric Pattern Fixed: Proper wall gaps and hole detection
- Pattern Centering Control: Choose between object-centered or globally-centered patterns
✨ New Features
New Infill Patterns
Polyslice now supports 7 total infill patterns (previously 3):
1. Concentric Pattern 🎯
Inward-spiraling contours that follow the natural boundary shape.
Best for:
- Curved shapes and organic forms
- Cylindrical cross-sections
- Parts where following the boundary is beneficial
Characteristics:
- Continuous paths minimize travel moves
- Natural fit for circular geometries
- Each layer independently follows the boundary shape
2. Gyroid Pattern 🌊
Triply periodic minimal surface (TPMS) with wavy interlocking structure.
Best for:
- Parts requiring maximum strength-to-weight ratio
- Isotropic strength requirements
- Aesthetic wavy patterns
Characteristics:
- Single rotating direction per layer (0° to 90° over 8 layers)
- 3D interlocking structure across layers
- Excellent strength comparable to hexagons
- Smooth gradual transitions between layers
3. Spiral Pattern 🌀
Archimedean spiral from center outward in one continuous path.
Best for:
- Circular or cylindrical parts
- Smooth continuous motion printing
- Parts where radial structure is beneficial
Characteristics:
- Single continuous spiral from center
- No direction changes within a layer
- Natural fit for cylindrical geometries
- Efficient for circular cross-sections
4. Lightning Pattern ⚡
Tree-like branching structure for fast printing with minimal material.
Best for:
- Draft prints and prototypes
- Parts where speed is prioritized
- Internal support structure
- Low-density infill requirements
Characteristics:
- Tree-like branching from boundary inward
- 45° fork angles for natural appearance
- Minimal material usage
- Fast printing speed
- Adequate support for top surfaces
Infill Pattern Centering
New configuration option infillPatternCentering gives you control over pattern alignment:
// Object-centered (default) - centers on each object's boundaries
slicer.setInfillPatternCentering('object');
// Global-centered - centers on build plate center (0,0)
slicer.setInfillPatternCentering('global');Affected patterns: Grid, Triangles, Hexagons, Gyroid, Spiral, Lightning
Not affected: Concentric (inherently follows boundary)
Use cases:
- Object mode: Best for most prints, centers patterns naturally on each object
- Global mode: Consistent pattern alignment across multiple prints, easier visual comparison
🔧 Major Changes
Gyroid Pattern Algorithm Revision
The gyroid pattern has been completely rewritten for better performance and quality:
Before:
- Generated two sets of wavy lines per layer (X and Y directions)
- ~170 lines per layer
- Abrupt direction changes between layers
After:
- Single set of wavy lines per layer
- Gradual rotation from 0° to 90° over 8-layer cycle
- Consistent ~85-100 lines per layer
- Smooth transitions for better layer adhesion
- Better performance and material usage
Example layer sequence:
- Layer 0: 0° (horizontal wavy lines) - ~92 lines
- Layer 4: 45° (diagonal) - ~98 lines
- Layer 7: ~79° (near vertical) - ~88 lines
- Layer 8: Cycle repeats
This change results in:
- ✅ Better layer-to-layer adhesion
- ✅ More consistent material usage
- ✅ Improved performance (fewer lines to generate)
- ✅ Smoother interlocking 3D structure
🐛 Bug Fixes
Concentric Infill Issues Fixed
Problem: Concentric infill had multiple issues:
- First loop too close to walls (no gap)
- Infill generated inside holes (torus example showed 33% points in holes)
Solution:
- Added proper
lineSpacinggap before first infill loop - Implemented hole detection using majority voting on 8 sample points per loop
- Loop skipped only if more than half the sample points are inside holes
Impact: Torus example now shows 0% erroneous points (down from 33%)
Cylinder Bottom Layer Fixed
Problem: Cylinders had incomplete walls on the bottom layer
Solution: Increased SLICE_EPSILON from 0.001mm to layerHeight/2 to avoid geometric boundary issues
Impact: All cylinder slicing now produces complete walls on every layer
Spiral Pattern LastEndPoint Tracking
Problem: Spiral pattern updated lastEndPoint unconditionally, causing incorrect combing calculations
Solution: Only update lastEndPoint when actual movement is generated (distance > 0.001mm)
Impact: More accurate travel path optimization in spiral infill
Skin Generation for Nested Structures
Problem: Travel moves between skin areas in nested structures were incorrect
Solution: Proper handling of travel moves when generating skin for complex nested geometries
Impact: Cleaner G-code with better travel optimization
CI Pipeline Dependency Conflicts
Problem: CI pipeline failed due to eslint-plugin-jest conflicts with eslint 10.x
Solution: Removed unused eslint-plugin-jest from devDependencies
Impact: CI pipeline now runs successfully with latest eslint 10.0.0
📊 Pattern Comparison
| Pattern | Directions | Speed | Strength | Use Case |
|---|---|---|---|---|
| Grid | 2 (±45°) | Medium | Good | General purpose |
| Triangles | 3 (45°, 105°, -15°) | Medium | Better | Structural parts |
| Hexagons | Honeycomb | Slower | Best | Maximum strength |
| Concentric | Spiraling | Fast | Good | Curved/circular parts |
| Gyroid | Wavy TPMS | Medium | Excellent | Isotropic strength |
| Spiral | Radial | Fast | Good | Circular parts |
| Lightning | Branching | Fastest | Adequate | Draft/prototype |
📚 Documentation Updates
- Updated all instruction files for new infill patterns
- Added comprehensive API documentation for new patterns
- Updated README with pattern comparison table
- Added example scripts demonstrating all patterns
- Documented infill pattern centering feature
🔬 Testing
All new features include comprehensive test coverage:
- Concentric pattern: 11 tests
- Gyroid pattern: 13 tests
- Spiral pattern: 11 tests
- Lightning pattern: 11 tests
- Pattern centering: Integration tests
🙏 Acknowledgments
Special thanks to the GitHub Copilot team for assisting with:
- Complex gyroid algorithm implementation
- Concentric infill hole detection logic
- Lightning pattern tree structure
- Comprehensive documentation updates
🔗 Links
- GitHub Release: https://github.com/jgphilpott/polyslice/releases/tag/v26.2.0
- npm Package: https://www.npmjs.com/package/@jgphilpott/polyslice
- Documentation: https://github.com/jgphilpott/polyslice#readme
- Changelog: https://github.com/jgphilpott/polyslice/blob/main/CHANGELOG.md
📦 Installation
npm install @jgphilpott/polysliceOr via CDN (browser):
<script src="https://unpkg.com/@jgphilpott/polyslice@26.2.0/dist/index.browser.min.js"></script>🚀 Upgrade Guide
Upgrading from v26.1.2 is straightforward - all changes are additive:
npm update @jgphilpott/polysliceNew API Methods:
// Use new infill patterns
slicer.setInfillPattern('concentric');
slicer.setInfillPattern('gyroid');
slicer.setInfillPattern('spiral');
slicer.setInfillPattern('lightning');
// Configure pattern centering
slicer.setInfillPatternCentering('object'); // Default
slicer.setInfillPatternCentering('global');Breaking Changes: None - all existing code continues to work
Behavior Changes:
- Gyroid pattern now generates different output (single rotating direction)
- Concentric pattern now properly respects holes
- Cylinder slicing may produce slightly different output due to SLICE_EPSILON fix
📈 Statistics
Since v26.1.2:
- 80+ commits merged
- 7 major pull requests (4 for new patterns, 3 for fixes)
- 4 new infill patterns added
- 25 new tests added
- 200+ documentation updates
- 15+ bug fixes and improvements
Full Changelog: https://github.com/jgphilpott/polyslice/blob/main/CHANGELOG.md
v26.1.2
Release v26.1.2
Release Date
January 28, 2026
Highlights
This release adds comprehensive metadata and progress tracking capabilities to Polyslice, including G-code metadata extraction, configurable metadata headers, progress callbacks, and print time calculation.
New Features
1. G-code Metadata Extraction (getGcodeMetadata())
Extract metadata from G-code files with automatic multi-slicer support:
// Extract from slicer's internal G-code
const metadata = slicer.getGcodeMetadata();
// Or extract from any G-code string
const customGcode = fs.readFileSync('print.gcode', 'utf8');
const metadata = slicer.getGcodeMetadata(customGcode);
console.log(metadata.printer); // "Ender3"
console.log(metadata.nozzleTemp.value); // 200
console.log(metadata.nozzleTemp.unit); // "°C"
console.log(metadata.totalLayers); // 50
console.log(metadata.filamentLength.value); // 1234.5
console.log(metadata.filamentLength.unit); // "mm"Supported Slicers:
- ✅ Polyslice (native)
- ✅ Cura / Ultimaker Cura
- ✅ PrusaSlicer
- ✅ Generic G-code (fallback parser)
Extracted Metadata Fields:
Common Fields (all slicers):
generatedBy- Slicer nameversion- Slicer versionprinter- Printer modellayerHeight- Layer height with unitstotalLayers- Layer countfilamentLength- Filament used with unitsestimatedPrintTime- Print time estimate
Polyslice-specific Fields:
timestamp- ISO 8601 timestamprepository- Repository URLfilament- Filament name and typenozzleTemp- Nozzle temperature with unitsbedTemp- Bed temperature with unitsmaterialVolume- Material volume with unitsmaterialWeight- Material weight with unitsflavor- G-code flavor (e.g., "Marlin")infillDensity- Infill percentageinfillPattern- Infill pattern typewallCount- Number of perimetersboundingBox- Print bounding box coordinates
2. Configurable Metadata Fields
Fine-grained control over metadata output with 20+ configurable fields:
const slicer = new Polyslice({
metadataVersion: true, // Include version number
metadataTimestamp: true, // Include timestamp
metadataRepository: true, // Include repository URL
metadataPrinter: true, // Include printer info
metadataFilament: true, // Include filament info
metadataNozzleTemp: true, // Include nozzle temperature
metadataBedTemp: true, // Include bed temperature
metadataLayerHeight: true, // Include layer height
metadataTotalLayers: true, // Include total layers
metadataFilamentLength: true, // Include filament length
metadataMaterialVolume: true, // Include material volume
metadataMaterialWeight: true, // Include material weight
metadataPrintTime: true, // Include estimated print time
metadataFlavor: true, // Include G-code flavor
metadataInfillDensity: true, // Include infill density
metadataInfillPattern: true, // Include infill pattern
metadataWallCount: true, // Include wall count
metadataSupport: true, // Include support status
metadataAdhesion: true, // Include adhesion type
metadataSpeeds: true, // Include print speeds
metadataBoundingBox: true // Include bounding box
});All metadata fields output with proper units (°C for temperature, mm for length, etc.).
3. Progress Callback System
Real-time feedback during slicing with customizable progress callbacks:
const slicer = new Polyslice({
progressCallback: (progressInfo) => {
console.log(`Stage: ${progressInfo.stage}`);
console.log(`Progress: ${progressInfo.percent}%`);
if (progressInfo.currentLayer) {
console.log(`Layer: ${progressInfo.currentLayer}/${progressInfo.totalLayers}`);
}
console.log(`Message: ${progressInfo.message}`);
}
});
const gcode = slicer.slice(mesh);Progress Stages:
initializing- Mesh preparationpre-print- Pre-print G-code generationadhesion- Adhesion structure generationslicing- Layer-by-layer slicing (0-100%)post-print- Post-print G-code generationcomplete- Slicing finished
Default Progress Bar:
If no custom callback is provided, Polyslice includes a default lightweight progress bar:
- Node.js: In-place updating progress bar using
process.stdout.write - Browser: Console.log updates for each stage
4. Print Time Calculation
Accurate print time estimation from G-code analysis:
// Automatically calculated during slicing
const gcode = slicer.slice(mesh);
const metadata = slicer.getGcodeMetadata();
console.log(metadata.estimatedPrintTime); // "2h 34m 15s"Features:
- Analyzes all G-code movement commands (G0, G1, G2, G3)
- Accounts for feedrates and positioning modes (absolute/relative)
- Supports arc movements and Bézier curves
- Parses actual G-code for accurate estimates
5. Enhanced Metadata Headers
G-code files now include comprehensive metadata headers:
; Generated by Polyslice
; Version: 26.1.2
; Timestamp: 2026-01-28T12:00:00.000Z
; Repository: https://github.com/jgphilpott/polyslice
; Printer: Ender3
; Filament: Generic PLA (pla)
; Nozzle Temp: 200°C
; Bed Temp: 60°C
; Layer Height: 0.2mm
; Total Layers: 50
; Filament Length: 1234.5mm
; Material Volume: 3.2cm³
; Material Weight: 4.0g
; Estimated Print Time: 2h 34m 15s
; Flavor: Marlin
; Infill Density: 20%
; Infill Pattern: grid
; Wall Count: 2
; Support: false
; Adhesion: skirt
; Perimeter Speed: 50mm/s
; Infill Speed: 60mm/s
; Travel Speed: 120mm/s
; Bounding Box: X[0.0,100.0] Y[0.0,100.0] Z[0.0,10.0]Improvements
- Improved Metadata Parsing - Better handling of multiple G-code flavors
- Enhanced G-code Headers - Comprehensive metadata in G-code comments
- Better Metadata Organization - Structured data with proper units
- Improved Code Documentation - Better inline documentation for metadata features
Use Cases
- G-code Analysis Tools - Build tools to analyze and compare print settings
- Print Management - Track and categorize prints by settings
- Quality Control - Verify print parameters before sending to printer
- Cross-Slicer Compatibility - Read metadata from any slicer
- Print Statistics - Collect statistics on material usage and print times
- Progress Monitoring - Track slicing progress in real-time
- Custom Metadata Headers - Generate G-code with specific metadata fields
API Changes
New Configuration Options
// Metadata field options (all default to true)
metadataVersion
metadataTimestamp
metadataRepository
metadataPrinter
metadataFilament
metadataNozzleTemp
metadataBedTemp
metadataLayerHeight
metadataTotalLayers
metadataFilamentLength
metadataMaterialVolume
metadataMaterialWeight
metadataPrintTime
metadataFlavor
metadataInfillDensity
metadataInfillPattern
metadataWallCount
metadataSupport
metadataAdhesion
metadataSpeeds
metadataBoundingBox
// Progress callback option
progressCallback: FunctionNew Methods
// Extract metadata from G-code
slicer.getGcodeMetadata(gcode?: string): ObjectInstallation
npm install @jgphilpott/polyslice@26.1.2Or update your existing installation:
npm update @jgphilpott/polysliceCDN (Browser)
<script type="module">
import Polyslice from 'https://unpkg.com/@jgphilpott/polyslice@26.1.2/dist/index.browser.esm.js';
</script>Documentation
Full API documentation: https://github.com/jgphilpott/polyslice/blob/main/docs/api/API.md#getgcodemetadatagcode--null
Breaking Changes
None - This is a backward-compatible feature addition.
Dependencies
No dependency changes in this release.
Testing
- All 695 tests passed ✅
- Linting passed with no issues ✅
- All distributions built successfully ✅
Thanks
This feature was developed to improve G-code interoperability and enable better tooling around 3D printing workflows.
Full Changelog
See CHANGELOG.md for complete version history.
Previous Release: v26.1.1
Next Release: TBD
v26.1.1
Release v26.1.1
Release Date: January 23, 2026
Version: 26.1.1 (Second release of January 2026)
Highlights
This release introduces several major enhancements to Polyslice, focusing on improving print quality, adding comprehensive adhesion support, and optimizing travel paths for more efficient printing.
New Features
Smart Wipe Nozzle
A new intelligent wipe nozzle feature that prevents marks and filament threads on finished parts:
- Intelligent Path Calculation: Analyzes the mesh bounding box to find the shortest path away from the print boundaries
- Built-in Retraction: Includes retraction during the wipe move to prevent oozing
- Configurable: Control via the
smartWipeNozzleoption (enabled by default whenwipeNozzleis true) - Automatic Backoff: Adds 3mm safety backoff beyond mesh boundaries
Traditional wipe implementations simply move X+5, Y+5 in relative coordinates, which can cause the nozzle to land on the print itself. The smart wipe calculates the optimal direction to move perpendicular to the nearest boundary.
Complete Adhesion Module
A comprehensive adhesion system with three distinct adhesion types:
Skirt
- Circular Mode: Perfect circles around the model for simple nozzle priming
- Shape Mode: Follows the actual first layer outline for precise boundary visualization
- Configurable Distance: Set distance from model edge (default: 5mm)
- Line Count: Control number of loops (default: 3)
Brim
- Attached Support: Directly attaches to model edge for maximum warping prevention
- Minimal Gap: Configurable gap from model (default: 0mm for full attachment)
- Wide Support: 8 lines by default for strong hold
Raft
- Three-Layer System: Base layer, interface layers, and air gap
- Configurable Thickness: Independent control of base and interface layer heights
- Air Gap: Adjustable gap between raft and model for easy removal
- Line Spacing: Control raft density for optimal bed adhesion
All adhesion types include:
- Modular architecture with separate sub-modules
- Boundary checking to warn if extending beyond build plate
- Integration with verbose mode for detailed G-code annotations
- Example scripts demonstrating usage
Travel Path Optimization
Significant improvements to travel move efficiency:
- Nearest-Neighbor Algorithm: Objects are processed in order of proximity to minimize travel distance
- Sequential Completion: For independent objects, each is fully completed (walls → skin → infill) before moving to the next
- Home Position Start: First layer sorting starts from printer home position (0,0)
- Intelligent Application: Optimization applies when exposure detection is disabled for simple multi-object prints
This can dramatically reduce print time for prints with multiple independent objects by eliminating zigzag patterns across the build plate.
Development Tools
- Release Agent: New specialized agent for managing calendar-based version releases
- CHANGELOG.md: Formal changelog following Keep a Changelog conventions
- Example Scripts: New slice-pillars example generating pillar arrays from 1x1 to 5x5
Improvements
Module Organization
- Reorganized adhesion module into clean subdirectories (
skirt/,brim/,raft/,helpers/) - Each adhesion type now has its own dedicated module with clear separation of concerns
- Improved code maintainability and testability
Travel Efficiency
- Travel paths now use nearest-neighbor sorting throughout the slicing process
- Better handling of independent objects vs complex geometries with holes
- Reduced unnecessary travel moves between features
Bug Fixes
- Test Output: Cleaned up test output to suppress expected console warnings
- Travel Optimization: Fixed incorrect application when exposure detection was enabled
- Home Position: Proper handling of printer home position (0,0) as starting point for first layer sorting
Breaking Changes
Removed
- Deprecated
outlineSetting: Theoutlineconfiguration option has been removed. This feature was deprecated and unused in the codebase.
Dependencies
No dependency updates in this release. Current major dependencies:
- three.js: ^0.182.0
- @jgphilpott/polytree: ^0.1.6
- @jgphilpott/polyconvert: ^1.0.5
- polygon-clipping: ^0.15.7
- three-subdivide: ^1.1.5
Documentation
- Added comprehensive CHANGELOG.md
- Updated adhesion module documentation
- Added smart wipe implementation guide
- Documented travel optimization strategies
Testing
All tests pass (651 tests):
- Unit tests for all new features
- Integration tests for adhesion types
- Smart wipe calculation tests
- Travel optimization validation
Migration Guide
From v26.1.0 to v26.1.1
No breaking API changes. All existing code will continue to work.
If you were using the outline setting (unlikely as it was deprecated), simply remove it from your configuration:
// Before
const slicer = new Polyslice({
outline: true, // Remove this
// ... other settings
});
// After
const slicer = new Polyslice({
// ... other settings
});New Optional Features
To use the new features, simply enable them in your configuration:
const slicer = new Polyslice({
// Smart wipe nozzle (enabled by default when wipeNozzle is true)
wipeNozzle: true,
smartWipeNozzle: true,
// Adhesion
adhesionEnabled: true,
adhesionType: 'skirt', // or 'brim' or 'raft'
skirtDistance: 5,
skirtLineCount: 3,
// Travel optimization (automatic for independent objects)
exposureDetection: false, // Enable optimization
});Known Issues
None reported for this release.
Installation
npm
npm install @jgphilpott/polysliceBrowser CDN
<script src="https://unpkg.com/@jgphilpott/polyslice@26.1.1/dist/index.browser.min.js"></script>Verification
To verify the installation:
const Polyslice = require('@jgphilpott/polyslice');
console.log(Polyslice.version); // Should output "26.1.1"Next Steps
After merging this PR:
- Push Tags:
git push origin main --tagsto push the v26.1.1 tag - GitHub Release: Create a GitHub release using these notes
- npm Publish: Run
npm publishto publish to npm registry - Verification:
- Check
npm view @jgphilpott/polyslice version - Test installation in a clean directory
- Verify unpkg CDN updates
- Check
Thanks
Thanks to all contributors and users who have provided feedback and helped improve Polyslice!
Full Changelog: v26.1.0...v26.1.1