@@ -18,25 +18,16 @@ set = query(sys, MultiOrderCoverage(polygon); maxcells = 10) # cardinality firs
1818
1919# The two modes
2020
21- `level` is accuracy first. Traversal is depth first: it emits a cell contained
22- by the target and recurses through boundary crossings, to the requested level;
23- cells still crossed there are emitted too, so the set covers the target rather
24- than being covered by it. The cardinality is whatever the outline needs.
25-
26- `maxcells` is cardinality first — "ten cells that cover California, or a
27- hundred". Refinement is coarsest first over the crossing cells, a level at a
28- time; a cell whose replacement would not fit is kept whole and the search moves
29- on. A seed already larger than the budget is the one set returned over it. The
30- depth is then whatever the budget bought, and varies from branch to branch.
31-
32- Neither mode approximates the other: a `level` set is the exact answer at a
33- fixed depth, a `maxcells` set the best a fixed cardinality can say, with the
34- deepest level it reached as its reference level. The keywords are mutually
35- exclusive; [`query`](@ref) states the rules.
36-
37- [`iscontained`](@ref) reports which emissions were *proven* to fit — a cell
38- emitted at the deepest level is never asked; [`coarsest_contained`](@ref) is the
39- accessor that uses it.
21+ `level` is accuracy first: refine every boundary crossing down to `level`, and
22+ the cardinality is whatever the outline needs. `maxcells` is cardinality
23+ first: crossing cells refine coarsest first, a cell whose replacement would
24+ not fit is kept whole, and the depth is whatever the budget bought. A `level`
25+ set is the exact answer at a fixed depth, a `maxcells` set the best a fixed
26+ cardinality can say. The keywords are mutually exclusive; [`query`](@ref)
27+ documents both modes, their edge cases and their guarantees.
28+
29+ [`iscontained`](@ref) reports which emissions were *proven* to fit;
30+ [`coarsest_contained`](@ref) is the accessor that uses it.
4031
4132!!! warning "Coverage is a statement about the leaves, not about the drawn cells"
4233 The guarantee is at the deepest level: every cell there that meets the
@@ -46,16 +37,13 @@ accessor that uses it.
4637 congruent.
4738
4839 The union of the emitted polygons is not that region. Replacing a subtree
49- by its root swaps the subtree's footprint for the root's, and the two agree
50- only under congruent refinement: HEALPix, S2 and ISEA4R tile; on a
51- state-sized target the slivers cover under 2% of it on IGEO7, 15% on H3 and
52- 30% on A5 — the bounds [`query`](@ref) states and its suite asserts. Draw a
53- set as *which cells were chosen*; expand it before computing with it as a
54- region.
55-
56- The same non-congruence runs the other way: a member's descendants may lie
57- outside the target, inside a hole in it for instance, so the expansion
58- over-covers exactly where the refinement does.
40+ by its root swaps the subtree's footprint for the root's, and the two
41+ agree only under congruent refinement (HEALPix, S2, ISEA4R) — the bounds
42+ [`query`](@ref) states and its suite asserts. Draw a set as *which cells
43+ were chosen*; expand it before computing with it as a region. The same
44+ non-congruence runs the other way: a member's descendants may lie outside
45+ the target — inside a hole, for instance — so the expansion over-covers
46+ exactly where the refinement does.
5947"""
6048struct MultiOrderCoverage{T}
6149 target:: T
@@ -79,11 +67,10 @@ target — not which ones do; that docstring draws the line.
7967[`cell_polygon`](@ref) and [`cell_polygons`](@ref) read mixed-level geometry
8068without the caller resolving a level grid per cell.
8169
82- The REFERENCE LEVEL is the depth the set speaks about: the `level` the query was
83- given, or — in `maxcells` mode, where no depth was asked for — the deepest level
84- the budget reached. It is the default expansion level for
85- [`level_ranges`](@ref), [`cellindices`](@ref) and `CellLookup`, and the level at
86- which the covering guarantee is stated.
70+ The REFERENCE LEVEL is the depth the set speaks about — the `level` the query
71+ was given, or in `maxcells` mode the deepest level the budget reached. It is
72+ the default expansion level for [`level_ranges`](@ref), [`cellindices`](@ref)
73+ and `CellLookup`, and the level the covering guarantee is stated at.
8774
8875!!! note "Expansion needs sorted subtrees"
8976 `level_ranges` throws where [`has_sorted_subtrees`](@ref) is `false` (A5),
@@ -158,28 +145,25 @@ crossing cell for level after level and the budget never binds.
158145
159146Every point of the target lies inside one of the emitted cells. The seed is
160147the coarsest cells meeting the target; refinement replaces a crossing cell by
161- its meeting children. Non-congruent refinement descends through missing cells
162- too, as `level` mode does, so a crossing cell with no meeting child is dropped
163- for the cells that do cover its share — and its reserved slot pays for what the
164- walk still owes: cells found and not afforded, or the cell itself kept whole
165- where its share was never certified.
166-
167- It is EXACT, at every budget, on the three systems whose four children tile
168- their parent: HEALPix, S2 and ISEA4R. Where children do not tile their parent it
169- degrades in the way [`MultiOrderCoverage`](@ref)'s warning already describes, and
170- for the same reason — replacing a cell by its children swaps one footprint for
171- another. Measured on a state-sized outline as the fraction of the target lying
172- in no emitted cell: under 2% on IGEO7, 3% on its authalic wrap, 15% on H3 and
173- 30% on A5.
174-
175- The LEAF statement `level` mode makes — every reference-level cell meeting the
176- target is a member or the descendant of one — is a law here on those same three
177- systems only. Elsewhere the budget makes the same overhang descent but has no
178- fixed depth to carry it to: where it stops paying, the search goes on only for
179- the dropped cells whose share is still unproven. On the same outline the leaf
180- statement misses under 1% of the target on IGEO7, 2% on its authalic wrap and
181- on H3, and 18% on A5. `test/systems/crosssystem/multiorder_budget.jl` asserts
182- both statements' bounds per system, at three budgets and on four targets.
148+ its meeting children, descending through missing cells as `level` mode does. A
149+ crossing cell with no meeting child is dropped for the cells that cover its
150+ share, and its reserved slot pays for what the walk still owes: cells found
151+ and not afforded, or the cell itself kept whole where its share was never
152+ certified.
153+
154+ Two statements, both EXACT at every budget where four children tile their
155+ parent (HEALPix, S2, ISEA4R), and measured elsewhere on a state-sized outline
156+ as the fraction of the target missed:
157+
158+ | statement | IGEO7 | authalic | H3 | A5 |
159+ |:---------------------------------------------------------|------:|---------:|----:|----:|
160+ | union — the target lies in the emitted polygons | 2% | 3% | 15% | 30% |
161+ | leaf — every reference-level cell meeting the target is a member or descends from one | 1% | 2% | 2% | 18% |
162+
163+ Where the leaf statement is inexact the budget has no fixed depth to carry the
164+ overhang descent to: where it stops paying, the search goes on only for the
165+ dropped cells whose share is still unproven. The suite asserts both bounds per
166+ system, at three budgets and on four targets.
183167
184168What a budget does NOT buy is a tight picture of the target: at ten cells the
185169set over-covers California by a wide margin, and [`iscontained`](@ref) says so.
@@ -229,9 +213,7 @@ function _multi_order(sys::AbstractHierarchicalGridSystem, target_value, maxleve
229213 # Emissions at `maxlevel` are never asked, so `false` there means unproven,
230214 # not outside. `iscontained` documents the asymmetry.
231215 contained = BitVector ()
232- # One level grid per level, built once rather than per visited cell: the
233- # traversal touches every level from the roots down, and `levelgrid` is
234- # cheap but not free.
216+ # One grid per level, built once: `levelgrid` is cheap but not free.
235217 top = first (levels (sys))
236218 grids = [levelgrid (sys, l) for l in top: maxlevel]
237219 for c in rootcells (sys)
@@ -241,12 +223,10 @@ function _multi_order(sys::AbstractHierarchicalGridSystem, target_value, maxleve
241223end
242224
243225function _coverage_visit! (cells, contained, sys, target, c, maxlevel:: Int , grids, top:: Int )
244- # Only `node_extent` may prune descendants; child geometry can overhang its
245- # parent. Exact cell geometry determines emission, not descent.
246- #
247- # Both prunes read that extent: the target's cap first, at one distance,
248- # then the boundary-arc proof, which is what keeps the traversal
249- # output-sensitive when the cap is loose or the whole sphere.
226+ # Only `node_extent` may prune descent — child geometry can overhang its
227+ # parent; exact cell geometry decides emission only. The one-distance cap
228+ # test runs before the boundary-arc proof, keeping the traversal
229+ # output-sensitive on a loose or whole-sphere cap.
250230 extent = node_extent (sys, c)
251231 Extents. intersects (target. cap, extent) || return nothing
252232 _subtree_outside (target, extent) && return nothing
@@ -282,9 +262,8 @@ function _sorted_cell_set(sys::AbstractHierarchicalGridSystem, cells::Vector{ID}
282262 return MultiOrderCellSet {typeof(sys),ID} (sys, cells[perm], keys[perm],
283263 contained[perm], reference_level)
284264 end
285- # No curve intervals to order by; `(level, id)` is the documented fallback,
286- # and the keys become the cells' own indices within their level, which is
287- # still a total order but not a curve order.
265+ # `(level, id)` is the documented fallback; the keys are the cells' own
266+ # within-level indices — a total order, not a curve order.
288267 perm = sortperm (cells; by= c -> (level (c), c))
289268 ordered = cells[perm]
290269 keys = [something (globalindex (levelgrid (sys, level (c)), c), 0 ) for c in ordered]
0 commit comments