chore: release v0.27.12
This commit is contained in:
@@ -172,6 +172,50 @@ export function greatCirclePoints(
|
||||
return out;
|
||||
}
|
||||
|
||||
// splitAtAntimeridian cuts a continuous (unwrapped) path into the pieces that
|
||||
// fit on a map showing ONE world, each piece with longitudes back inside ±180.
|
||||
//
|
||||
// greatCirclePoints deliberately lets longitude run past ±180 so the polyline
|
||||
// stays smooth. That is right for a map with repeating world copies, and wrong
|
||||
// for one without: an arc from Australia to South America came out at 190°,
|
||||
// 210°, 250° — drawn into the empty space off the right-hand edge, ending
|
||||
// nowhere, while its own end marker sat correctly on the far left. From VK,
|
||||
// where most paths cross the antimeridian, that was most of the map's arcs.
|
||||
//
|
||||
// Each crossing ends one piece at exactly ±180 and starts the next at the
|
||||
// opposite edge, at the SAME latitude, so the line leaves one side of the map
|
||||
// and re-enters the other at the height it left. Leaflet takes the result as a
|
||||
// multi-polyline, so one path is still one layer.
|
||||
export function splitAtAntimeridian(pts: [number, number][]): [number, number][][] {
|
||||
if (pts.length === 0) return [];
|
||||
// Which copy of the world a longitude belongs to: 0 is the map's own.
|
||||
const world = (lon: number) => Math.floor((lon + 180) / 360);
|
||||
const norm = (lon: number) => lon - 360 * world(lon);
|
||||
const out: [number, number][][] = [];
|
||||
let cur: [number, number][] = [];
|
||||
for (let i = 0; i < pts.length; i++) {
|
||||
const [lat, lon] = pts[i];
|
||||
if (i > 0) {
|
||||
const [pLat, pLon] = pts[i - 1];
|
||||
const wPrev = world(pLon), wCur = world(lon);
|
||||
if (wPrev !== wCur) {
|
||||
const east = wCur > wPrev;
|
||||
// The meridian actually crossed, in unwrapped degrees.
|
||||
const edge = 180 + 360 * Math.min(wPrev, wCur);
|
||||
const f = (edge - pLon) / (lon - pLon);
|
||||
const edgeLat = pLat + f * (lat - pLat);
|
||||
cur.push([edgeLat, east ? 180 : -180]);
|
||||
out.push(cur);
|
||||
cur = [[edgeLat, east ? -180 : 180]];
|
||||
}
|
||||
}
|
||||
cur.push([lat, norm(lon)]);
|
||||
}
|
||||
if (cur.length > 1) out.push(cur);
|
||||
else if (cur.length === 1 && out.length === 0) out.push(cur);
|
||||
return out;
|
||||
}
|
||||
|
||||
function toRad(d: number): number { return (d * Math.PI) / 180; }
|
||||
function toDeg(r: number): number { return (r * 180) / Math.PI; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user