@zendir/ui 0.2.8 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -217,6 +217,11 @@ export interface GroundTrackMapProps {
217
217
  * `enabled` is the new toggle state.
218
218
  */
219
219
  onLayerChange?: (layerId: string, enabled: boolean) => void;
220
+ /**
221
+ * Show sun and moon position markers on the map.
222
+ * Requires `showTerminator`. Default: true when terminator is enabled.
223
+ */
224
+ showCelestialMarkers?: boolean;
220
225
  }
221
- export declare function GroundTrackMap({ groundTrack, satellites, groundStations, accessMask, teamPaths, showTerminator, terminatorTime, showGrid, showLegend, showEquator, showRecenterButton, showMapStyleToggle, isLoading, emptyMessage, width, height, minHeight, defaultCenter, defaultZoom, className, onSatelliteClick, onStationClick, mapProvider, tileUrl, nightTileUrl, lightSources, pins, pinsEditable, onPinAdd, onPinUpdate, onPinRemove, customLayers, onLayerChange, }: GroundTrackMapProps): React.ReactElement;
226
+ export declare function GroundTrackMap({ groundTrack, satellites, groundStations, accessMask, teamPaths, showTerminator, terminatorTime, showGrid, showLegend, showEquator, showRecenterButton, showMapStyleToggle, isLoading, emptyMessage, width, height, minHeight, defaultCenter, defaultZoom, className, onSatelliteClick, onStationClick, mapProvider, tileUrl, nightTileUrl, lightSources, pins, pinsEditable, onPinAdd, onPinUpdate, onPinRemove, customLayers, onLayerChange, showCelestialMarkers, }: GroundTrackMapProps): React.ReactElement;
222
227
  export default GroundTrackMap;
@@ -78,6 +78,38 @@ function hexToRgb(hex) {
78
78
  }
79
79
  return [255, 238, 221];
80
80
  }
81
+ function calculateSubSolarPoint(date) {
82
+ const dayOfYear = Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 864e5);
83
+ const declination = -23.44 * Math.cos(2 * Math.PI / 365 * (dayOfYear + 10));
84
+ const B = 2 * Math.PI / 365 * (dayOfYear - 81);
85
+ const eotMinutes = 9.87 * Math.sin(2 * B) - 7.53 * Math.cos(B) - 1.5 * Math.sin(B);
86
+ const utcHours = date.getUTCHours() + date.getUTCMinutes() / 60 + date.getUTCSeconds() / 3600;
87
+ const solarHours = utcHours + eotMinutes / 60;
88
+ const lon = -(solarHours - 12) * 15;
89
+ return [declination, (lon + 540) % 360 - 180];
90
+ }
91
+ function calculateSubLunarPoint(date) {
92
+ const J2000 = Date.UTC(2e3, 0, 1, 12, 0, 0);
93
+ const d = (date.getTime() - J2000) / 864e5;
94
+ const DEG = Math.PI / 180;
95
+ const L = (218.316 + 13.176396 * d) % 360;
96
+ const M = (134.963 + 13.064993 * d) % 360;
97
+ const F = (93.272 + 13.22935 * d) % 360;
98
+ const lon_ecl = L + 6.289 * Math.sin(M * DEG);
99
+ const lat_ecl = 5.128 * Math.sin(F * DEG);
100
+ const obliquity = 23.439 - 36e-8 * d;
101
+ const sinRA = Math.sin(lon_ecl * DEG) * Math.cos(obliquity * DEG) - Math.tan(lat_ecl * DEG) * Math.sin(obliquity * DEG);
102
+ const cosRA = Math.cos(lon_ecl * DEG);
103
+ let RA = Math.atan2(sinRA, cosRA) / DEG;
104
+ if (RA < 0) RA += 360;
105
+ const dec = Math.asin(
106
+ Math.sin(lat_ecl * DEG) * Math.cos(obliquity * DEG) + Math.cos(lat_ecl * DEG) * Math.sin(obliquity * DEG) * Math.sin(lon_ecl * DEG)
107
+ ) / DEG;
108
+ const GMST = (280.46061837 + 360.98564736629 * d) % 360;
109
+ let geoLon = RA - GMST;
110
+ geoLon = (geoLon + 540) % 360 - 180;
111
+ return [dec, geoLon];
112
+ }
81
113
  function calculateTerminatorContinuous(date, depressionDeg = 0, numPoints = 360) {
82
114
  const dayOfYear = Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 864e5);
83
115
  const declination = -23.44 * Math.cos(2 * Math.PI / 365 * (dayOfYear + 10));
@@ -147,7 +179,8 @@ function GroundTrackMap({
147
179
  onPinUpdate,
148
180
  onPinRemove,
149
181
  customLayers,
150
- onLayerChange
182
+ onLayerChange,
183
+ showCelestialMarkers
151
184
  }) {
152
185
  const { tokens } = useTheme();
153
186
  const canvasRef = useRef(null);
@@ -313,6 +346,54 @@ function GroundTrackMap({
313
346
  }
314
347
  ctx.restore();
315
348
  }
349
+ const celestialEnabled = showCelestialMarkers !== void 0 ? showCelestialMarkers : true;
350
+ if (celestialEnabled) {
351
+ const [sunLat, sunLon] = calculateSubSolarPoint(now);
352
+ const sx = lonToX(sunLon, W), sy = latToY(sunLat, H);
353
+ ctx.save();
354
+ ctx.shadowColor = "rgba(255, 179, 0, 0.5)";
355
+ ctx.shadowBlur = 8;
356
+ ctx.fillStyle = "#FFB300";
357
+ ctx.strokeStyle = "#FF8F00";
358
+ ctx.lineWidth = 1.2;
359
+ ctx.beginPath();
360
+ ctx.arc(sx, sy, 6, 0, Math.PI * 2);
361
+ ctx.fill();
362
+ ctx.stroke();
363
+ ctx.shadowBlur = 0;
364
+ ctx.strokeStyle = "rgba(255, 179, 0, 0.85)";
365
+ ctx.lineWidth = 1.4;
366
+ for (let a = 0; a < 360; a += 45) {
367
+ const rad = a * Math.PI / 180;
368
+ ctx.beginPath();
369
+ ctx.moveTo(sx + 8 * Math.cos(rad), sy + 8 * Math.sin(rad));
370
+ ctx.lineTo(sx + 12 * Math.cos(rad), sy + 12 * Math.sin(rad));
371
+ ctx.stroke();
372
+ }
373
+ ctx.restore();
374
+ const [moonLat, moonLon] = calculateSubLunarPoint(now);
375
+ const mx = lonToX(moonLon, W), my = latToY(moonLat, H);
376
+ ctx.save();
377
+ ctx.shadowColor = "rgba(224, 224, 224, 0.4)";
378
+ ctx.shadowBlur = 6;
379
+ ctx.fillStyle = "#e0e0e0";
380
+ ctx.strokeStyle = "#9e9e9e";
381
+ ctx.lineWidth = 0.8;
382
+ ctx.beginPath();
383
+ ctx.arc(mx, my, 5.5, 0, Math.PI * 2);
384
+ ctx.fill();
385
+ ctx.stroke();
386
+ ctx.shadowBlur = 0;
387
+ ctx.fillStyle = "rgba(189, 189, 189, 0.5)";
388
+ ctx.beginPath();
389
+ ctx.arc(mx - 1.5, my - 1, 1.4, 0, Math.PI * 2);
390
+ ctx.fill();
391
+ ctx.fillStyle = "rgba(189, 189, 189, 0.4)";
392
+ ctx.beginPath();
393
+ ctx.arc(mx + 2, my + 1.5, 0.9, 0, Math.PI * 2);
394
+ ctx.fill();
395
+ ctx.restore();
396
+ }
316
397
  }
317
398
  ctx.fillStyle = COLORS.land;
318
399
  ctx.strokeStyle = "rgba(100, 120, 160, 0.25)";
@@ -1019,7 +1100,8 @@ function GroundTrackMap({
1019
1100
  onPinUpdate,
1020
1101
  onPinRemove,
1021
1102
  customLayers,
1022
- onLayerChange
1103
+ onLayerChange,
1104
+ showCelestialMarkers
1023
1105
  }
1024
1106
  )
1025
1107
  }