# Solar Shadows Web Workers

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

- Skill: `ntizar/solar-shadows-web-workers` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ntizar/solar-shadows-web-workers`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ntizar/solar-shadows-web-workers/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: ntizar (https://skillmd.com/u/ntizar)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ntizar/solar-shadows-web-workers

---


# 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** viene desde sur (0=S), convertir a 0=N CW: `(azFromSouth + 180 + 360) % 360`
- **Optimización**: usar `visitToken` en vez de `Set` para marcar segmentos visitados (evita alloc)

## Referencias

- SolMAD: `src/workers/shadows.worker.ts` (~14KB)
- SolMAD: `src/lib/sun.ts` — utilidad de conversión de azimut
- Comlink: https://github.com/GoogleChromeLabs/comlink

