Skip to content

Fix boundary point classification in computeLineEnds optimization (#1175)#1200

Merged
dr-jts merged 1 commit into
locationtech:masterfrom
grootstebozewolf:bugfix/RelateNg-Boundary-Skip-1175
Jun 13, 2026
Merged

Fix boundary point classification in computeLineEnds optimization (#1175)#1200
dr-jts merged 1 commit into
locationtech:masterfrom
grootstebozewolf:bugfix/RelateNg-Boundary-Skip-1175

Conversation

@grootstebozewolf

@grootstebozewolf grootstebozewolf commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

… disjoint line components

The optimization in computeLineEnds() that skips processing of line components whose envelopes are disjoint from the target after finding one exterior intersection was incorrectly skipping boundary point classification.

Track hasInteriorExteriorIntersection and hasBoundaryExteriorIntersection separately so that we only skip when both kinds of exterior line-end intersections have been recorded. This ensures boundary endpoints on later disjoint components (e.g. odd-valence ends in a MultiLineString) are still processed and reported in the DE-9IM matrix (position 7, EB).

  • Refactor computeLineEnds() + computeLineEnd() to use two booleans and return the line-end location (INTERIOR/BOUNDARY/NONE) instead of a simple boolean.
  • Add the exact reproduction case from the issue as testLineDisjointMultiLineWithBoundaryInExterior_JTS1175() exercising relate() + the various predicate helpers.
  • Update history.

Reported by peterstace; reproduction:
g1 = LINESTRING(10 10,20 20) g2 = MULTILINESTRING((0 0,1 0),(1 0,2 0),(-1 0,0 0)) Expected: FF1FF0102 (EB='0'), was FF1FF01F2 (EB='F')

(cherry picked from commit 2991049,
isolated to just the RelateNG boundary skip changes)

Fixes #1175

… disjoint line components (locationtech#1175)

The optimization in computeLineEnds() that skips processing of line components
whose envelopes are disjoint from the target after finding one exterior
intersection was incorrectly skipping boundary point classification.

Track hasInteriorExteriorIntersection and hasBoundaryExteriorIntersection
separately so that we only skip when both kinds of exterior line-end
intersections have been recorded. This ensures boundary endpoints on
later disjoint components (e.g. odd-valence ends in a MultiLineString)
are still processed and reported in the DE-9IM matrix (position 7, EB).

- Refactor computeLineEnds() + computeLineEnd() to use two booleans
  and return the line-end location (INTERIOR/BOUNDARY/NONE) instead of
  a simple boolean.
- Add the exact reproduction case from the issue as
  testLineDisjointMultiLineWithBoundaryInExterior_JTS1175() exercising
  relate() + the various predicate helpers.
- Update history.

Reported by peterstace; reproduction:
  g1 = LINESTRING(10 10,20 20)
  g2 = MULTILINESTRING((0 0,1 0),(1 0,2 0),(-1 0,0 0))
  Expected: FF1FF0102 (EB='0'), was FF1FF01F2 (EB='F')

(cherry picked from commit 2991049,
 isolated to just the RelateNG boundary skip changes)
@dr-jts dr-jts merged commit e8de44d into locationtech:master Jun 13, 2026
2 checks passed
grootstebozewolf added a commit to grootstebozewolf/jts that referenced this pull request Jun 17, 2026
…tiontech#1195)

Records the dependency-ordered queue for opening the per-TAG branches as PRs
against locationtech/jts:master. The queue is held until the foundation PRs
(locationtech#1194, locationtech#1198) merge, so each TAG PR is a clean single-TAG diff rather than one
conflated with the unmerged foundation. Captures the dependency tree, the
tier-by-tier firing plan, and the locationtech#1200-style title/body for each of the twelve
TAG PRs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014UP8vRDiu5WomqAqXf5dsP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RelateNG.computeLineEnds() incorrectly skips boundary points for disjoint line components

2 participants