# Generador hiperbólico client-side del MVM UIS

Esta carpeta contiene exactamente el código que ejecuta la ruta
`/generador-hiperbolico/`, con sus tres salidas: disco de Poincaré, stripe
periódico y anillo.

- `geometria.js`: números complejos, transformaciones de Möbius, expansión de
  teselaciones regulares y bi-regulares y refinado por puntos medios. Es el
  núcleo compartido por los dos motores.
- `motor.js`: motor del disco. Validación estricta, capas visuales y escritura
  SVG compuesta con arcos exactos.
- `stripes.js`: motor conforme. Transformación del disco a franja y anillo,
  período, cobertura garantizada y Bézier adaptativas.
- `worker.js`: ejecución fuera del hilo de la interfaz. Carga bajo demanda el
  motor que pide el mensaje, así que abrir la página en modo disco no descarga
  el motor de franjas.
- `ui-comun.js`: piezas de interfaz compartidas por las tres salidas —formato
  de cifras, indicador de estado, límites según memoria, lectura de paletas,
  vista previa y descarga.
- `app.js`: selector de salida, pestañas de parámetros, progreso, vista previa
  y descarga.

No hay llamadas de red, `eval`, código aportado por el visitante ni un servidor
de cálculo. El Worker recibe un objeto de parámetros, genera un `Blob` SVG y lo
devuelve a la página. Cancelar termina el Worker inmediatamente.

## Una sola ruta, tres salidas

El selector de salida decide qué motor se usa. Cada modo conserva sus propios
parámetros validados, porque no significan lo mismo: el disco tiene refinado,
familia bi-regular y coloreo por triángulos; la franja y el anillo tienen
período `Δ`, cobertura y tolerancia de curva. Sólo se comparte lo que de verdad
coincide: decimales, metadatos, agrupación de subtrazados y nombre del archivo.

El motor conforme trabaja únicamente con familias regulares. El refinado, el
modo bi-regular y los coloreos por triángulos pertenecen al disco.

## Límites deliberados

La geometría hiperbólica crece de forma exponencial. El navegador aplica un
límite duro de 250.000 polígonos, 1.500.000 aristas y 512 MiB de texto SVG; la
interfaz usa valores recomendados menores según la memoria aproximada que el
navegador declara. Estos límites protegen la pestaña, pero no cambian ni
simplifican una teselación que sí cabe: si una solicitud supera el límite, se
rechaza completa con un mensaje explícito.

La vista previa se rasteriza únicamente dentro del `canvas`, respetando siempre
la proporción real del archivo. El SVG que se descarga sigue siendo vectorial y
conserva todos sus subtrazados.

Los lados curvos no se convierten en polilíneas. En el disco, cada geodésica y
cada borde de una cinta se escribe como un arco circular nativo `A` de SVG; se
emite una recta `L` solamente cuando la solución en el disco de Poincaré es
realmente recta. Las cintas se construyen con equidistantes hiperbólicas
exactas y fueron contrastadas con `Line.to_drawables` de `hyperbolic` 2.0.0.
Por eso ampliar el SVG no revela facetas ni depende de una resolución de
muestreo.

En la franja y el anillo ocurre una situación distinta: el logaritmo y la
exponencial llevan una geodésica general a una curva trascendente que SVG no
puede expresar como arco circular. `stripes.js` usa Bézier cúbicas adaptativas
con primera y segunda derivada analíticas y una tolerancia editable. Son curvas
vectoriales, no segmentos rectos; la prueba recomendada mide un error menor que
`1e-7`.

La cobertura tampoco se decide por una profundidad aproximada. El motor calcula
el disco inscrito en el parche finito y recorta la altura a la zona que está
cubierta por completo. Las pruebas centinela examinaron 583.260 píxeles
interiores del anillo y 280.308 del stripe sin encontrar huecos. Los dos
límites circulares del anillo se remarcan por defecto con el borde configurado
—y pueden ocultarse— para que una celda del color del fondo no se confunda
visualmente con una discontinuidad.

## Procedencia matemática

La expansión por borde y las fórmulas de polígonos regulares de
`geometria.js` son una adaptación en JavaScript de `hyperbolic` 2.0.0, de Casey
Duckering, publicado con licencia MIT. El refinado regular reproduce la regla
de `hypertiling`: triangulación inicial de polígonos de más de tres lados y
subdivisiones recursivas en cuatro mediante puntos medios hiperbólicos.

Las transformaciones de franja y anillo siguen el
[ejemplo oficial de hypertiling](https://gitpages.physik.uni-wuerzburg.de/hypertiling/hyperweb/doc/examples/conformal-transformation.html):
el anillo usa `k·Δ` en el denominador y repite exactamente `k` bloques.

## Pruebas

```powershell
npm run test:hyperbolic
npm run test:hyperbolic-stripes
npm run render:hyperbolic-stripes
```

La comprobación raster de cobertura se ejecuta, con el Python del proyecto, a
partir de `scripts/validate-stripe-coverage.py`.

El resto de esta implementación forma parte del proyecto del Museo Virtual de
las Matemáticas de la Universidad Industrial de Santander.
