chore: release v0.27.12

This commit is contained in:
2026-09-05 19:07:21 +02:00
parent f93e1c5898
commit be889681a9
40 changed files with 4971 additions and 453 deletions
+44
View File
@@ -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; }