Skip to content

feat: mark_sf(merge = TRUE) dissolves adjacent same-fill regions - #142

Merged
schochastics merged 1 commit into
mainfrom
feat/wi9-choropleth-merge
Aug 1, 2026
Merged

feat: mark_sf(merge = TRUE) dissolves adjacent same-fill regions#142
schochastics merged 1 commit into
mainfrom
feat/wi9-choropleth-merge

Conversation

@schochastics

Copy link
Copy Markdown
Collaborator

Wires the merged-choropleth half of WI-9: vl_path_op() as region geometry. (The other half — clipping-as-geometry — stays a documented follow-up, as agreed; it's an architectural change to the viewport-mask pipeline and only benefits vector marks.)

What

A choropleth built from many small features (counties grouped into regions) draws a border between every feature, meshing each colour block with internal seams. mark_sf(merge = TRUE) dissolves each same-fill style group into one region.

In .emit_sf, each feature's rings become an operand (interpreted even-odd, so holes and multipart features stay correct) and are folded with vellum::vl_path_op(op = "union") into a single winding path — shared interior borders gone, one crisp outline per region, exact in PDF. Raw coordinates are unioned and the result mapped once (the same map-once discipline as the batched emit), reusing the venn.R unwrap/rewrap pattern.

Boundaries

  • < 2 features in a group → nothing to union → falls back to the ordinary batched emit (single-feature no-op is byte-identical).
  • Interactive layer → merge is skipped, since dissolving the features would drop the per-feature keys a tooltip needs.

Verification (WI-0)

Rendered and looked at plain vs merged NC choropleths (internal county borders present → dissolved to one outline per region); confirmed a merged map renders to a valid PDF (%PDF-, crisp geometry) and through vellumwidget::as_widget(); inst/examples/33-merged-regions.R runs end to end.

Deterministic tests in test-sf-merge.R: two adjacent squares sharing an edge lose that edge when merged (border-pixel count halves), distinct fills are untouched, a single feature is a no-op, and an NC choropleth renders to PNG/PDF/scene. Full suite [ FAIL 0 | WARN 1 pre-existing | SKIP 0 | PASS 2880 ].

No new exports (a merge = argument on mark_sf()); requires the already-declared vellum >= 0.6.5.

🤖 Generated with Claude Code

A choropleth built from many small features (counties grouped into regions)
draws a border between every feature, meshing each colour block with internal
seams. `merge = TRUE` dissolves each same-fill style group into one region:
each feature's rings are unioned with vellum::vl_path_op() (interpreted
even-odd, so holes and multipart features stay correct), producing a single
winding path whose shared interior borders are gone -- one crisp outline per
region, exact in PDF, no double-stroked seams.

Raw coordinates are unioned and the result mapped once (the same map-once
discipline as the batched emit). With fewer than two features in a group there
is nothing to union, so it falls back to the ordinary emit; and it is skipped
on an interactive layer, where the per-feature keys must survive.

Docs: NEWS, a spatial-and-networks section, inst/examples/33-merged-regions.R,
tests in test-sf-merge.R.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@schochastics
schochastics merged commit c159fa6 into main Aug 1, 2026
2 checks passed
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