Releases: barebaric/raygeo
v0.13.2
What's Changed
- New
precisionparameter for adaptive wavefronts — controls the angular step when sweeping wavefront arcs; improves performance and fidelity of adaptive clearing engagement paths - Fix: reengagement search for adaptive clearing — correctly handles cases where the reengagement point search would skip valid positions near narrow-region boundaries
Full Changelog: https://github.com/anomalyco/raygeo/compare/v0.13.1...v0.13.2
v0.13.1
What's Changed
- New adaptive clearing debug tool — interactive Streamlit-based step-through inspector for adaptive clearing operations
- Fix: bezier command parsing for legacy formats — proper handling of bezier curves in older SVG/CAM files
- Better adaptive clearing diagnostic plots — improved visualization of narrow regions and centre-island detection
- De-duplicated debug logging macros — consolidated debug log infrastructure into a shared module
- Polyline tests ported to Python — moved test coverage from Rust to Python test suite
v0.13.0
Release v0.13.0
Highlights
- Improved
adaptive_wavefronts()results — better quality wavefront generation - Numerous performance improvements —
sweep_area(),build_link_segmentswith rayon, lazy MAT trimming, profiling infrastructure - Reorganized
opsmodule:ops.polylinesplit intoops.assembly.polyline+ops.transform.link;ops.assembly.hsmsplit intoops.assembly.entry+ops.assembly.wavefront - Removed unreliable
adaptive_peeling()and associated HSM pipeline - New
geo.algo.engagementmodule:point_engagement,angular_engagement,compute_engagement,disk_segment_area - New
geo.algo.rootfindmodule:bisect,illinois,secantsolvers with tracking variants andbracket_grid - New geometry helpers:
does_polygon_enclose_circle,get_polygon_heading_at,walk_polygon_from_point,rotate_point,normalize_angle_signed,does_rect_contain_rect SpatialGridgains aremove()method
Migration Guide: v0.12.1 → v0.13.0
Module Moves
ops.polyline split into ops.assembly.polyline + ops.transform.link
| v0.12.1 | → | v0.13.0 |
|---|---|---|
raygeo.ops.polyline.polyline_to_ops |
→ | raygeo.ops.assembly.polyline.polyline_to_ops |
raygeo.ops.polyline.link_passes |
→ | raygeo.ops.transform.link.link_passes |
raygeo.ops.polyline.find_pass_entry |
→ | raygeo.ops.transform.link.find_pass_entry |
raygeo.ops.polyline.find_pass_exit |
→ | raygeo.ops.transform.link.find_pass_exit |
raygeo.ops.polyline.LinkStrategy |
→ | raygeo.ops.transform.link.LinkStrategy |
Old: from raygeo.ops.polyline import polyline_to_ops, link_passes, LinkStrategy
New: from raygeo.ops.assembly.polyline import polyline_to_ops / from raygeo.ops.transform.link import link_passes, LinkStrategy
ops.assembly.hsm split into ops.assembly.entry + ops.assembly.wavefront
| v0.12.1 | → | v0.13.0 |
|---|---|---|
raygeo.ops.assembly.hsm.adaptive_entry |
→ | raygeo.ops.assembly.entry.adaptive_entry |
raygeo.ops.assembly.hsm.adaptive_wavefronts |
→ | raygeo.ops.assembly.wavefront.adaptive_wavefronts |
Old: from raygeo.ops.assembly.hsm import adaptive_entry, adaptive_wavefronts
New: from raygeo.ops.assembly.entry import adaptive_entry / from raygeo.ops.assembly.wavefront import adaptive_wavefronts
Removed (No Replacement)
adaptive_peeling()— too unreliable, removed entirelyfind_cutting_arc(),link_arcs_to_ops(),split_ordered_wavefronts(),PyWavefrontGraph— part of removed HSM pipelinedoes_rect_intersect_rect()— duplicate ofdo_rects_intersect()find_next_resume(..., medial_axis=...)—medial_axisparameter droppedResumePoint.link_pathfield removedTool.step/Tool.step_with_bias— merged into singlestepmethod
Removed Modules
| Module | Migration |
|---|---|
raygeo.ops.polyline |
→ ops.assembly.polyline + ops.transform.link |
raygeo.ops.assembly.hsm |
→ ops.assembly.entry + ops.assembly.wavefront |
New Public API
raygeo.geo.algo.engagement — point_engagement, angular_engagement, compute_engagement, disk_segment_area
raygeo.geo.algo.rootfind — bisect, bisect_tracked, bracket_grid, illinois, illinois_tracked, secant, secant_tracked
New geometry helpers — does_polygon_enclose_circle, get_polygon_heading_at, walk_polygon_from_point, rotate_point, normalize_angle_signed, does_rect_contain_rect, SpatialGrid.remove
Quick Migration
# polyline / link
# Old:
from raygeo.ops.polyline import polyline_to_ops, link_passes, LinkStrategy
# New:
from raygeo.ops.assembly.polyline import polyline_to_ops
from raygeo.ops.transform.link import link_passes, LinkStrategy
# HSM assembly
# Old:
from raygeo.ops.assembly.hsm import adaptive_entry, adaptive_wavefronts
# New:
from raygeo.ops.assembly.entry import adaptive_entry
from raygeo.ops.assembly.wavefront import adaptive_wavefronts
# Removed — no replacement:
# adaptive_peeling(), find_cutting_arc(), link_arcs_to_ops(),
# split_ordered_wavefronts(), PyWavefrontGraphv0.12.1
Breaking changes
- Removed machining terminology from the
geolayer — several functions
and parameters renamed to use geometry-domain names:trochoid_along_3d:tool_diameter→diameterClearedArea.expand:tool_path→path,tool_radius→radiusMedialAxis.compute:tool_radius→min_clearanceoffset.find_deepest_cores:valid_tool_area→regions
append_end_fillets: the singlesideparameter is split into
start_sideandend_side, fixing fillet direction at V-junctions
New features
descending_radius_fillet— new fillet function that tries descending
radii until one fits, replacing the manual trim_to_safe_fillet_span /
try_fillet_one_end cascadecut_powerparameter onadaptive_entry,adaptive_peeling,
adaptive_wavefronts, andlink_arcs_to_opsfor laser power controlPyWavefrontGraphgainssegments,segment_directions, and
arc_segmentsproperties exposing V-junction-split sub-segments
Bug fixes
- Fix duplicate cutlines emitted by
split_ordered_wavefronts - Fix wrong fillet direction on arcs with V-junctions (split arcs before
determining turn sign so each half gets its own direction) - Fix adaptive peeling corner coverage — all bites now incorporated
unconditionally, with a perimeter fallback whenfind_cutting_arcfails - Fix CDT panics from degenerate geometry and peeling hangs on pinched
frontiers - Fix
link_arcs_to_opsMAT reconstruction when passed raw (nodes, edges)
Full commit log: https://github.com/anomalyco/raygeo/compare/v0.12.0...v0.12.1
v0.12.0
v0.12.0
Highlights
- Layered architecture:
geo→ops→cnclayering established with HSM motion assembly moved fromgeotoops::assembly. - CNC terminology: Laser-centric naming replaced with CNC-milling terminology (
cut_speed→feed_rate,travel_speed→rapid_rate,air_assist→CoolantMode, etc.). - 2D/3D naming convention: All functions now follow
bare = 2D, _3d = 3D. - Polygon/Polyline module split: Polyline functions moved from
polygonto dedicatedpolylinemodule. - New geometry primitives: Medial axis routing, A* pathfinding, FEM meshing, spiral/helix/ramp/trochoid primitives, polylabel, offset improvements.
- New CNC module:
raygeo.cncwithTool,StateStrategy,EntryStrategy, andadaptive_clear_hsmorchestrator.
Breaking changes
See the full migration guide below.
CNC terminology rename
State.cut_speed→State.feed_rateState.travel_speed→State.rapid_rateState.active_laser_uid→State.active_head_uidState.spindle_speed→State.spindle_rpmOps.set_cut_speed()→Ops.set_feed_rate()Ops.set_travel_speed()→Ops.set_rapid_rate()Ops.set_laser()→Ops.set_head()Ops.set_spindle_speed()→Ops.set_spindle_rpm()ops.travel_distance()→ops.distance()enable_air_assist()removed → useset_coolant()estimate_time/estimate_command_timesparameter rename:default_cut_speed→default_feed_rate,default_travel_speed→default_rapid_rateget_frame(speed=)→get_frame(feed_rate=)CommandType.SetCutSpeed→SetFeedRate,SetTravelSpeed→SetRapidRate,SetLaser→SetHead,SetSpindleSpeed→SetSpindleRpmCommandType.EnableAirAssist/DisableAirAssistremoved →SetCoolant
Coolant mode enum
State.air_assist: bool→State.coolant: Option<CoolantMode>CoolantModevalues:Off,Flood,Mist,Air
ScanMode uppercase
ScanMode.Segmented→ScanMode.SEGMENTEDScanMode.FullSweep→ScanMode.FULL_SWEEP
JoinStyle enum
offset_polygon(..., join_style="round")→offset_polygon(..., join_style=JoinStyle.Round)offset_contour_group(..., join_style="miter")→offset_contour_group(..., join_style=JoinStyle.Miter)- Rust:
offset_polygon_with_stylerenamed back tooffset_polygon
Rect/Rect3D struct change
Rect(x1, y1, x2, y2)→Rect { min: Point, max: Point }Rect.0/.1/.2/.3→Rect.min.x/.y,Rect.max.x/.yRect3D.x_min/.x_max/.y_min/.y_max/.z_min/.z_max→Rect3D.min/.max
2D/3D naming
circumcenteris now 2D;circumcenter_3dis 3D (swap)simplify_polyline→simplify_polyline_3d(2D wrapper removed)midpoint→midpoint_3d,transform_point→transform_point_3dnormal_from_clockwise→normal_from_clockwise_3dgenerate_helix→generate_helix_3d,generate_spiral→generate_spiral_3d,generate_ramp→generate_ramp_3d,trochoid_along→trochoid_along_3dsmooth_polyline→smooth_polyline_3dflatten_to_points→flatten_to_points_3dresample_polyline(3D) moved fromgeo.algo.smoothtogeo.shape.polygon3d
Module reorganization
ops.lead_in_out→ops.assembly.lead_in_out(re-exported)ops.overscan→ops.assembly.overscan(re-exported)ops.tabs→ops.assembly.tabs(re-exported)ops.polyline→ops.assembly.polyline(re-exported)ops.raster→ops.assembly.raster(re-exported)- Polygon module split: polyline functions moved to
geo.shape.polyline
New features
CNC orchestration (raygeo.cnc)
Tool,ToolShape,ToolMaterialclassesStateStrategywithconstant()factoryEntryStrategywith helix/ramp supportadaptive_clear_hsm— full HSM clearing orchestrator
Geometry additions
- Medial axis computation and MAT path routing
- A* pathfinding with rasterized grid
- FEM PDE meshing with Laplace solver
- Flat Archimedean spiral primitive
ClearedAreawithfragments(),bites(),bite_in_direction(),incorporate(),all_bites(),remaining_in_inset(),add_cleared_polygons()- Adaptive entry (helix/spiral + zigzag ramp) and adaptive wavefronts
- Polylabel:
find_largest_circle, pole-of-inaccessibility algorithm - Offset improvements:
find_deepest_cores,compute_inset_region,apply_minimum_curvature JoinStyleenum (Miter/Round/Square) for offset operations- Fillet arc ends, safe sweep end detection
walk_along_polyline_3d,walk_along_polygon_3d,fillet_polyline_3dpolyline_to_ops,link_passes,find_pass_entry/find_pass_exitapply_lead_in_out,apply_overscan,apply_tab_gaps,apply_tab_powerget_ray_polygon_intersection,does_line_cross_polygon,get_segment_segment_distanceget_polyline_closest_point,trim_polyline_at,trim_polyline_angular_endssplit_polyline_at_v_junctions,resample_polygonget_polygon_boundary_distance,get_polygon_vertex_centroidshortcut_pathsmoothing, shortcut + Gaussian relaxationdeduplicate_polyline_3d,get_polyline_end_tangent_3dfit_cubic_bezier,nearest_tangent_circle_on_bezierarc_through_point,generate_arc_between_two_points,generate_linking_arcinterpolated_segment_3d,circumcenter_2dget_polygon_area_3d,get_polygon_signed_area_3dorder_nearest_neighbor,blend_tangent,get_polyline_turn_signcompute_valid_tool_area
Ops additions
Ops::apply_state(&State)for domain-neutral state emissionOps.distance(),Ops.cut_distance()CoolantModeenum
Migration Guide
Migration Guide
1. 2D/3D Naming Convention
Function names now consistently follow the rule: bare = 2D, _3d = 3D.
Tier 1 — Pair inversions
circumcenter / circumcenter_3d swap
The 3D circumcenter (takes Point3D) was renamed from circumcenter to circumcenter_3d. The 2D circumcenter (takes Point) was renamed from circumcenter_2d to circumcenter.
// Rust
-use raygeo::geo::shape::point::circumcenter; // was 3D, now 2D
+use raygeo::geo::shape::point::circumcenter_3d; // 3D circumcenter (returns Option<Point3D>)
+use raygeo::geo::shape::point::circumcenter; // 2D circumcenter (returns (Point, f64)) # Python
-from raygeo.geo.shape.point import circumcenter # was 3D
-from raygeo.geo.shape.point import circumcenter_2d # was 2D
+from raygeo.geo.shape.point import circumcenter_3d # 3D circumcenter
+from raygeo.geo.shape.point import circumcenter # 2D circumcentersimplify_polyline → simplify_polyline_3d
// Rust
-use crate::geo::algo::simplify::simplify_polyline;
+use crate::geo::algo::simplify::simplify_polyline_3d;The Python 2D wrapper was removed entirely — only simplify_polyline_3d exists:
# Python
-from raygeo.geo.algo.simplify import simplify_polyline # removed
-from raygeo.geo.algo.simplify import simplify_polyline_3d
+from raygeo.geo.algo.simplify import simplify_polyline_3d # only nameConvert 2D calls by adding z=0:
-result = simplify_polyline([(0, 0), (5, 5), (10, 0)], tolerance=0.5)
+result = simplify_polyline_3d([(0, 0, 0), (5, 5, 0), (10, 0, 0)], tolerance=0.5)Tier 3 — Misnamed _2d helpers → _xy
Private functions that accept Point3D but only measure XY:
| File | Old name | New name |
|---|---|---|
src/ops/assembly/tabs.rs |
bezier_arc_length_2d |
bezier_arc_length_xy |
src/ops/assembly/tabs.rs |
distance_2d |
distance_xy |
src/ops/optimize.rs |
dist_2d |
dist_xy |
No Python impact (all private).
Tier 4 — 3D orphans → _3d suffix
Functions that return 3D types and have no 2D counterpart:
Point operations
// Rust
-use crate::geo::shape::point::midpoint;
-use crate::geo::shape::point::transform_point;
+use crate::geo::shape::point::midpoint_3d;
+use crate::geo::shape::point::transform_point_3d; # Python
-from raygeo.geo.shape.point import midpoint
-from raygeo.geo.shape.point import transform_point
+from raygeo.geo.shape.point import midpoint_3d
+from raygeo.geo.shape.point import transform_point_3dArc operations
// Rust
-use crate::geo::shape::arc::normal_from_clockwise;
+use crate::geo::shape::arc::normal_from_clockwise_3d;No Python impact (no direct binding).
Helix / Spiral / Ramp / Trochoid
// Rust
-use crate::geo::algo::helix::generate_helix;
-use crate::geo::algo::spiral::generate_spiral;
-use crate::geo::algo::ramp::generate_ramp;
-use crate::geo::algo::trochoid::trochoid_along;
+use crate::geo::algo::helix::generate_helix_3d;
+use crate::geo::algo::spiral::generate_spiral_3d;
+use crate::geo::algo::ramp::generate_ramp_3d;
+use crate::geo::algo::trochoid::trochoid_along_3d; # Python
-from raygeo.geo.algo.helix import generate_helix
-from raygeo.geo.algo.spiral import generate_spiral
-from raygeo.geo.algo.ramp import generate_ramp
-from raygeo.geo.algo.trochoid import trochoid_along
+from raygeo.geo.algo.helix import generate_helix_3d
+from raygeo.geo.algo.spiral import generate_spiral_3d
+from raygeo.geo.algo.ramp import generate_ramp_3d
+from raygeo.geo.algo.trochoid import trochoid_along_3dSmoothing
// Rust
-use crate::geo::algo::smooth::smooth_polyline;
+use crate::geo::algo::smooth::smooth_polyline_3d; # Python
-from raygeo.geo.algo.smooth import smooth_polyline
+from raygeo.geo.algo.smooth import smooth_polyline_3dFitting
// Rust
-use crate::geo::algo::fitting::flatten_to_points;
+use crate::geo::algo::fitting::flatten_to_points_3d; # Python
-from raygeo.geo.algo.fitting import flatten_to_points
+from raygeo.geo.algo.fitting import flatten_to_points_3dTier 5 — Rect re-export
Rect is now exporte...
v0.11.0
v0.11.0 (2026-06-22)
78 commits since v0.10.0. ~10 400 insertions across 113 source files.
Breaking Changes
See the full Migration Guide below.
Rect— tuple struct → named fields (min/maxasPoint)Rect3D— flat fields →min/maxasPoint3Doffset_polygon()gained a requiredJoinStyleparameter (Python defaults to"miter")trochoid_along()output — added longitudinal component (true trochoidal loop)ScanModevariants renamed to UPPER_CASE (Segmented→SEGMENTED,FullSweep→FULL_SWEEP)
New Modules
raygeo.geo.algo.astar— A* pathfinding with rasterized grid support, obstacle avoidance, and configurable heuristics.raygeo.geo.algo.cleared_area— Incremental union of tool-swept polygons withSpatialGrid-windowed queries. Supportsincorporate,frontier,bites,fragments,remaining_in_inset, andadd_cleared_polygons.raygeo.geo.algo.fillet— Fillet arc-end trimming and linking primitives extracted from the HSM module.raygeo.geo.algo.medial_axis— Delaunay-circumcenter Medial Axis Transform with per-branch boustrophedon routing (mat_path).raygeo.geo.algo.polylabel— Pole of inaccessibility with hole/island support (find_largest_circle,get_polygon_closest_point).raygeo.geo.algo.spiral— Flat Archimedean spiral primitive (generate_spiral/SpiralOptions).raygeo.mesh— Full PDE meshing pipeline: constrained Delaunay triangulation (spade), linear FEM Laplace solver (nalgebraCG), gradient field computation, spiral tracing across triangle meshes, and remeshing. Submodules:build,laplace,gradient,pde,remesh,types.
HSM (High Speed Machining)
- Adaptive clearing wavefronts — inside-out expansion loop with frontier-based clipping, simplification, and multi-island support.
- Adaptive peeling — peeling algorithm for centred seed circles with full-ring cutting arc generation and filleted arc-end linking.
- Adaptive entry — Helix → spiral (wide area) or ZigZag ramp (tight slot) with
AdaptiveEntryOptions/AdaptiveEntryResult. - ClearedArea methods —
incorporate,frontier,bites,fragments,remaining_in_inset,add_cleared_polygons. - Constrained path smoothing —
smooth_path()with shortcut + Gaussian relaxation, obstacle clearance, integrated intolink_filleted_arcsandAdaptiveWavefrontOptions. compute_inset_region— replacescompute_valid_tool_areathroughout the HSM pipeline.
New Functions (existing modules)
raygeo.geo.shape
- point:
circumcenter - arc:
arc_through_point,get_polyline_turn_sign - bezier:
fit_cubic_bezier,nearest_tangent_circle_on_bezier - circle:
find_tangent_circle_centers,nearest_tangent_circle_on_polyline - line:
does_line_cross_polygon,get_segment_segment_distance,longest_line_through_point,get_interior_angle,interpolated_segment_3d - polygon:
apply_minimum_curvature,get_circle_polygon,get_polygon_closest_point,get_polygons_closest_point,get_polyline_bounds,get_segment_swept_polygon,does_path_sweep_intersect_polygon,get_polyline_closest_point,trim_polyline_at,trim_polyline_angular_ends - polygon3d:
walk_along_polyline_3d,walk_along_polygon_3d,deduplicate_polyline_3d,fillet_polyline_3d,get_polygon_area_3d,get_polygon_signed_area_3d,interpolated_segment_3d
raygeo.geo.algo
- fitting:
arc_between_two_points(exposed asgenerate_arc_between_two_points),generate_linking_arc - interp:
barycentric_interpolate,barycentric_weights - intersect:
get_ray_line_intersection,get_ray_polygon_intersection - offset:
compute_inset_region,find_deepest_cores(binary-search core detection) - smooth:
smooth_path
Refactors
ops/assembly— New submodule consolidatinghsm,lead_in_out,overscan,polyline,raster/, andtabs. HSM assembly moved fromgeo.algotoops.assemblyand refactored to returnOpscontainers.Rect/Rect3D— Converted to useglamvector types (DVec2/DVec3).Rectnow{ min: Point, max: Point };Rect3Dnow{ min: Point3D, max: Point3D }.- glam migration — Manual scalar math (
hypot,sqrt, manual dot/cross, manuallerp, manualnormalize) replaced withglammethods across all geo modules. offset_polygon— Restored original name (was temporarilyoffset_polygon_with_style), added properJoinStyleenum for Python API.ScanMode— Python-facing variants renamed to PEP8 UPPER_CASE via#[pyo3(name = "...")].- Module cleanup — Redundant aliases removed, local imports moved to module level, type annotations fixed in polygon stubs.
Infrastructure
- PDE meshing —
spade-based constrained Delaunay triangulation withTriangleMesh, boundary tagging, Steiner point insertion. - FEM Laplace solver — Linear FEM elements with conjugate-gradient solve (
nalgebra/nalgebra-sparse), gradient field computation, convergence history. - Profiling —
src/prof.rswith RAIIprof_guardfor operation timing. - New dependencies —
spade = "2",nalgebra = "0.35",nalgebra-sparse = "0.12". - Visual testing —
tools/visual_test.pysplit into submodule with one file per page; example image generator avoids re-generation if timestamps are unchanged. - Makefile — Added
venvtarget for virtual environment setup.
Removals
morph_spiralmodule removed (did not work well enough).geo.algo.hsmcompletely removed; remaining function moved toops.assembly.hsm.compute_valid_tool_areareplaced bycompute_inset_region.
Migration Guide: v0.10.0 → v0.11.0
This section covers only changes that break code written for v0.10.0.
New features (modules, functions added since v0.10.0) are not listed —
they require no migration.
1. Rect type: tuple struct → named fields
src/types.rs:47
// v0.10.0
pub struct Rect(pub f64, pub f64, pub f64, pub f64);
// x_min y_min x_max y_max
// v0.11.0
pub struct Rect {
pub min: Point, // DVec2
pub max: Point, // DVec2
}Rust code that constructs or destructures Rect as a 4-tuple will not
compile:
// BROKEN
let r = Rect(0.0, 0.0, 10.0, 20.0);
let Rect(x1, y1, x2, y2) = r;
// FIXED
let r = Rect::new(0.0, 0.0, 10.0, 20.0);
let x1 = r.min.x;
let y1 = r.min.y;
let x2 = r.max.x;
let y2 = r.max.y;Python impact: The Python API still passes Rect as
(x_min, y_min, x_max, y_max) tuples. Python code does not need
changes.
2. Rect3D type: flat fields → min/max
src/types.rs:181
// v0.10.0
pub struct Rect3D {
pub x_min: f64,
pub x_max: f64,
pub y_min: f64,
pub y_max: f64,
pub z_min: f64,
pub z_max: f64,
}
// v0.11.0
pub struct Rect3D {
pub min: Point3D,
pub max: Point3D,
}Replace field access:
| Old | New |
|---|---|
r.x_min |
r.min.x |
r.y_max |
r.max.y |
r.z_min |
r.min.z |
r.z_max |
r.max.z |
Construction changes from Rect3D { x_min: ..., x_max: ..., ... } to
Rect3D::new(min_pt, max_pt) or Rect3D { min: ..., max: ... }.
3. offset_polygon() gained a JoinStyle parameter
src/geo/shape/polygon.rs:648
The function name is unchanged, but the Rust signature now requires a
JoinStyle argument. Python binding keeps the old signature by
defaulting to "miter".
// Rust — new required parameter
offset_polygon(&poly, offset, JoinStyle::Miter);
offset_polygon(&poly, offset, JoinStyle::Round);
offset_polygon(&poly, offset, JoinStyle::Square);# Python — backwards compatible, defaults to JoinStyle.Miter
from raygeo.geo.shape.polygon import JoinStyle
offset_polygon(poly, offset) # defaults to Miter
offset_polygon(poly, offset, JoinStyle.Miter)
offset_polygon(poly, offset, JoinStyle.Round)
offset_polygon(poly, offset, JoinStyle.Square)4. trochoid_along() output geometry changed
src/geo/algo/trochoid.rs:108-109
v0.10.0 produced a sine-wave oscillation perpendicular to the carrier
path. v0.11.0 adds a longitudinal (tangential) component, making it a
true trochoidal loop where the tool reverses direction in each cycle:
// v0.10.0 — simple lateral sine wave
let x = pos.x + lateral * normal.x;
let y = pos.y + lateral * normal.y;
// v0.11.0 — true trochoidal loop
let longitudinal = loop_radius * theta.sin();
let x = pos.x + lateral * normal.x + longitudinal * tangent.x;
let y = pos.y + lateral * normal.y + longitudinal * tangent.y;This improves chip evacuation and limits tool engagement angle, but the
output path is completely different from v0.10.0 — expect longer
paths with backward/forward motion. Tests that assert exact point
positions on trochoidal paths will fail.
5. ScanMode enum variants renamed to UPPER_CASE
src/python/ops/raster.rs:26-28
PEP8 convention — enum members now use UPPER_CASE:
# v0.10.0
ScanMode.Segmented
ScanMode.FullSweep
# v0.11.0
ScanMode.SEGMENTED
ScanMode.FULL_SWEEPAll default parameters in rasterize_mask_lines, rasterize_mask_scan,
rasterize_multi_pass, and rasterize_power_modulation default to
ScanMode.SEGMENTED (same value, just renamed).
No Rust-level changes required — the Rust enum variants remain
Segmented / FullSweep; only the Python-facing names were updated via
#[pyo3(name = "...")].
Python code using ScanMode.Segmented or ScanMode.FullSweep must be
updated to the uppercase forms.
v0.10.0
v0.10.0 — CNC generalization & geometry primitives
This release generalizes the API from laser-specific terminology to generic CNC machining terms and introduces new geometry generation primitives.
Migration Guide
1. State — renamed fields
| Old field | New field |
|---|---|
state.air_assist (bool) |
state.coolant (CoolantMode) |
state.cut_speed |
state.feed_rate |
state.travel_speed |
state.rapid_rate |
state.active_laser_uid |
state.active_head_uid |
State.__init__ keyword args renamed accordingly.
2. air_assist → CoolantMode enum
The boolean air_assist is replaced by CoolantMode in raygeo.ops.state:
from raygeo.ops.state import CoolantMode
# Before
state.air_assist = True
ops.enable_air_assist(False)
# After
state.coolant = CoolantMode.AIR
ops.set_coolant(CoolantMode.OFF)Variants: OFF, FLOOD, MIST, AIR.
3. Ops builder methods — renamed
| Old | New |
|---|---|
set_cut_speed(speed) |
set_feed_rate(feed_rate) |
set_travel_speed(speed) |
set_rapid_rate(rapid_rate) |
set_laser(uid) |
set_head(uid) |
enable_air_assist(bool) |
set_coolant(CoolantMode) |
speed(idx) |
rate(idx) |
laser_uid(idx) |
head_uid(idx) |
get_frame(power=, speed=) |
get_frame(power=, feed_rate=) |
4. Time estimation — renamed parameters
# Before
ops.estimate_time(default_cut_speed=..., default_travel_speed=...)
# After
ops.estimate_time(default_feed_rate=..., default_rapid_rate=...)Same for estimate_command_times().
5. CommandType — renamed variants
| Old | New |
|---|---|
SET_CUT_SPEED |
SET_FEED_RATE |
SET_TRAVEL_SPEED |
SET_RAPID_RATE |
SET_LASER |
SET_HEAD |
ENABLE_AIR_ASSIST |
(removed) |
DISABLE_AIR_ASSIST |
(removed) |
New variant: SET_COOLANT.
6. CommandInfo — renamed properties
| Old | New |
|---|---|
.speed |
.feed_rate |
New: .rapid_rate, .spindle_rpm, .coolant.
7. Serialization format
Dict/JSON/numpy serialization field names changed to match new naming. Old serialized data is not backward-compatible.
8. allow_rapid_change()
Now compares coolant instead of air_assist.
New Features
- Geometry primitives:
raygeo.geo.algo.helix,.ramp,.trochoid,.offset(concentric offsets) polyline_to_ops()— convert polylines to Opslink_passes()— link passes with retract/stay-down strategiesfind_pass_entry()/find_pass_exit()— consolidated entry/exit detectionState.spindle_rpmfield +set_spindle_rpm()builderState.coolantfield +set_coolant()builder
Internal
- Codebase refactoring: decomposed large functions, consolidated entry/exit logic
- Added
rustfmt.tomlwith 80-char line width - Makefile dependency installation
v0.9.0
What's New
3D Polygon Operations
- Add 3D polygon boolean and offset wrappers, including plane-offset support
- Add 3D analytical and transform polygon wrappers with full API documentation
- Add
simplify_polylinefor 3D polylines
2D/3D Separation & Architecture
- Implement 2D/3D separation with planar-only docs, Z-fix in offset, projection helpers, 2D clipping split, planar namespace, and tests
- Upgrade
Command::Arcfrom 2D to 3D (center_offset: Point3D,normal: Point3D)
Breaking Change
- Replace custom
Point/Point3Dstructs withglam::DVec2/glam::DVec3type aliases
Improvements
- Promote
spatial_grid→spatial_grid2dfromnest2dtogeo::algo - Deduplicate
nfp_convex_fastby routing tominkowski2d::get_no_fit_polygon
Bug Fixes
- Fix
perpendicular_3dhandedness and endpoint offset direction
Documentation
- Improve API doc generation with multi-line param/returns descriptions, PEP8 signature wrapping, shorter type names, and Python code blocks
- Return value descriptions are now in tables, fix notation markup
- Add API doc visualizations for polygon3d functions
raygeo v0.8.0
What's Changed
SVG processing
- Add
extract_svg_metadata(),parse_svg_length(),svg_length_to_mm(), andsvg_length_to_px()helpers. - Add
svg_string_to_geometry_by_layer()— extract per-layer geometry from SVG strings. - Add unit conversion helpers to the
SvgMetadataPython class. - Fix SVG arc import/export bugs and derive large-arc flag at export.
- Remove
BORDER_SIZEfrom SVG coordinate transform.
Image preprocessing (new module)
- Add
preprocessmodule with Otsu thresholding and connected-component analysis. - Add
denoise_binary()andcompute_adaptive_threshold().
Scanline / rasterisation
- Add
extract_zero_power_segments()for zero-power segment extraction from scanlines. - Add
transform_to_cylinder()andrasterize_scanlines().
Geometry / fitting
- Add
convert_arcs_to_beziers()for arc-to-bezier conversion. - Remove redundant
create_arc_cmdandcreate_line_cmdfrom the fitting module.
Documentation
- Add complexity documentation to each API function.
- Add many more visual examples and auto-generated doc images.
- Add a visualization for
apply_minimum_run_length().
Full Changelog: v0.7.1...v0.8.0
v0.7.1
What's Changed
Math engine
- Integrate glam math crate — replace manual matrix operations,
Point/Point3Doperators, removemat4_mul. - Fix
map_geometry_to_framematrix column ordering.
SVG parsing
- Use svgtypes crate for SVG path data parsing instead of custom tokenizer.
Geometry / ops
- Fix travel path optimizer not respecting the "flip" flag.
- Refactor
is_bezier_flatextraction fromlinearize_bezier_adaptive, use explicit stack. - Refactor add mutable buffer params to
linearize,smooth, and intersection functions. - Unconditionally compile ops modules (lead_in_out, merge_lines, overscan, tabs, transform).
Documentation
- Add docs and auto-generated visual example images.
- Add more visual examples, improve existing ones, fix tables in API docs.
- Concave hull visual test now allows uploading an SVG.
- Add showcase image to README.
Full Changelog: https://github.com/rayforge/raygeo/compare/v0.7.0...v0.7.1