mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-06-08 07:13:53 +02:00
668ce16dc7
Gate messages now propagate via the Infonet hashchain as encrypted blobs — every node syncs them through normal chain sync while only Gate members with MLS keys can decrypt. Added mesh reputation system, peer push workers, voluntary Wormhole opt-in for node participation, fork recovery, killwormhole scripts, obfuscated terminology, and hardened the self-updater to protect encryption keys and chain state during updates. New features: Shodan search, train tracking, Sentinel Hub imagery, 8 new intelligence layers, CCTV expansion to 11,000+ cameras across 6 countries, Mesh Terminal CLI, prediction markets, desktop-shell scaffold, and comprehensive mesh test suite (215 frontend + backend tests passing). Community contributors: @wa1id, @AlborzNazari, @adust09, @Xpirix, @imqdcr, @csysp, @suranyami, @chr0n1x, @johan-martensson, @singularfailure, @smithbh, @OrfeoTerkuci, @deuza, @tm-const, @Elhard1, @ttulttul
137 lines
4.7 KiB
TypeScript
137 lines
4.7 KiB
TypeScript
/**
|
|
* Solar Terminator — computes the day/night boundary polygon for real-time rendering.
|
|
*
|
|
* Uses simplified astronomical formulas to compute the subsolar point,
|
|
* then generates a GeoJSON polygon covering the nighttime hemisphere.
|
|
*
|
|
* Performance: pure math, no API calls, ~0.1ms per computation.
|
|
* The polygon has 360 vertices (one per degree of longitude) — trivial for MapLibre.
|
|
*/
|
|
|
|
const DEG = Math.PI / 180;
|
|
const RAD = 180 / Math.PI;
|
|
|
|
/**
|
|
* Compute the Sun's declination and equation of time for a given JS Date.
|
|
* Returns: { declination (radians), eqTime (minutes) }
|
|
*/
|
|
function solarPosition(date: Date) {
|
|
const start = new Date(date.getFullYear(), 0, 0);
|
|
const diff = date.getTime() - start.getTime();
|
|
const oneDay = 1000 * 60 * 60 * 24;
|
|
const dayOfYear = Math.floor(diff / oneDay);
|
|
const hour = date.getUTCHours() + date.getUTCMinutes() / 60 + date.getUTCSeconds() / 3600;
|
|
|
|
// Fractional year in radians
|
|
const gamma = ((2 * Math.PI) / 365) * (dayOfYear - 1 + (hour - 12) / 24);
|
|
|
|
// Equation of time (minutes)
|
|
const eqTime =
|
|
229.18 *
|
|
(0.000075 +
|
|
0.001868 * Math.cos(gamma) -
|
|
0.032077 * Math.sin(gamma) -
|
|
0.014615 * Math.cos(2 * gamma) -
|
|
0.040849 * Math.sin(2 * gamma));
|
|
|
|
// Solar declination (radians)
|
|
const declination =
|
|
0.006918 -
|
|
0.399912 * Math.cos(gamma) +
|
|
0.070257 * Math.sin(gamma) -
|
|
0.006758 * Math.cos(2 * gamma) +
|
|
0.000907 * Math.sin(2 * gamma) -
|
|
0.002697 * Math.cos(3 * gamma) +
|
|
0.00148 * Math.sin(3 * gamma);
|
|
|
|
return { declination, eqTime };
|
|
}
|
|
|
|
/**
|
|
* For a given longitude, compute the latitude of the terminator line.
|
|
* Returns the latitude (in degrees) where the sun angle = 0.
|
|
*/
|
|
function terminatorLatitude(lng: number, declination: number, subsolarLng: number): number {
|
|
// Hour angle at this longitude
|
|
const ha = (lng - subsolarLng) * DEG;
|
|
// Terminator: cos(zenith) = 0 => sin(lat)*sin(dec) + cos(lat)*cos(dec)*cos(ha) = 0
|
|
// => tan(lat) = -cos(ha) * cos(dec) / sin(dec)
|
|
// => lat = atan(-cos(ha) / tan(dec))
|
|
|
|
const tanDec = Math.tan(declination);
|
|
if (Math.abs(tanDec) < 1e-10) {
|
|
// Near equinox, terminator is roughly at ±90° adjusted
|
|
return -Math.acos(0) * RAD; // fallback
|
|
}
|
|
const lat = Math.atan(-Math.cos(ha) / tanDec) * RAD;
|
|
return lat;
|
|
}
|
|
|
|
/**
|
|
* Generate a GeoJSON FeatureCollection containing the nighttime polygon.
|
|
* Updated every call with the current date.
|
|
*/
|
|
export function computeNightPolygon(date: Date = new Date()): GeoJSON.FeatureCollection {
|
|
const { declination, eqTime } = solarPosition(date);
|
|
|
|
// Subsolar longitude: where the sun is directly overhead
|
|
const hour = date.getUTCHours() + date.getUTCMinutes() / 60 + date.getUTCSeconds() / 3600;
|
|
const subsolarLng = -(hour - 12) * 15 - eqTime / 4; // degrees
|
|
|
|
// Generate terminator line points (one per degree of longitude)
|
|
const terminatorPoints: [number, number][] = [];
|
|
for (let lng = -180; lng <= 180; lng += 1) {
|
|
const lat = terminatorLatitude(lng, declination, subsolarLng);
|
|
// Clamp latitude to valid range
|
|
terminatorPoints.push([lng, Math.max(-85, Math.min(85, lat))]);
|
|
}
|
|
|
|
// Determine which side is night: if declination > 0 (northern summer),
|
|
// the night polygon is on the south side of the terminator, and vice versa.
|
|
// More precisely: at lng=subsolarLng, the sun is overhead, so the opposite side is night.
|
|
// We check: is the subsolar point on the +lat or -lat side of the terminator at that lng?
|
|
|
|
// The subsolar latitude
|
|
const subsolarLat = declination * RAD;
|
|
// The terminator latitude at the subsolar longitude
|
|
const termLatAtSubsolar = terminatorLatitude(subsolarLng, declination, subsolarLng);
|
|
|
|
// If subsolar lat > terminator lat at that point, night is on the south (below terminator)
|
|
const nightIsSouth = subsolarLat > termLatAtSubsolar;
|
|
|
|
// Build the night polygon
|
|
// South side: terminator -> bottom edge (-85) -> close
|
|
// North side: terminator -> top edge (85) -> close
|
|
const nightCoords: [number, number][] = [];
|
|
|
|
if (nightIsSouth) {
|
|
// Night is below the terminator line
|
|
// Go left-to-right along the terminator, then close along the bottom
|
|
for (const pt of terminatorPoints) nightCoords.push(pt);
|
|
nightCoords.push([180, -85]);
|
|
nightCoords.push([-180, -85]);
|
|
} else {
|
|
// Night is above the terminator line
|
|
for (const pt of terminatorPoints) nightCoords.push(pt);
|
|
nightCoords.push([180, 85]);
|
|
nightCoords.push([-180, 85]);
|
|
}
|
|
|
|
// Close the ring
|
|
nightCoords.push(nightCoords[0]);
|
|
|
|
return {
|
|
type: 'FeatureCollection',
|
|
features: [
|
|
{
|
|
type: 'Feature',
|
|
properties: {},
|
|
geometry: {
|
|
type: 'Polygon',
|
|
coordinates: [nightCoords],
|
|
},
|
|
},
|
|
],
|
|
};
|
|
}
|