Skip to content

docs: remove deprecated offset option and GDAL attribution#77

Open
thomas-hervey wants to merge 11 commits intospringmeyer:mainfrom
thomas-hervey:docs/arc-options-cleanup
Open

docs: remove deprecated offset option and GDAL attribution#77
thomas-hervey wants to merge 11 commits intospringmeyer:mainfrom
thomas-hervey:docs/arc-options-cleanup

Conversation

@thomas-hervey
Copy link
Copy Markdown
Contributor

@thomas-hervey thomas-hervey commented Apr 9, 2026

Summary

Fast-follow to #76. No implementation changes — docs and test hygiene only.

  • ArcOptions.offset: Mark @deprecated in JSDoc; field is kept for backwards compatibility but is a no-op since the GDAL heuristic was replaced with analytical bisection
  • GDAL attribution: Delete GDAL-LICENSE.md, remove from package.json files list, strip file-level attribution block from great-circle.ts, and remove GDAL references from README.md — no remaining code derives from GDAL
  • DEVELOPING.md: Remove non-existent test:build / test:all scripts and CJS/UMD bundle references (ESM-only since chore: stop tracking files compiled by TS and advertise node@16 as the min supported runtime #73)
  • Tests: Strip { offset } from all Arc() call sites in great-circle.test.ts; update typescript.test.ts to document why the backwards-compat assertion exists
  • README.md: Remove options.offset parameter docs; update Dateline Crossing section to reflect automatic detection
  • index.html: Remove the offset UI control (was wired to a no-op parameter)

Test plan

  • npm test passes (89/89)
  • No references to offset remain in docs or examples outside of the deliberate backwards-compat note in typescript.test.ts

…n splitting

- Remove bHasBigDiff / dfMaxSmallDiffLong / dfDateLineOffset heuristic
- Bisect for exact crossing fraction via interpolate() (50 iterations)
- Insert [±180, lat*] boundary points; npoints ≤ 2 keeps current behavior
- Fixes issue springmeyer#75: low npoints (e.g. 10) no longer skips the split
- Tighten test assertions: SPLIT_NPOINTS constant, directional ±180 checks
Addresses Copilot review comment — adds coords.length === 2 check to
assertSplitAtAntimeridian to guard against false positives from 3+
segment splits.
- Routes 2-5 (antimeridian crossers): replace stale coordinate snapshots
  with semantic assertions (Feature type, properties pass-through, WKT
  contains two LINESTRING parts). Splitting correctness is owned by
  antimeridian.test.ts.
- Southern hemisphere filter: switch to coordinate comparison
  (start.y < 0 || end.y < 0) and flatten MultiLineString coordinates
  before .some() to fix number[][][] vs number[][] traversal bug.
- Add south-to-south antimeridian crossing coverage: Sydney ↔ Buenos
  Aires at npoints=10 and 100 in both directions.
- Reformat antimeridian.test.ts to consistent 2-space indentation.
- Add geographic place names to all routes for maintainer clarity.
The GDAL-ported dateline splitting heuristic was removed when the
analytical bisection approach was introduced. No remaining code
derives from GDAL, so delete GDAL-LICENSE.md, remove it from the
package.json files list, drop the file-level attribution block in
great-circle.ts, and remove the GDAL references from README.md.
Mark ArcOptions.offset as @deprecated no-op. Remove non-existent
test:build / test:all scripts and CJS/UMD bundle references from
DEVELOPING.md.
Strip { offset } from all Arc() call sites — the field is a no-op
since the GDAL heuristic was replaced. Keep the backwards-compat type
assertion in typescript.test.ts with an explanatory comment. Update
README Dateline Crossing section and remove the offset UI control from
index.html.
Copy link
Copy Markdown
Collaborator

@jgravois jgravois left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very cool @thomas-hervey!

i must say, i dig this PR. it not only makes the library more resilient in edge-cases, it makes the public API more approachable and simplifies the licensing story all at the same time. 😇

Comment on lines 99 to -106
if (!npoints || npoints <= 2) {
first_pass.push([this.start.lon, this.start.lat]);
first_pass.push([this.end.lon, this.end.lat]);
Copy link
Copy Markdown
Collaborator

@jgravois jgravois Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personally i'm fine with your rationale when users select an npoints value <= 2, but the fact that you've deprecated offset makes me think that we should take an additional step and default to an npoints value that produces a relatively 'true' arc if none is supplied to tidy up the signature even further.

// defaults to npoints ~ 100?
const line = gc.Arc();

offset was indeed a bit of a 'magic' number. i don't think npoints is quite, but a reasonable default still feels like it would be a usability improvement.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome suggestion.
Right now Arc() with no args hits the <= 2 branch and returns a 2-point LineString (just start/end). A default of 100 makes the zero-arg call actually useful. I pushed 77c9045 to address your comment.

dfMaxSmallDiffLong = dfDiffLong;
}
// NOTE: options.offset was previously used as dfDateLineOffset in the GDAL-ported
// heuristic. It is kept in ArcOptions for backwards compatibility but is a no-op here.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a great breadcrumb. thank you for it.

// Analytical antimeridian splitting via bisection.
// For each consecutive pair of points where |Δlon| > 180 (opposite sides of ±180°),
// binary-search for the exact crossing fraction f* using interpolate(), then insert
// [±180, lat*] boundary points and start a new segment. 50 iterations → sub-nanodegree precision.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

50 iterations → sub-nanodegree precision.

do you have a rough idea of the performance implication of this compared with the prior approach? my instinct is that there are few (if any) running this in a hot codepath that generates many arcs in a batch, but i also must say that i also doubt there are users that trust for survey grade accuracy.

i'm assuming you aimed for a degree :trollface: of accuracy that is roughly equivalent, if so and this heuristic has a performance cost, i'm certainly okay with that. i'd just prefer to know than to guess.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really great question. Yeah, this is why I was hoping to get additional eyes on this PR. I did benchmark it via the new scripts/benchmark.mjs. It's runnable if you want to see exact numbers on your machine.

In short, I pushed the commit b3e8116 to benchmark. Bisection adds ~100 extra interpolate() calls per crossing (50 iterations × 2). At npoints=100, that's ~8µs/arc overhead in absolute terms. I think this is negligible for any realistic use case, but I agree that most user's aren't looking for survey grade accuracy, so let me know if you want me to try simplifying this logic.

Arc() with no argument previously returned a 2-point LineString (the
<= 2 fallback). A default of 100 produces a usable great circle arc
out of the box, consistent with the library's intent.
Consolidates inline coordinate constants, route arrays, and test
property helpers into a single source of truth. All test files now
import from test/fixtures/routes.ts, eliminating duplication and
making fixture coverage reviewable in one place.
Generates a GeoJSON FeatureCollection of all test fixtures using the
library itself (actual great circle arcs, not straight lines).
Documents usage in DEVELOPING.md.
…tion

Quantifies the performance cost of the analytical antimeridian bisection
vs the prior GDAL linear interpolation approach. Runnable via
`node scripts/benchmark.mjs` after `npm run build`.
@thomas-hervey
Copy link
Copy Markdown
Contributor Author

@jgravois thanks again for such a quick and thorough review. I've re-requested your review.

In short, I responded to your comments and I did a bit more cleanup, including extracting shared fixtures (990ee2a), and a script to quickly visually check the geojson output (869b1cd) since the number of test cases and fixtures had increased and visual verification is paramount IMHO.

Copy link
Copy Markdown
Owner

@springmeyer springmeyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, merge when you are ready.

Copy link
Copy Markdown
Collaborator

@jgravois jgravois left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm too! 🎸

non-blocking but personally I think you should add yourself to the list of contributors in the package.json in one of your upcoming PRs too. 💜

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.

3 participants