Skip to content

Carry payloads in RTree and dissolve the relate edge-index side-tables#440

Closed
asinghvi17 wants to merge 2 commits into
relateng-cleanupsfrom
relateng-payload-tree
Closed

Carry payloads in RTree and dissolve the relate edge-index side-tables#440
asinghvi17 wants to merge 2 commits into
relateng-cleanupsfrom
relateng-payload-tree

Conversation

@asinghvi17

Copy link
Copy Markdown
Member

Stacked on #439 (base branch relateng-cleanups). The "payload-carrying tree" follow-up from the substrate audit, in two commits.

RTree carries the collection it indexes. Queries already return indices into the input collection, but the tree threw the collection away — so every consumer had to carry a parallel payload vector alongside the tree (JTS trees carry their items; the index-returning design needs the vector to live somewhere). It now lives on the tree as tree.data. Two supporting changes:

  • An extents kwarg supplies precomputed extents (one per element, in order) for payload elements that carry no extent of their own, or extents computed in another coordinate space — the relate kernel computes segment extents over kernel-converted points, which GI.extent on the payload could never reproduce.
  • Unsorted loading returns Base.OneTo from loadorder, so the constructor skips the identity permutation and aliases the extents vector as the leaf level. Zero copies — the same build cost as NaturalIndex, making RTree(Unsorted(), ...) a true natural index. (RTreeNode is reparametrized on the concrete tree type since RTree gained type parameters.)

The relate edge index dissolves its side-tables. _relate_edge_index(m, ss_list) now returns a natural-order RTree whose data is each leaf's (string index, segment index) owner, built from the flattened segment extents (or nothing for empty lists). The three dual-traversal sites map hits through tree.data[i] instead of a parallel owners vector, and PreparedEdgeIndex — a struct pairing exactly that tree with exactly that vector — dissolves into the tree itself: PreparedRelate.edge_tree is now the RTree or nothing.

This sets up the interval-tree follow-up: SortedPackedIntervalRTree is a midpoint-sorted packed tree over 1-D intervals carrying segment payloads, which is RTree(STR(), segs; extents = y_intervals) — STR in one dimension is the midpoint sort.

Tests

New FlexibleRTrees testset covers payload round-trips under reordering, the Unsorted zero-copy aliasing, collected non-vector input, and the extents/data length mismatch throw; the existing brute-force query sweeps now exercise the zero-copy Unsorted path. RelateNG: engine + prepared mode, edge intersector accelerator differentials, spherical end-to-end, JTS XML conformance, LibGEOS fuzz, and the allocation budget (256-vertex pairs exceed the tree threshold, so the budget covers the new build path) all green.

🤖 Generated with Claude Code

asinghvi17 and others added 2 commits July 13, 2026 14:34
Queries return indices into the input collection, but the tree previously
threw the collection away — every consumer had to carry a parallel payload
vector alongside the tree. Keep it as `tree.data` instead, and accept an
`extents` vector for payload elements that carry no extent of their own
(or extents computed in another coordinate space).

`Unsorted` loading now returns `Base.OneTo` from `loadorder`, so the
constructor skips the identity permutation and aliases the extents vector
as the leaf level — zero copies, matching `NaturalIndex`'s build cost.
`RTreeNode` is reparametrized on the concrete tree type since `RTree`
gained type parameters.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`_relate_edge_index(m, ss_list)` now returns a natural-order `RTree`
whose data is the (string index, segment index) owner of each leaf, built
directly from the flattened segment extents. This replaces the
`NaturalIndex` + parallel `owners` vector at the three dual-traversal
sites, and `PreparedEdgeIndex` — a pair of exactly those two — dissolves
into the tree itself (`PreparedRelate.edge_tree` is now the `RTree` or
`nothing`).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asinghvi17

Copy link
Copy Markdown
Member Author

Collapsed into #416 for whole-piece review — the relateng branch was fast-forwarded to this stack's tip, so #416 now contains these commits. This PR stays as a focused, reviewable diff of its layer (see the review map in #416).

@asinghvi17 asinghvi17 closed this Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant