You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(great-circle): extract bisection constant and add inline comments
- Extract 50-iteration bisection count into ANTIMERIDIAN_BISECTION_ITERATIONS constant
- Add inline comments explaining each phase of the Arc() algorithm
- Clean up comments across src/ for clarity and consistency
- Add Thomas Hervey to contributors in package.json
// but maintained for backward compatibility with original arc.js behavior
42
+
// NOTE: coordinates: null is non-standard GeoJSON (RFC 7946 specifies empty array []) but maintained for backward compatibility with original arc.js behavior.
// NOTE: With npoints ≤ 2, no antimeridian splitting is performed.
94
-
// A 2-point antimeridian route returns a single LineString spanning ±180°.
95
-
// Renderers that support coordinate wrapping (e.g. MapLibre GL JS) handle this
96
-
// correctly, whereas splitting would produce two disconnected straight-line stubs
97
-
// with no great-circle curvature — arguably worse behavior. This is a known
98
-
// limitation; open for maintainer discussion if a MultiLineString split is preferred.
99
+
// A 2-point antimeridian route returns a single LineString spanning ±180°. Renderers that support coordinate wrapping (e.g. MapLibre GL JS) handle this correctly, whereas splitting would produce two disconnected straight-line stubs with no great-circle curvature — arguably worse behavior. This is a known limitation; open for maintainer discussion if a MultiLineString split is preferred.
99
100
if(!npoints||npoints<=2){
100
101
constarc=newArc(this.properties);
101
102
constline=new_LineString();
@@ -105,19 +106,16 @@ export class GreatCircle {
105
106
returnarc;
106
107
}
107
108
108
-
// NOTE: options.offset was previously used as dfDateLineOffset in the GDAL-ported
109
-
// heuristic. It is kept in ArcOptions for backwards compatibility but is a no-op here.
109
+
// 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.
110
110
111
+
// Sample npoints evenly spaced positions along the great circle arc.
111
112
constdelta=1.0/(npoints-1);
112
113
constfirst_pass: [number,number][]=[];
113
114
for(leti=0;i<npoints;++i){
114
115
first_pass.push(this.interpolate(delta*i));
115
116
}
116
117
117
-
// Analytical antimeridian splitting via bisection.
118
-
// For each consecutive pair of points where |Δlon| > 180 (opposite sides of ±180°),
119
-
// binary-search for the exact crossing fraction f* using interpolate(), then insert
120
-
// [±180, lat*] boundary points and start a new segment. 50 iterations → sub-nanodegree precision.
118
+
// Walk the sampled points, splitting into segments wherever the arc crosses the antimeridian.
121
119
constsegments: [number,number][][]=[];
122
120
letcurrent: [number,number][]=[];
123
121
@@ -131,21 +129,25 @@ export class GreatCircle {
131
129
132
130
constprev=first_pass[i-1]!;
133
131
132
+
// A longitude jump > 180° between adjacent samples indicates an antimeridian crossing.
134
133
if(Math.abs(pt[0]-prev[0])>180){
134
+
// Bisect to find the interpolation fraction f* at which the arc crosses ±180°.
0 commit comments