Add the OverlayNG engine core (phase 2): graph, labeller, and result builders#443
Draft
asinghvi17 wants to merge 3 commits into
Draft
Add the OverlayNG engine core (phase 2): graph, labeller, and result builders#443asinghvi17 wants to merge 3 commits into
asinghvi17 wants to merge 3 commits into
Conversation
Build the half-edge topology graph over phase 1's `NodedArrangement`: - `overlay_label.jl` — faithful `OverlayLabel` port (mutable plain struct, the four edge states, the `is_forward` Left/Right swap on one shared label). - `edge_source.jl` — `EdgeSourceInfo` per ring/line; `depth_delta` derived once from `_ring_material_interior_on_left` (`material_interior_on_left ? -1 : +1`). - `half_edge.jl` — integer-indexed winged-edge substrate (port of `edgegraph.HalfEdge`); bulk-build then sort each node's star once with the exact `rk_compare_edge_dir` comparator. - `overlay_graph.jl` — `MergeEdge` + `Edge.merge` semantics (depth-delta summing with direction flip, collapse detection, hole-role merge), the `EdgeMerger` keyed on the unordered node-id pair, and `OverlayEdge`/`OverlayGraph`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Cover the phase-2a engine core: degree-6 coincidence-merged node ordering (foreign-direction slow path), collinear shared boundary merging to one `OverlayEdge` with correct per-side locations, spherical crossing-node star ordering, the depth-delta / `Edge.merge` algebra (sum, collapse, hole role), the four label states and the `getLocation` `is_forward` swap, and graph invariants on Natural Earth country pairs (both manifolds). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Port the labeller, result builders, and the internal driver on top of the phase-2a graph, completing the OverlayNG engine core. - `overlay_labeller.jl`: `_compute_labelling!` (the five JTS passes in order), `_is_result_of_op` (SYMDIFFERENCE handled natively), result-area marking and duplicate unmarking. - `maximal_edge_ring.jl` + `polygon_builder.jl`: maximal/minimal edge rings with the self-touching minimal-ring split, `linkResultAreaMaxRingAtNode` called ungated (JTS-faithful), and shell/hole nesting via kernel-point containment (`rk_point_in_ring` / indexed locators), never planar even-odd. - `line_builder.jl`, `intersection_point_builder.jl`: result lines and the intersection-only result points. - `overlay_ng.jl`: the driver `_overlay_ng` (input model, `computeEdgeOverlay` phase order, `extractResult` dimensional priority, empty short-circuits) with spherical empty-vs-full disambiguation. All internal (no exports, plain-backtick docstrings); the existing `intersection`/`union`/`difference` are untouched. Line and area inputs are supported in any A x B combination; point inputs raise a clear error (phase 3). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 2 of the OverlayNG port: the engine core — half-edge graph, labeller, and result builders, consuming phase 1's exact
NodedArrangement(#442) and producing overlay results through an internal driver. Stacked on #442 (→ #416 → #434); merge in stack order. Design doc:docs/plans/2026-07-16-overlayng-noding-substrate.md§3 (on the base branch).What's here
Graph layer (
half_edge.jl,edge_source.jl,overlay_label.jl,overlay_graph.jl, ~750 SLOC):edgegraph.HalfEdge): storeso_nextdirectly, bulk-builds and sorts each node star once through the exactrk_compare_edge_dirwithNodeKeyapexes and parent-endpoint direction points — no constructed coordinate enters angular ordering, including at coincidence-merged nodes (foreign directions take the kernel's exact-rational slow path).OverlayLabelported faithfully (plain mutable struct, four states, one shared label per sym pair with the forward/reverse L/R swap).EdgeKeyis not ported (the segment/minor-arc between two nodes is unique;relativeDirectionbecomes an exact integer comparison). Depth deltas derive once per ring from_ring_material_interior_on_left(the material-interior authority landed in Add the OverlayNG noding substrate (phase 1): exact noded arrangements with symbolic nodes #442), so labels are winding-independent by construction andSpherical(; oriented)semantics flow through with no extra plumbing.Engine core (
overlay_labeller.jl,maximal_edge_ring.jl,polygon_builder.jl,line_builder.jl,intersection_point_builder.jl,overlay_ng.jl, ~1,050 SLOC):OverlayLabellerpasses in JTS order (area propagation with side-conflict errors, two linear BFS passes, collapse labelling, disconnected-edge PIP against the original inputs via the indexed locators — both endpoints, never collapsed edges).rk_point_in_ring/ indexed locators) — never planar even-odd on emitted coordinates, so the builders are manifold-correct.LineBuilder(raw noded-edge extraction; JTS's dead merged-line path not ported),IntersectionPointBuilder, and the internal_overlay_ng(m, op, a, b)driver for intersection/union/difference/symmetric difference on both manifolds, including spherical empty-vs-full disambiguation (boundaryless results resolved by locating one input vertex; a full-sphere result throws — unrepresentable under enclosed-region semantics, a documented phase-3 refinement).Nothing is exported and no existing behavior changes — the public opt-in API, point inputs, and the differential-validation harness are phase 3.
Validation
OverlayNGTestcases pass (GEOS topologicalequals+isValidon every result): nested shells, adjacent boxes, touching holes, box/line and polygon/line ops, line/line unions incl. figure-8 and rings, flat-collapse intersection. Skips are principled: the fixed-precision family (snapping/collapse tests) does not apply to a floating-only exact engine by design, andtestTouchingPolyDifferenceis a known substrate limitation (the noder does not self-node a single input, so a hole touching its own shell yields a correct-area but non-simple split — tracked for phase 3).area(A∪B)+area(A∩B) = area(A)+area(B)at rtol 1e-12, difference/intersection reconstruction, symdifference identity, and Natural Earth shifted-self conservation on both manifolds._overlay_ng0.19 ms intersection/union vs LibGEOS 0.09/0.08 ms — ~2× GEOS's C for pure Julia with exact predicates; spherical 6–11 ms (exact spherical kernel, as expected).🤖 Generated with Claude Code