mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-26 10:47:11 -06:00
G11: the grid budget counts an item's distinct cells; parity row and evidence
CodeRabbit on #4080: `needed` summed footprint pieces before insertion deduplicated them, so on a degenerate grid (ten collinear lines, 4,096 pieces each in ten cells) every item exceeded the budget and went to the scanned list, making the per-cell assertion vacuous. The cells are now collected in piece order and consecutive repeats dropped before the budget check and the filing; the horizontal fixture asserts `rest` is empty and that the lines are filed. docs/target-app-parity.md: the Path operations area row, the Shape Builder row and the evidence list record the bounded index (scores unchanged). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014gCpjL3yUhaH3jRp7ksufh
This commit is contained in:
committed by
bflatastic
co-authored by
Claude Fable 5.1
parent
6f8ac34f38
commit
a5806c8caa
@@ -182,26 +182,27 @@ impl<T> RectIndex<T> {
|
||||
}
|
||||
// The item's cells, counted before they are filed: past the grid's budget the item,
|
||||
// and the ones after it, are scanned instead (the index stays bounded in memory).
|
||||
let needed: usize = spans.iter().map(|(xs, ys)| (xs.end() - xs.start() + 1) * (ys.end() - ys.start() + 1)).sum();
|
||||
if !scan && needed > budget {
|
||||
// Pieces of one segment that fall in the same cell (a degenerate grid's tiny cells)
|
||||
// count and file it once: the pieces come in order, so the repeats are consecutive.
|
||||
let mut mine: Vec<usize> = if scan {
|
||||
Vec::new()
|
||||
} else {
|
||||
spans.iter().flat_map(|(xs, ys)| ys.clone().flat_map(|y| xs.clone().map(move |x| y * cols + x))).collect()
|
||||
};
|
||||
mine.dedup();
|
||||
if !scan && mine.len() > budget {
|
||||
scan = true;
|
||||
}
|
||||
if scan {
|
||||
rest.push(i);
|
||||
continue;
|
||||
}
|
||||
budget -= needed;
|
||||
for (xs, ys) in spans {
|
||||
for y in ys {
|
||||
for x in xs.clone() {
|
||||
// Pieces of one segment that fall in the same cell (a degenerate grid's
|
||||
// tiny cells) file it once: the item's pieces come in order.
|
||||
if let Some(c) = cells.get_mut(y * cols + x)
|
||||
&& c.last() != Some(&index)
|
||||
{
|
||||
c.push(index);
|
||||
}
|
||||
}
|
||||
budget -= mine.len();
|
||||
for c in mine {
|
||||
if let Some(c) = cells.get_mut(c)
|
||||
&& c.last() != Some(&index)
|
||||
{
|
||||
c.push(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2153,7 +2154,9 @@ mod tests {
|
||||
let line = PathSeg::Line(kurbo::Line::new((0.0, 0.0), (1000.0, 0.0)));
|
||||
let items: Vec<_> = (0..10).map(|k| (line.bounding_box(), (line, k))).collect();
|
||||
let index = RectIndex::with_footprint(items, |r, (s, _), cell| segment_footprint(r, s, cell));
|
||||
assert!(index.rest.is_empty(), "every line is in the grid, {} scanned", index.rest.len());
|
||||
assert!(index.cells.iter().all(|c| c.len() <= 10), "{:?}", index.cells.iter().map(Vec::len).collect::<Vec<_>>());
|
||||
assert!(index.cells.iter().map(Vec::len).sum::<usize>() >= 10, "the lines are filed");
|
||||
assert_eq!(index.at(Point::new(500.0, 0.0), 0.1).count(), 10);
|
||||
// 4,096 coincident vertical segments: one column, a row per segment, every segment along
|
||||
// every row would be 16 million references; the budget keeps it to a few hundred per item.
|
||||
|
||||
@@ -106,7 +106,7 @@ dominate; 3D, graphs and automation are specialist). They sum to 105. Feature de
|
||||
|---|---:|---:|---|---:|---|
|
||||
| Selection, transform & align tools | 6 | 85% | Direct Selection segment click/Delete corrected (#1278); open-path anchor Delete keeps gaps; Select › Start Global Edit finds the paths, compound paths and symbol instances of the selected object's shape (Appearance, Size and artboard options) and gives an edit of one to all of them in proportion, as one undo step (#3521); remaining: Free Transform/Scale/Reflect along a rotated box, Global Edit of similar groups and excluding a match with Shift-click, transform nuances (no-op anchor Align history regression-tested, #1180 follow-up) | 4–6 | estimated; Global Edit regression-tested (`crates/engine/src/tests_globaledit.rs`; Quick Action, menu label and Escape in `panels::properties::tests::start_global_edit_quick_action_and_escape`) |
|
||||
| Drawing tools (Pen, Curvature, Pencil, shapes, Shaper) | 7 | 85% | Shaper construction widget, Pencil/Pen nuances, Blob Brush options, Touch Type, Dimension tool; see [ui-parity.md](ui-parity.md) | 8–13 | estimated; Curvature point display regression-tested (#1236, in part); Polygon/Star exact-size count persistence regression-covered; Live Corners' Relative rounding done (#3091), score unchanged |
|
||||
| Path operations, Pathfinder, Shape Builder, Live Paint | 5 | 80% | Shape Builder on the reporter's file (#937: art past 4,096 segments is cut by lines again; unconfirmed on the file itself), its gap detection and options; Live Paint Gap Options | 4–8 | estimated (lowered from 86%: open issues); compound attributes regression-tested (#1197); single-result source names survive SVG export/import (#1293), with [SVG ID semantics](https://www.w3.org/TR/SVG2/struct.html#IDAttribute) and original-shape tests; Simplify component selection and preview regression-tested (#1272); Simplify of a Direct Selection part of a path regression-tested (`tests_simplify_part.rs`); Divide open-cutting-path geometry and appearance regression-tested (#1307) |
|
||||
| Path operations, Pathfinder, Shape Builder, Live Paint | 5 | 80% | Shape Builder on the reporter's file (#937: art past 4,096 segments is cut by lines again; unconfirmed on the file itself), its gap detection and options; Live Paint Gap Options | 4–8 | estimated (lowered from 86%: open issues); compound attributes regression-tested (#1197); single-result source names survive SVG export/import (#1293), with [SVG ID semantics](https://www.w3.org/TR/SVG2/struct.html#IDAttribute) and original-shape tests; Simplify component selection and preview regression-tested (#1272); Simplify of a Direct Selection part of a path regression-tested (`tests_simplify_part.rs`); Divide open-cutting-path geometry and appearance regression-tested (#1307); the Shape Builder's edge-source grid is bounded in memory and files a segment once per cell (`planar.rs` test `rect_index_holds_a_bounded_number_of_references`) |
|
||||
| Colour, swatches, gradients, patterns, mesh, recolor | 7 | 92% | 30.0's gradient dither, perceptual blending and gradient presets; freeform and mixed spot/process gradients in SVG/PDF | 4–7 | estimated (lowered from 96%: target moved); unpainted zero-width stroke restoration fixed (#1253), score and hours unchanged; Eyedropper source reads regression-tested (#1251) |
|
||||
| Path operations, Pathfinder, Shape Builder, Live Paint | 5 | 80% | Shape Builder misses planar regions in real files (#937), its gap detection and options; Live Paint Gap Options | 4–8 | estimated (lowered from 86%: open issues); compound attributes regression-tested (#1197); single-result source names survive SVG export/import (#1293), with [SVG ID semantics](https://www.w3.org/TR/SVG2/struct.html#IDAttribute) and original-shape tests; Simplify component selection and preview regression-tested (#1272); Simplify of a Direct Selection part of a path regression-tested (`tests_simplify_part.rs`); Divide open-cutting-path geometry and appearance regression-tested (#1307) |
|
||||
| Colour, swatches, gradients, patterns, mesh, recolor | 7 | 92% | 30.0's gradient presets (gradient dither and perceptual blending are done); freeform and mixed spot/process gradients in SVG/PDF | 4–7 | estimated; Recolor model selection is available through the engine and MCP only (#2520); the dialog retains its existing controls (lowered from 96%: target moved); unpainted zero-width stroke restoration fixed (#1253), score and hours unchanged; Eyedropper source reads regression-tested (#1251); screen-bounded Recolor Edit chip list (#3416), score and hours unchanged |
|
||||
@@ -252,7 +252,7 @@ Depth here is "does the basic use work", not the area's full score.
|
||||
| Type: point and area text, font, size | 8 | 88% | font menu with previews; Hyphenation… and Justification… options per paragraph (#2310, #2755) |
|
||||
| Align, group, arrange | 6 | 95% | |
|
||||
| Layers, basic | 4 | 85% | Layers panel rework; no row context menus |
|
||||
| Shape Builder | 5 | 70% | beginners lean on it; region detection failed on art of thousands of segments (#937's reproduced case, fixed; unconfirmed on the reporter's file) |
|
||||
| Shape Builder | 5 | 70% | beginners lean on it; region detection failed on art of thousands of segments (#937's reproduced case, fixed, and its edge-source grid is bounded in memory; unconfirmed on the reporter's file) |
|
||||
| Pathfinder | 4 | 95% | exact booleans |
|
||||
| Place images, Image Trace | 4 | 85% | 13 trace presets |
|
||||
| Export PNG/JPG/SVG/PDF, print | 8 | 92% | Art Optimized supersample closes Asset Export ghost borders (#983 / #1037) |
|
||||
@@ -681,6 +681,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
With Pick Color From Artwork, a merged shape takes the appearance, opacity and blending mode of the object where the drag starts, else of the object where it ends, else of the front-most selected object, as the [Shape Builder combine page](https://web.archive.org/web/20251006211643/https://helpx.adobe.com/illustrator/desktop/draw-shapes-and-paths/draw-shapes/combine-shapes-with-shape-builder-tool.html) describes. A click in an area that no selected object covers, such as a hole other shapes enclose, takes the front-most selected object's look (`shapeBuilder.merge` `points`: the first point is where the drag starts, and the last point is where it ends).
|
||||
A Shift-drag with the Shape Builder tool draws a rectangular marquee for merging many paths at once, as [Combine shapes with the Shape Builder tool](https://web.archive.org/web/20251006211643/https://helpx.adobe.com/illustrator/desktop/draw-shapes-and-paths/draw-shapes/combine-shapes-with-shape-builder-tool.html) describes: the regions it reaches are shaded while it is drawn and merge into one shape on release, or with Alt they are deleted. The marquee reaches each region whose outline crosses it or has an anchor inside it, and the region that holds the whole marquee; this rule is VectorCraft's own. For Pick Color From Artwork, the marquee's starting corner is where the drag starts and the opposite corner is where it ends (`shapeBuilder.merge` `rect`).
|
||||
Shape Builder pieces on dense hatches (lines at exact 0.25 or 0.5 pt steps across another line) come back one per stretch between crossings, with no speck where the sweep cut a line's two passes a rounding error apart: the planar map contracts the stub between such cuts into one vertex, bounded by each cluster's extent so a run of tiny level segments keeps its length (`crates/pathops/src/planar.rs` tests `a_dense_hatch_at_exact_binary_steps_cuts_each_line_once_per_crossing`, `a_run_of_tiny_level_segments_is_not_contracted_as_stubs`, `a_line_crossed_where_its_two_passes_part_is_cut_once`).
|
||||
The planar map's edge-source grid stays linear in memory on any input: a segment is filed once per cell it crosses, and the grid holds at most a budget of cell references (a few dozen per item plus a few rows' worth), past which the remaining items go to a short scanned list and are still found, so thousands of coincident segments cannot make the index quadratic (`crates/pathops/src/planar.rs` test `rect_index_holds_a_bounded_number_of_references`).
|
||||
The Blob Brush Tool Options have Keep selected and Merge only with selection, both off by default: while Keep selected is off, the blob a stroke draws or merges into is not selected afterwards, and while Merge only with selection is on, a stroke merges only with selected blobs of its color that it touches (`path.blob` `keepSelected` and `mergeOnlySelection`).
|
||||
- **Ruler guides as layer objects:** a guide goes on the current layer, shows, hides, locks and is deleted with it, is listed in the Layers panel (its row selects it) and moves to another layer (`guide.setLayer`, or its row dragged onto that layer's rows); guides on a hidden or locked layer can't be selected, moved or deleted, Duplicate copies a layer's guides and Merge Selected and Flatten Artwork keep them on the merged layer; guides from files saved before guides had layers go on the top visible, unlocked layer when the document opens. Not done: guides stacked among the art of their layer (they are listed above it), a guide row's own eye and lock. Lock Guides also locks the objects made into guides: they can't be selected, moved or deleted (#1543); they are drawn in the guide colour and style of Preferences, and a dragged selection snaps to ruler guides with Smart Guides on (#1583, fixes #1534). The Transform panel shows a selected ruler guide's X or Y, and typing a value moves it (#1659, part of #1597). This is not established by the documentation we could find: the public help pages on guides, rulers and the Transform, Control and Properties panels (read again on 2026-10-14) describe selecting and dragging unlocked guides and the panels' X and Y for a selection, not a guide's position in a panel, and the one public statement of it is a user's [community answer](https://community.adobe.com/questions-652/adding-a-new-custom-guide-785586), which is not documentation. It is kept as a convenience pending the owner's decision, with no parity claim and nothing counted towards a score.
|
||||
- **Releasing ruler guides:** View › Guides › Release Guides turns the selected ruler guides into paths with no fill or stroke. An artboard guide becomes a line across its artboard, and a canvas guide becomes a line across the artboards (`view.guides.release {index?, ids?}`). A Cmd/Ctrl+Shift double-click with the Selection, Direct Selection or Group Selection tool releases the ruler guide or guide path under the pointer.
|
||||
@@ -1099,6 +1100,7 @@ applies to fills). Tests: `color::gradient::tests` (perceptual midpoint, expansi
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-24 | minor | Path operations: the Shape Builder's edge-source grid holds a bounded number of cell references (coincident segments no longer quadratic in memory) and files a segment once per cell; Path operations 80%, Shape Builder 70% unchanged (estimated).; area row and evidence list updated; the budget counts an item's distinct cells, so a degenerate grid's pieces don't send it to the scanned list. |
|
||||
| 2026-10-24 | minor | Path operations: the Shape Builder's edge-source grid holds a bounded number of cell references (coincident segments no longer quadratic in memory) and files a segment once per cell; Path operations 80%, Shape Builder 70% unchanged (estimated). |
|
||||
| 2026-10-25 | minor | Floating panels open in OS windows of their own on the desktop (inside the window on the web and on Wayland); saved layouts from earlier versions convert to the shared docking layout (#4135); scores and estimates unchanged (estimated) |
|
||||
| 2026-10-24 | minor | Recolor Artwork › Assign: double-clicking a row's new color opens the Color Picker over the dialog; its OK sets the row's new color in the model it was picked in (a CMYK mix stays CMYK, RGB becomes CMYK in a CMYK document), Cancel leaves the row as it was. A Lab new color is kept, but a Lab color can't be typed yet: the picker's Lab fields work in RGB, as for fill and stroke (part of #4028; Lab entry, swatch libraries and the row menu remain). Scores and estimates unchanged. |
|
||||
|
||||
Reference in New Issue
Block a user