Skip to main content

solar-shadows-web-workers

Patrón de cálculo de sombras solares con Web Workers + Comlink para no bloquear la UI

Ir a la instalación

Datos de origen

Repositorio
Ntizar/MasterMind
Última actividad en el origen
16 de septiembre de 2026 a las 14:19
Idioma detectado de SKILL.md
español
Estrellas
2
Forks
0

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
solar-shadows-web-workers
description
Patrón de cálculo de sombras solares con Web Workers + Comlink para no bloquear la UI
version
1.1.0
created
2026-06-01T00:00:00.000Z
updated
2026-09-16T00:00:00.000Z
source
Ntizar/solmad
status
active
tags
["data-science","solar","sombras","web-workers","solmad"]
# Patrón: Cálculo de Sombras Solares con Web Workers **Proyecto origen:** SolMAD (Ntizar/solmad) **Clusters:** web-workers, calculo-solar, rendimiento-ui **Decay:** lento ## Descripción Patrón para realizar cálculos intensivos de sombras solares sin bloquear el hilo principal de la UI, usando Web Workers + Comlink para una API type-safe. ## Cuándo usarlo - Tienes cálculos que duran >50ms y pueden bloquear la UI - Necesitas hacer raycasting contra un grid de edificios - El usuario necesita feedback visual en tiempo real mientras se calcula ## Pasos ### 1. Instalar dependencias ```bash npm install comlink suncalc ``` ### 2. Crear el worker (`src/workers/shadows.worker.ts`) ```typescript import * as Comlink from 'comlink'; import SunCalc from 'suncalc'; class SegIndex { cell = 60; // metros por celda grid = new Map<string, Seg[]>(); build(buildings, originLng, originLat) { // Indexar segmentos de fachada en grid espacial } forEachAlongRay(ox, oy, dx, dy, len, fn) { // Raycasting optimizado con grid spatial // Usa visitToken para evitar Set (más rápido) } } ``` ### 3. Crear el cliente (`src/workers/shadowsClient.ts`) ```typescript import * as Comlink from 'comlink'; const workerUrl = new URL('./shadows.worker.ts', import.meta.url); const worker = new Worker(workerUrl, { type: 'module' }); export const workerApi = Comlink.wrap<ShadowWorker>(worker); Comlink.release(workerApi); ``` ### 4. Usar en el componente ```typescript import { workerApi } from './workers/shadowsClient'; await workerApi.build(buildings, centerLng, centerLat); const result = await workerApi.checkShadow(terraceLng, terraceLat, date); ``` ## Pitfalls - **Comlink serializa funciones** — no puedes pasar callbacks arbitrarios, solo funciones serializables - **No compartas estado mutable** entre llamadas al worker - **Limpia el worker** con `Comlink.release()` cuando el componente se desmonte - **SunCalc azimut según versión (CRÍTICO 2026-09)**: en **v1** (≤1.9, la que usa SolMAD: `"suncalc": "^1.9.0"`) viene desde sur (0=S) → convertir con `(azFromSouth + 180 + 360) % 360`; en **v2** ya viene en grados clockwise desde el NORTE (0=N) → usar directo, NO aplicar la conversión o se gira 180° (sombras calculating en dirección opuesta). Ver `## SunCalc v2` abajo. - **Optimización**: usar `visitToken` en vez de `Set` para marcar segmentos visitados (evita alloc) ## SunCalc v2 (2.0.2, 2026-09-02) — qué cambia al migrar desde v1 Aprendido del repo [mourner/suncalc](https://github.com/mourner/suncalc) (3.471⭐, BSD-2, activo). v2 es una reescritura de precisión: posición solar ~0.43°→~0.08°, salidas/puestas ~75s→~15s, posición lunar ~1.2°→~0.09° (validado contra JPL Horizons y USNO, fórmulas de Jean Meeus). **Breaking changes (migración SolMAD/shademap u otros proyectos con `suncalc@1.x`):** 1. **ESM-first**: `import * as SunCalc from 'suncalc'` (ya no default `import SunCalc`). Sigue hay build UMD/CJS para `<script>` (global `SunCalc`) y `require()` — jsDelivr: `https://cdn.jsdelivr.net/npm/suncalc/+esm` (módulo) o `/npm/suncalc` (bundle global). 2. **Todos los ángulos en GRADOS** (entrada y salida: altitude, azimuth, parallactic…) — v1 usaba radianes. Un upgrade sin tocar el código = azimuts interpretados 57× fuera de rango, silenciosamente. 3. **Azimut desde el NORTE, CW** (0=N, 90=E, 180=S, 270=W) — v1 era desde el SUR. Eliminar toda conversión propia tipo `(az+180)%360` (ver pitfall arriba). 4. **Altitud aparente** (corregida por refracción atmosférica) — cerca del horizonte coincide con lo observado; con v1 el sol "sale" medido ~3-4 min antes/despes de lo visible. 5. **Fechas = instantes UTC absolutos** sin conversión de zona; `getTimes` resuelve el día solar de la fecha pase la hora que pase (en v1 había que pasar el mediodía para evitar off-by-one). Para MOSTRAR en zona: `toLocaleString`/`Intl` con `timeZone` explícito (el DST se aplica solo). 6. **Eventos inexistentes = `null`** (no `Invalid Date`) + flags `alwaysUp`/`alwaysDown` en latitudes polares. En zonas templadas como Madrid no dispara, pero el código que hace `isNaN(date)` debe pasar a `=== null`. 7. `getMoonTimes` escanea el día UTC; eliminado el argumento `inUTC` — para ventana civil local, pasar fecha a medianoche local. `getMoonIllumination` añade flag `waxing`. **Para el raytraceo de sombras (uso en este patrón):** `getPosition(date, lat, lng)` → `{altitude, azimuth}` en grados; el check "hay sol" sigue siendo `altitude > obstrucción`; el vector de dirección del rayo se construye YA desde norte (sin el +180). Precisión de ~15s hace innecesario el truco v1 de muestrear a mediodía. ## Referencias - SunCalc v2: https://github.com/mourner/suncalc (3.471⭐, BSD-2, v2.0.2 — notas de ruptura en la release v2.0.0) - SolMAD: `src/workers/shadows.worker.ts` (~14KB) - SolMAD: `src/lib/sun.ts` — utilidad de conversión de azimut - Comlink: https://github.com/GoogleChromeLabs/comlink
Ver en GitHub