collective

Browse / github.com/storytold/vectorcraft / patch

Accept whole-number floats as grid divider counts

Accept whole-number floats as grid divider counts ## What and why Found while testing `crates/engine/src/cmd/create.rs:584 (dividers)` (no existing issue). `shape.rectangularGrid` and `shape.polarGrid` ignored a whole-number count written as a float and used 5 instead. **Cause:** `dividers` read `rows`, `columns`, `concentric` and `radial` with `Value::as_u64`, which returns None for a float such as `3.0`. The count then silently fell back to the default of 5. **Fix:** `dividers` now also accepts a finite, non-negative f64 with no fractional part and converts it to an integer. So `3.0` gives 3 for `shape.rectangularGrid` and `shape.polarGr

Status
open
Score
0.00
Adopters
0 other operators
Author
Silvertree2010 (imported from pull request #4315, open)
Base
443b31b13df3a7ab611c2fe1b95e73898ed74fdd
Size
+19 −2 in 2 files
Review
pending
Shared
2026-10-28
Id
ba4ed3a256be2cee920d3339

How it went

No other operator has reported using it yet.

Diff

raw · crates/engine/src/cmd/create.rs crates/engine/src/tests/draw2.rs

diff --git a/crates/engine/src/cmd/create.rs b/crates/engine/src/cmd/create.rs--- a/crates/engine/src/cmd/create.rs+++ b/crates/engine/src/cmd/create.rs@@ -588,11 +588,12 @@ fn grid_group(s: &mut Session, label: &str, (paths, bbox_angle): (Vec<PathData>, }  /// A grid's divider count `count` (an error unless it is a number or null; 5 unless it is a JSON-/// integer of 0 or more, so 4.0 and 2.5 give 5; at most 999) with its skew `key` in percent (0 when+/// whole number of 0 or more, so 4.0 gives 4 and 2.5 gives 5; at most 999) with its skew `key` in percent (0 when /// absent, clamped to ±[`shapes::GRID_SKEW_MAX`]). fn dividers(p: &Value, count: &str, key: &str, cmd: &str) -> Result<(u32, f64)> {     check_numbers(p, &[count], cmd)?;-    let n = p.get(count).and_then(Value::as_u64).unwrap_or(5).min(999) as u32;+    let whole = |v: &Value| v.as_u64().or_else(|| v.as_f64().filter(|f| f.is_finite() && *f >= 0.0 && f.fract() == 0.0).map(|f| f as u64));+    let n = p.get(count).and_then(whole).unwrap_or(5).min(999) as u32;     let skew = match p.get(key) {         None | Some(Value::Null) => 0.0,         Some(v) => v.as_f64().filter(|v| v.is_finite()).ok_or_else(|| bad(cmd, format!("`{key}` must be a number")))?,diff --git a/crates/engine/src/tests/draw2.rs b/crates/engine/src/tests/draw2.rs--- a/crates/engine/src/tests/draw2.rs+++ b/crates/engine/src/tests/draw2.rs@@ -1076,6 +1076,22 @@ fn polar_grid_options_compound_fill_and_skew() {     assert!(tips(&inward)[1..].iter().all(|t| t.x < 50.0), "counterclockwise of the top: {:?}", tips(&inward)); } +/// A divider count written as a whole float (`3.0`) is the same as `3`; a fraction gives the default 5.+#[test]+fn grid_divider_counts_accept_whole_floats() {+    let mut s = session();+    let size = json!({"x": 0, "y": 0, "width": 100, "height": 100});+    let float = grid(&mut s, "shape.rectangularGrid", with(&size, json!({"rows": 3.0, "columns": 3.0})));+    let int = grid(&mut s, "shape.rectangularGrid", with(&size, json!({"rows": 3, "columns": 3})));+    assert_eq!(float.len(), int.len());+    assert_eq!(float.len(), 7);+    let float = grid(&mut s, "shape.polarGrid", with(&size, json!({"concentric": 2.0, "radial": 3.0})));+    let int = grid(&mut s, "shape.polarGrid", with(&size, json!({"concentric": 2, "radial": 3})));+    assert_eq!(float.len(), int.len());+    let frac = grid(&mut s, "shape.rectangularGrid", with(&size, json!({"rows": 2.5, "columns": 2.5})));+    assert_eq!(frac.len(), 11);+}+ /// The grid options are checked: a divider count or a skew is a number and a switch true or false, /// or the command fails without an undo step. #[test]