Las observaciones
Una observación es lo que un testigo relata de lo que vio: cuándo, dónde, qué aspecto tenía, cómo se movía y cómo estaban el cielo y el tiempo. Es el evento que UFO@home reproduce. Un caso contiene al menos una, y puede contener otras: otros testigos del mismo suceso, cada uno con su propio relato, y explicaciones alternativas, que también son observaciones. Una observación puede ser designada por una entrevista mantenida con el testigo, y remitir a ella a su vez.
Parte técnica: el archivo de observación#
Lo que sigue es para quien escribe estos archivos a mano, los genera o los lee en código. En el editor no hace falta saber nada de ello.
Una grabación es un simple archivo JSON. Nada en ella es un blob binario, un identificador de una base de datos ni una referencia a este sitio — puedes escribir una a mano, generarla desde tu propio archivo, o comparar dos en una revisión de código.
Cada extracto de abajo es de solo lectura, y cada uno conoce el formato: sitúa el cursor dentro de un objeto y pulsa Ctrl+Espacio (⌥+I en un Mac) para listar todas las claves que podrían ir allí, con lo que el modelo dice de cada una.
La observación#
| Campo | Significado |
|---|---|
version | Siempre 1 |
id | Qué relato es este, único entre todas las grabaciones de cualquier parte: el día, y luego quién lo vio ("1964-04-24-ZamoraLonnie"), o dónde para un observador anónimo ("1964-04-24-Socorro"). Aquello por lo que un caso lo nombra no es este id sino el de su evento (véase más abajo). |
time, endTime | { year, month, day, hour, minute, second, raw }, cada parte opcional — así es como el formato expresa “1954” o “hacia las 05:00”. raw es la fecha tal como se escribe en EDTF, y es lo que la fecha significa: "1948-07-24T02:45~" (aproximada), "2025-06?" (incierta), "1965-07-01%" (ambas cosas), "19XX" (un año enmascarado), o "05:00" solo, para una hora del día recordada sin su fecha. Los números se mantienen de acuerdo con ella para lo que se calcula (el cielo, el reloj). Es un subconjunto de EDTF (nivel 0, estos calificadores sobre la fecha entera, años enmascarados); @rr0/time es el modelo EDTF completo de RR0, al que las herramientas propias de UFO@home convierten las fechas de una grabación season (spring, summer, autumn o winter) dice una fecha conocida solo como «en primavera de 2022» (EDTF 2022-21), donde se omiten month y day. |
durationSeconds | Una alternativa a endTime, y prevalece si se dan las dos |
durationText | La duración tal como se enunció cuando no era exacta: una duración ISO 8601 con una duda (PT10M~) o un rango (PT5M/PT10M). durationSeconds es entonces la única duración a la que se reproduce, elegida a partir de ella |
utcOffsetHours | La hora LEGAL que marcaba el reloj del observador (+1 para Francia en 1965). Si falta, se aproxima a partir de la longitud, que no puede conocer la hora legal ni un cambio de horario de verano |
timeZone | La zona IANA de la que se derivó el desfase ("Europe/Paris"): la regla, mientras que utcOffsetHours es el número que daba en esa fecha. Solo se lee el número para situar el cielo; la zona es lo que permite derivar de nuevo el desfase cuando cambia la fecha |
place | [{ lat, lng, name }] — name es el nombre completo del lugar a partir del cual se resolvieron las coordenadas |
observer | { id, title, lastName, firstNames }, todos opcionales; se omite por completo para un observador anónimo. id es una referencia a la persona (en RR0, su directorio: "ZamoraLonnie"); los demás campos la describen cuando nadie le ha dado uno |
description | El relato en prosa — una cadena, o una por idioma (véase más abajo) |
image, summary, summaryTime | Lo que representa la observación donde solo se enlaza y nunca se reproduce: la tarjeta que muestra un enlace compartido (véase Compartir). image es una imagen, una dirección (absoluta, relativa al archivo, o una ruta RR0 desde la raíz del sitio); summary una o dos frases, una cadena o una por idioma. Ausentes, la tarjeta muestra el logotipo y dice quién la vio, en qué caso y cuándo, hasta donde lo diga el archivo. summaryTime es el segundo de la grabación en que se fotografía la imagen de la tarjeta (0 por defecto: la primera imagen), para una grabación cuya primera imagen no muestra el fenómeno; solo la herramienta de captura del proyecto lo lee, nunca el reproductor |
tags | Una lista de cadenas, escritas en inglés: son términos técnicos, y dos grabaciones que comparten uno tienen que coincidir en él. A cada lector se le muestran en su propio idioma cuando se conoce una traducción, que hoy es el caso de landing, trace, aerial observation, project sign, paralysis, contact, occupants, close encounter, photograph, radar, electromagnetic effect. La lista no está cerrada: cualquier otra se muestra tal como está escrita, y los códigos de clasificación ("RR3", "NL") o las referencias de caso ("Blue Book 8729") se escriben tal cual. Una cambia la reproducción: paralysis mantiene inmóvil la vista del observador |
account | Quién lo vio y cómo viajó el relato: observerAgeYears (en aquel momento), observerBirth (fecha de nacimiento, mantenida en fase con él), observerPerception (visión del color, alcohol, fatiga: solo lo que difiere de un observador típico), observerOccupation, source (cómo llegó a quien escribió la grabación: on-site, interview, telephone, questionnaire, letter, social-media, press) y followedUp (si se volvió a contactar al observador después) |
sources | Dónde leer el relato tal como se dio, con la forma de una fuente RR0: [{ type, title, authors, url, publication: { publisher, time }, index }], siendo type book o article, o nada para una página web o una publicación, que entonces es solo su url. Se muestran en el panel ?del reproductor, enlazadas cuando tienen dirección; se copian tal cual en un expediente RR0 |
milestones | Los momentos con nombre del relato, mostrados en la barra de reproducción: [{ t, label, note }], siendo label la letra o el número que usa el propio relato ("A", "B") o un par de palabras, y note lo que ocurrió entonces, con las palabras del relato cuando sea posible (una cadena, o una por idioma) |
roads | Las carreteras o caminos que dibuja el propio plano del relato, cuando el mapa no los tiene: [{ id, title, surface, widthM, path, source }], siendo surface paved, gravel o dirt, path el eje como [{ eastM, northM }] desde el lugar del observador al inicio, y source el plano o levantamiento del que se tomó |
Varios observadores: el caso#
Cada observador tiene su propia grabación, y una grabación no dice a qué caso
pertenece: un relato se sostiene por sí solo. Lo que los muestra juntos es el
caso, que los nombra: el
case.json de un expediente de RR0, que indica el
título, la fecha y la clasificación del caso, y enumera todo lo que ocurrió en él como
events. Sus eventos de tipo sighting son sus relatos, cada uno apuntando
a la grabación de un observador:
{
"id": "ChilesWhitted",
"title": "Chiles et Whitted",
"time": "1948-07-24 02:45",
"events": [
{ "type": "event", "eventType": "sighting", "url": "observer-chiles.json" },
{ "type": "event", "eventType": "sighting", "url": "observer-whitted.json" }
]
}
| Campo | Significado |
|---|---|
id | El identificador propio del caso. En rr0.org es el directorio del expediente y puede omitirse; un archivo de caso independiente lo indica |
title, time | El nombre del caso, y cuándo ocurrió tal como RR0 escribe una hora ("1948-07-24 02:45", "1954"). El reproductor nombra un caso que abre por su título |
events | La cronología del caso. Solo se reproducen los sighting, cada uno por su url, leída respecto a la dirección del propio archivo de caso (de modo que el mismo caso funciona desde la página de su expediente y desde cualquier otro lugar); los marcados con interpretationOf son lecturas de uno de ellos (véase abajo); los demás (un artículo, una película, una confesión) son de RR0 Un evento lleva un id cuando una lectura lo designa, y solo entonces: pertenece al caso, así que debe ser único entre los eventos del caso y en ninguna otra parte, y una referencia se lee en el archivo que la escribe. Un interpretationOf que ningún evento lleva se lee, como antes, como el id que declara una grabación que el caso enumera; el que no corresponde a ninguno de los dos es un fallo del caso, que el reproductor señala en su consola, el editor sobre sus grabaciones, y el validate.py del skill cuando se le da el archivo del caso. |
image, summary | Lo que muestra un enlace compartido al caso, como para una grabación (véase Compartir): una imagen, y una o dos frases, una cadena o una por idioma |
Dáselo a <rr0-sighting src> o al reproductor, y cada observador podrá
elegirse de una lista. Una grabación puede darse directamente, sin caso, pero un caso con un solo
avistamiento funciona igual y nombra lo que muestra. Pruébalo con
case-chiles-whitted.json
(reproducirlo).
Decirlo en más de un idioma#
Una grabación pasa de un lector a otro, así que cada campo que escribe un autor puede contener
una cadena por idioma en lugar de una sola: description, el title de
una forma o de un elemento del decorado, y el label y la note de un hito.
{
"description": {
"fr": "Tout le compte rendu de Lonnie Zamora, d'un seul tenant…",
"en": "Lonnie Zamora's whole account, of a piece…"
}
}
Las claves son etiquetas de idioma tal como las da un navegador (fr, en,
pt-BR), y ninguna es obligatoria. Una cadena simple sigue siendo perfectamente válida y
significa “en el idioma en que se escribiera” — lo que es toda grabación hecha antes de esto.
Un lector cuyos idiomas no son ninguno de los presentes recibe lo que el archivo SÍ tiene en
lugar de un campo vacío: una traducción que falta nunca debe convertir algo que el observador
dijo en algo que no dijo.
El idioma que recibe un lector es el de su navegador, salvo que la página diga otra cosa: un
lang en el propio elemento, o en cualquier cosa a su alrededor, se toma primero — un
artículo que declara su propio idioma ya ha dicho en qué idioma lo está leyendo su lector. La
lista del navegador viene después, así que declarar uno fuerza una elección sin descartar los
demás.
El editor muestra un idioma, el del lector, y al escribir solo toca ese — así que abrir un archivo en el otro idioma y escribir es como se añade una traducción, y un autor no puede borrar la de otro.
Lo que se vio#
timeline.keyframes es una lista de { t, shapes }, con t en
milisegundos desde el inicio. Cada forma lleva un sourceId — varias formas pueden
compartir una línea de tiempo (el fenómeno, una llama que lo sigue, una segunda luz) — y una shape:
{
"kind": "oval",
"bounds": { "x": 0, "y": 0, "width": 0, "height": 0 },
"color": "#39ff14",
"angle": 0,
"transparency": 0,
"haloScale": 1.5,
"brightness": 0,
"blur": 0,
"selected": false,
"title": "el fenómeno",
"angular": { "widthDeg": 1.2, "heightDeg": 0.4 },
"aim": { "azimuthDeg": 353.6, "altitudeDeg": 0.6 }
}
| Campo | Significado |
|---|---|
kind | oval, o polygon, que entonces también toma points: [{ x, y }] en píxeles desde la esquina superior izquierda de bounds, abarcando su anchura y su altura, para que el contorno se estire con ella cuando el ángulo redimensiona la caja. Cuando se omite bounds (el caso habitual: se deriva de aim y angular), escribir points como FRACCIONES de la caja, de 0 a 1, y no en píxeles |
title | Su nombre, mostrado al pasar el puntero por encima; una cadena, o una por idioma |
color | Cualquier color CSS |
angle | Su inclinación, en radianes alrededor de su propio centro, positiva en sentido horario en pantalla |
transparency | De 0 opaco a 1 invisible |
haloScale | El resplandor a su alrededor; 0 es ninguno |
brightness | Cuánto deslumbra: un velo, las puntas del diafragma, un núcleo saturado a blanco |
blur | Lo difusos que el observador dijo que se veían los bordes |
angular | Su tamaño aparente en grados — véase más abajo |
aim | Dónde estaba en el cielo del observador: la dirección de su centro, azimuthDeg en sentido horario desde el norte verdadero y altitudeDeg sobre el horizonte. No hacia dónde miraba el observador, que es el headingDeg y el pitchDeg de la pose — véase más abajo |
aim lo sitúa, angular lo dimensiona. bounds
es la proyección de ambos sobre el lienzo fijo de 640×360 con el rumbo y el campo de visión de
la pose, a través del propio instrumento de la grabación; se vuelve a derivar al cargar, así que
un archivo sobrevive a un cambio de lienzo, de campo de visión, de instrumento, o de hacia dónde
miraba el observador. Si los píxeles y los ángulos llegan a discrepar, ganan los ángulos: mover
bounds en un archivo no hace nada mientras aim esté ahí. Un archivo
escrito a mano puede omitir bounds por completo.
timeline.order es el orden de pintado de atrás hacia delante, timeline.groups los
identificadores de fuente agrupados. Ambos opcionales.
Todo lo que lo rodea#
| Campo | Significado |
|---|---|
observerTrack | { keyframes: [{ t, pose }] } — pose contiene lat, lng, elevationM (sobre el suelo local), headingDeg, pitchDeg, rollDeg, fovDeg, y para una cámara fNumber y focusDistanceM. Se reproduce como se mueve una persona: exactamente la pose indicada en cada fotograma clave, y entre ellos un movimiento que gana velocidad, la mantiene a través de los fotogramas clave que siguen moviéndose, y frena hasta una pausa — dos fotogramas clave con el mismo lugar, o el mismo rumbo. Una mirada empieza y acaba inmóvil; una marcha a pie o en coche ya en curso en el primer fotograma clave continúa. Detenerse y echar a andar añaden su propia sacudida, un cabeceo que se extingue en un segundo y medio, trasladado a la imagen tanto como el instrumento lo permite (apenas un ojo, del todo una cámara sostenida a mano). Y un cuerpo en reposo nunca está del todo quieto: de pie o esperando, la vista oscila unos milímetros y deriva una décima de grado, despacio, del mismo modo en el mismo instante — salvo para un observador que el relato dice que quedó paralizado (etiqueta paralysis). El pitchDeg indicado es cómo miraba el observador en el marco de lo que lo llevaba: mientras se desplaza, el reproductor suma la pendiente de la carretera bajo la traza (leída del relieve, positiva al subir, atenuada cuando la mirada se aparta de su camino), de modo que una cuesta eleva la vista y el chip Inclinaciónindica la suma filter es lo que se sostenía delante del instrumento, un id de FILTERS como solar-visual para un eclipse. Se mantiene entre fotogramas clave, sin mezclarse (nadie lleva media gafa), y se quita declarando "none". |
weatherTrack | { keyframes: [{ t, weather }] } — las condiciones del cielo a lo largo de la grabación: precipitación, viento, tormenta, y las nubes como capas con alturas reales, cada una capaz de contener nubes individuales situadas en metros. Todos los campos de un weather están en la sección siguiente |
weatherSource | { id, name, url } del registro del que se consultó el tiempo. Su presencia significa que la grabación se reproduce exactamente como se compuso y no se vuelve a consultar nunca. Si falta, es el propio relato del observador |
lightPollution | El brillo del cielo nocturno del lugar, ciudades incluidas: el cenit de una noche sin Luna en magnitudes por segundo de arco cuadrado, tal como lo lee un Sky Quality Meter o lo da el atlas mundial del brillo artificial del cielo nocturno (su cifra «SQM», Falchi et al. 2016, que lightpollutionmap.info muestra para cualquier lugar). 22 es un cielo natural, un suburbio ronda 19, el centro de una ciudad 17. Si falta, un cielo natural. La parte de las ciudades, lo que queda al quitar los 22 naturales, se suma al cielo como luz: más intensa hacia el horizonte, donde el aire bajo devuelve más, y dibujada con el blanco cálido de una lámpara de 3000 K. Ahoga la Vía Láctea y la luz zodiacal, y quita estrellas, por la diferencia en la estrella más débil que un ojo distingue (Crumey 2014): unas dos magnitudes a 19. La Luna ahora hace lo mismo. "derived" cuando se consulta en el atlas, "stated" cuando el observador lo midió. El editor lo rellena a partir del atlas para una observación de 2015 en adelante, como "derived" con el atlas nombrado, y nunca reemplaza una cifra escrita a mano; antes de 2015 no consulta nada, porque el cielo era más oscuro que el del atlas |
observerMap | Si el mapa de dónde estaba el observador empieza abierto cuando se reproduce o edita la grabación: true o false. Si falta, decide el reproductor: abierto para un observador que se desplazó, cerrado para uno que se quedó en su sitio. Una página que integra el reproductor tiene la última palabra (su atributo show-observer-map). El editor lo escribe cuando se abre o se cierra el mapa en él, para que un lector vea lo que el autor dejó |
frozen | Dónde se guardan, en archivos junto a la grabación (anexos), los datos que la escena pediría si no a terceros en cada reproducción, para que una grabación terminada se reproduzca igual dentro de diez años sin pedir nada a nadie: relief (la altura del suelo, tal como la fuente de altitud la dio para cada parcela de terreno que construye la escena, un zip), imagery (la foto del suelo, como las teselas que sirvió la fuente de imágenes, un zip), roads, water, railways (carreteras, agua y vías de cada parcela, en JSON), upperAir (el aire a la altura de los aviones, en JSON) y map (la foto bajo el mapa del observador, como las teselas que sirvió la fuente de imágenes para el terreno al que se ajusta el mapa, un zip: un mapa congelado muestra esa foto y no pide ninguna otra, ampliada al acercarse, vacía más allá al alejarse). Cada uno es { src, takenOn, attribution }, con src leído respecto a la dirección de la grabación, o una URL data: para un anexo guardado dentro de la propia grabación. Un grupo leído de su anexo no pide nada a nadie; uno sin anexo se pide en directo, como todo antes. "live": true en un grupo lo pide en directo en cada reproducción y nunca lo congela (lo que dice elegir su fuente en directo en lugar de Archivo), y en el propio frozen todos los grupos; "refresh": true en un grupo lo pide en directo una vez, y el editor lo vuelve a tomar al guardar. El editor toma lo que falta al guardar, y guarda la grabación y sus anexos en un único zip que descomprimir donde se publica. weather, place, lightPollution y decor dicen que el tiempo (weatherTrack, weatherSource), el nombre del lugar, la cifra del cielo nocturno y el decorado se leen del archivo en lugar de volver a pedirse (al registro meteorológico cuando cambian la fecha o el lugar, al geocodificador, al atlas y al levantamiento cuando el observador se mueve): {} si están dentro de la grabación, { src } para un anexo con sus claves, que los reproductores devuelven a la grabación al cargarla. Si faltan, están dentro de la grabación y el editor los vuelve a pedir. El huso horario no está aquí: está congelado en la propia grabación |
soundTrack | { keyframes: [{ t, sound }] } — kind (none/hum/whistle/rumble/crackle), volume, pitchHz, y un src opcional de una grabación real. volume y pitchHz se deslizan entre fotogramas clave, kind y src cambian en el fotograma clave. Un src en otro sitio debe servirse a cualquier origen (CORS) |
references | Imágenes del lugar superpuestas a la escena: src (una dirección, o una URL data: para una imagen añadida desde un disco), kind (photo/panorama), registration (headingDeg, pitchDeg, rollDeg, fovDeg), opacity, credit/creditUrl, t y drawing opcionales, from ({ lat, lng }, desde dónde se tomó: el reproductor la desvanece a medida que el observador se aleja de ese punto; si falta, nunca se desvanece), y los landmarks con los que se alineó (id, label, picture como { u, v } desde la esquina superior izquierda, scene como { azimuthDeg, altitudeDeg }) |
traces | Lo que un investigador dibujó sobre el lugar, importado de su archivo de Google Earth (KML o KMZ) y mostrado sobre la escena como suyo, nunca como parte de la reconstrucción: [{ id, title, kind, points, altitude, color, source }], siendo kind point, line o polygon, points los vértices como [{ lat, lng, altM }] tal como los tenía el archivo, altitude cómo se lee altM (ground, por defecto, relative al suelo bajo cada punto, o absolute sobre el nivel del mar), color un #rrggbb y source de quién es |
instrument, exposureSeconds | A través de qué se observó, y cuánto tiempo estuvo abierto el obturador. Si falta, el ojo desnudo. instrument es uno de eye, rectilinear-lens (una cámara de marca desconocida), roamer-1-120, instamatic-126, slr-35mm-50, slr-35mm-zoom, phone-landscape, phone-portrait, o una réflex digital (eos-5d-iii, nikon-d7000… los sensores del catálogo de Stellarium), unos prismáticos (binoculars-nikon-10x42-edg…) o un telescopio (telescope-celestron-c8…); exposureSeconds es un valor para toda la grabación, limitado al rango propio de ese aparato |
iso | La sensibilidad de la película o del sensor con que se tomó la imagen, cuando se conoce: 400 para una película de 400 ISO. Si falta, la del propio aparato (el negativo en color de una réflex es 100, el de una Instamatic 64). La imagen de una cámara no responde como la de un ojo: una película no se adapta al cielo, recibe una exposición — la luz, por el tiempo de obturación, dividida por el cuadrado del número f — y responde a ella con su propia curva (la suave de un negativo, la más abrupta de una diapositiva, la línea recta de un sensor que se detiene en el blanco). Así, una pose nocturna sale con un cielo negro y lo que brillaba en él destacando |
sway | Cuánto mueve la vista el cuerpo que sostiene el instrumento cuando no camina: 1 para una persona de pie o sentada, 0 para una cámara sobre trípode, cualquier valor intermedio o superior para menos o más. Si falta, 1 — salvo para un observador que el relato dice que quedó paralizado (etiqueta paralysis), para quien es 0, y para una exposición de más de medio segundo, que ninguna mano sostiene inmóvil: eso es un trípode, y también 0 |
vehicle | El vehículo en el que iba el observador, cuando el decorado no lo dibuja: { kind, windowsOpen, noise }, siendo kind car, van, truck, motorcycle o generic. Oído desde dentro: su motor sigue el propio trayecto del observador — la marcha según la velocidad, las revoluciones según la marcha, el esfuerzo según acelere o frene — con la rodadura y el viento, amortiguados por un habitáculo cerrado, dejados entrar por ventanillas abiertas; noise es su sonoridad frente a uno corriente de su tipo (1 por defecto). Es también lo que mantiene activo el botón de sonido del reproductor cuando el archivo no tiene soundTrack: el botón responde de todo lo que reproduce la escena — este motor, un engine del decorado, la lluvia y el viento — y no solo de la pista Sus luces: headlights es un ajuste como para un vehículo del decorado (off, position, dipped, main, fog) o auto, por defecto: las luces de cruce desde el crepúsculo y nada de día, que es lo que hace un conductor. headlightKeyframes es [{ t, mode }] para un cambio durante la grabación. El haz ilumina la carretera delante del observador, en la dirección en que va el vehículo. |
decor | Decorado a unos eastM/northM reales del observador: edificios (con floors, windows), árboles, arbustos, farolas, vehículos, puentes, líneas aéreas, otros observadores, aeronaves — opcionalmente con una track y lights cuyo pattern lleva una cadencia de destellos real. Véase más abajo |
Un elemento del decorado se expresa en metros, como todo lo que no es el fenómeno:
| Campo | Significado |
|---|---|
eastM, northM, headingDeg | Dónde está respecto al observador, y hacia dónde mira su frente, en sentido horario desde el norte verdadero |
sizeM | { widthM, lengthM, heightM } a lo largo de sus propios ejes, siendo la longitud el sentido hacia el que mira. Cada eje es opcional: uno que nadie midió conserva la proporción propia de la forma integrada |
model | Un modelo 3D real en lugar de la forma integrada: una entrada del catálogo por id, o un archivo glTF/GLB en url (que prevalece, debe poder leerse desde cualquier origen, y entonces necesita su credit; una relativa se lee desde el archivo que la indica). Nunca decide el tamaño: se escala, conservando sus proporciones, al primer eje medido entre longitud, altura y anchura, o al tamaño real que le da el catálogo. Visto desde dentro, y siempre que no se pueda obtener el modelo, se dibuja en su lugar la forma integrada headingOffsetDeg gira el modelo cargado sobre su eje vertical para que su morro apunte hacia donde la escena lo espera (0 mira al norte con un rumbo de 0); una entrada del catálogo trae el suyo. credit es { title, author, license, sourceUrl }: license tal como la enuncia su autor ("CC BY 4.0") y sourceUrl de dónde viene, para que la afirmación sea verificable. |
bridge | Para un "bridge": cómo está construido. sizeM.lengthM es toda su longitud a lo largo de la carretera, terraplenes incluidos, widthM la anchura del tablero y heightM la altura de la calzada sobre el tablero por encima del suelo; spanM es la luz libre bajo el tablero, discurriendo la carretera sobre un terraplén de tierra que desciende hasta el suelo a cada lado; deckThicknessM el espesor de la losa (1,2 por defecto); railing { heightM, postSpacingM, rails } la barandilla de ambos bordes, postes y barras cuyas aberturas son rectángulos (1,05 m, 1,5 m y 2 barras por defecto). Dibujado con esas medidas, nunca estirado |
wire | Para un "wire" (una línea eléctrica o telefónica): sizeM.lengthM es el vano entre sus postes, a lo largo de su headingDeg, y heightM la altura del cable más bajo; strands [{ heightM, acrossM }] cuelga varios (los superpuestos comparten un acrossM, los de una cruceta difieren); poles es both (por defecto), start o end (el extremo del que se aleja su rumbo o hacia el que apunta: el otro está anclado a un edificio) o none; diameterM (8 mm por defecto) y poleHeightM (medio metro sobre el cable más alto). Recta, sin flecha, y dibujada a esas medidas, nunca estirada |
track | [{ t, eastM, northM, altitudeM, headingDeg }] cuando se mueve, altitudeM por encima del suelo bajo él (el ojo está a elevationM + 1,6 m: un cuerpo a la altura del ojo tiene ese altitudeM). La posición se interpola entre fotogramas clave; el rumbo se mantiene de uno al siguiente |
lights | Sus luces: id, offsetM { x, y, z } desde su centro (derecha, arriba, delante), color, intensity (1 es una luz de navegación corriente) y un pattern: { "kind": "steady" }, o { "kind": "flash", perMinute, dutyCycle, phase }, la cadencia tal como la establecen los reglamentos, la fracción encendida de cada ciclo (cerca de 0,5 para un intermitente de filamento, 0,01 para un estroboscopio) y un desfase de 0 a 1 entre luces. El editor las rellena a partir de ajustes predefinidos: “Avión de pasajeros”, “Helicóptero”, “Coche, faros encendidos”, “Coche, luces de emergencia”, “Rotativos de vehículo de emergencia”, “Farola” |
engine | Un vehículo que se oye en marcha: { kind, noise }, como vehicle más arriba. Su motor sigue su propia track, oído desde donde está el observador, más débil y apagado con la distancia |
occludesSourceIds | Los fenómenos delante de los cuales el observador dijo que estaba — véanse las reglas más abajo |
facade | Solo el tipo building: { color?, plain? }. color es el muro, "#rrggbb"; salvo que plain sea true, se dibujan ventanas en cada planta y una puerta en la planta baja de la cara frontal. Se dibuja al sizeM enunciado (deben estarlo los tres lados), nunca estirada, y no para un edificio con un observador dentro. El editor toma el color del material que el mapa enuncia para los muros (piedra, ladrillo, hormigón, bloque, madera), o un enlucido donde no enuncia ninguno. Ausente es la caja lisa. |
roof | Solo el tipo building: { shape, riseM, color?, ridge? }. shape es "flat" (la caja), "gable" (dos vertientes hasta una cumbrera a lo largo del lado mayor, o de la profundidad con ridge: "depth") o "hip" (cuatro vertientes); riseM es lo que la cumbrera sube sobre el alero, así que los muros miden sizeM.heightM menos eso; color es el tejado visto desde arriba, "#rrggbb". El editor los lee del láser y de la foto aérea del levantamiento. Ausente es un tejado plano del color de los muros. |
origin | El levantamiento del que se tomó este objeto, por el id de su proveedor ("ign-lidar-topo"), cuando el editor lo tomó del levantamiento del lugar y el autor no lo colocó a mano: un árbol, un edificio, un puente o un vano de línea. Elegir otro levantamiento, o ninguno, u otro lugar, sustituye o quita lo que lleva un origin, y nunca lo que no lo lleva |
surveyedOn | El día (AAAA-MM-DD) del levantamiento más reciente del que se extrajo este objeto, cuando viene de uno (véase origin): el editor advierte cuando es posterior a la observación. |
lit, litKeyframes | Si la lámpara de una farola o los faros de un vehículo están encendidos. litKeyframes es [{ t, lit }], ordenado por t, para una luz que se enciende o se apaga durante la grabación; sin él, lit vale para toda la duración. Se ignora en un edificio, un árbol o un observador |
headlights, headlightKeyframes | Cómo están puestas las luces de un vehículo, pues no todo el mundo las enciende, ni como debe: off, position (las luces de posición, que muestran el vehículo y no iluminan nada), dipped (las luces de cruce), main (las luces de carretera: lejos, estrechas, deslumbrantes) o fog (los faros antiniebla: bajos y anchos). Un haz ilumina la carretera, los arcenes, los árboles y las paredes delante del vehículo, sea cual sea la forma en que se dibuje. headlightKeyframes es [{ t, mode }], ordenado por t, para un ajuste que cambia durante la grabación. Sin ninguno de los dos, lo dice lit: encendido son las luces de cruce. Se ignora para todo lo que no sea un vehículo. Solo cuatro vehículos (el del observador y luego los más cercanos del decorado) tienen un haz real. Los faros del observador proyectan sombras (un talud, un poste o un pilar de puente retiene la luz de lo que hay detrás), y el haz se ve en el aire en proporción a lo que el aire difunde de él: un rastro tenue con el aire limpio, un cono de luz en la niebla |
observerSide, observerFacing, observerKeyframes, occupiedFloor | El observador dentro del objeto, para un building o un vehículo (solo un objeto a la vez lo contiene). observerSide dice dónde está: front, behind, left, right, front-left, front-right, behind-left o behind-right, estando el ocupante de un vehículo en una de sus cuatro puertas. observerFacing es la ventana por la que mira cuando no es la de su asiento: un conductor se sienta en front-left y mira por el parabrisas, front. observerKeyframes, [{ t, side, facing }], dice dónde se sienta a lo largo del tiempo, cada uno mantenido hasta el siguiente, y un fotograma sin side significa fuera a partir de entonces, como un conductor que se baja. occupiedFloor es la planta de un edificio en la que está, de 0 (planta baja) a floors |
modelParameters | Los ajustes del modelo con el que se dibuja el objeto, por la clave con que la entrada del catálogo publica cada uno: { "costumeColor": "#5a6b3a" } para la ropa de una persona, foliageColor para un árbol, hullColor para una nave, gearUp para un avión de línea en vuelo. Un modelo trae los suyos (el editor dibuja un campo para cada uno); un objeto dibujado como forma integrada no tiene ninguno, se pinta con color |
sightingUrl | Para un observer: la dirección de la grabación propia de ese observador, cuando se conoce, para que el menú de la escena pueda ofrecer ver su testimonio |
Lo que era: interpretaciones#
Una grabación expresa ángulos, y un cuerpo en metros nunca forma parte de lo que se vio. Es una
afirmación sobre ello, y se pone a prueba colocándola en la escena y mirándola desde donde
estaba el observador: proyecta su sombra, el suelo puede ocultarla, y su contorno se mide
en cada instante frente a lo que dijo el observador. Una interpretación se muestra sola, como el
mundo que afirma; si se pide comparar (el botón ◌, o compare-account en
<rr0-sighting>), el reproductor dibuja a su lado todo lo que vio el observador como
contornos discontinuos e indica cuánto se desvía la dirección y cuántas veces más ancho y más alto
parece cada cuerpo, en rojo cuando un observador no podría haberse equivocado tanto.
La lectura del propio observador va en la grabación, como interpretation. La de otro no está en el relato: es otra observación, listada en el caso (véase abajo). Un relato cuyo observador dijo lo que
era se dibuja en volumen, como lo dijo; uno que no dice nada en metros se dibuja como los
ángulos que expresa. El reproductor lo ofrece, junto con la interpretación de cada analista, una cada vez.
{
"interpretation": {
"title": "Una nave posada sobre sus patas",
"bodies": [{
"id": "craft",
"explains": ["ufo-1"],
"model": { "id": "ellipsoid" },
"track": [
{ "t": 52000, "eastM": -571.6, "northM": -965.5, "onGround": true,
"sizeM": { "widthM": 3.36, "lengthM": 3.36, "heightM": 1.73 },
"appearance": { "color": "#e8e6df", "albedo": 0.7 } },
{ "t": 83000, "azimuthDeg": 195.9, "altitudeDeg": 4.1, "distanceM": 44 }
]
}]
}
}
| Campo | Significado |
|---|---|
explains | Los sourceId de los fenómenos que este cuerpo afirma ser |
model | Una forma construida aquí (ellipsoid, sphere, disc, cylinder, cone, box, torus, figure), un modelo del catálogo por id, o un archivo glTF en url con su credit; una url relativa se lee desde el archivo que la indica, no desde la página. Estirado a sizeM sea cual sea headingOffsetDeg y credit ({ title, author, license, sourceUrl }) son los del modelo de un objeto del decorado. |
track | Dónde está y qué aspecto tiene en cada t. Una posición se expresa o bien en el mundo (eastM/northM desde donde estaba el observador al inicio, como el decorado, con onGround o altitudeAboveGroundM) o bien desde el observador en ese instante (azimuthDeg, altitudeDeg, distanceM). Un cuerpo onGround se apoya en el relieve; una dirección sin distancia se encuentra entonces con el suelo donde lo hace esa línea. sizeM, attitude (headingDeg, pitchDeg, rollDeg) y appearance (color, albedo, luminanceCdM2, transparency de 0 a 1, haloScale como múltiplo del deslumbramiento de su luz propia) se mantienen hasta que un fotograma clave posterior los vuelve a indicar, y se mezclan entre dos fotogramas clave. present: false saca el cuerpo de la escena a partir de ese fotograma clave, y present: true lo devuelve. Una flame (lengthM, widthM, color en la tobera, tipColor, luminanceCdM2) se enciende en el fotograma clave que la indica, sale del nodo del modelo llamado exhaust (o del que nombre su node), ilumina lo que la rodea, levanta polvo donde toca el suelo cuando raisesDust lo indica, y se apaga con una luminanceCdM2 de 0 |
motions | En un fotograma clave: cuánto ha avanzado cada uno de los movimientos propios de su modelo, por el nombre del movimiento — las animaciones del archivo glTF. 0 es el inicio de un movimiento, 1 su final, y uno que se repite sigue más allá de 1: { "legs-turn": 7 } son siete vueltas. El modelo dice qué se mueve y cómo; la pista dice cuándo. Cada movimiento se interpola entre los fotogramas clave que lo indican, sean cuales sean los demás fotogramas clave que muevan el cuerpo entretanto, se mantiene tras el último y vale 0 antes del primero. La partida de Valensole se escribe así: { "t": 246000, "motions": { "pivot-retract": 0 } }, { "t": 248000, "motions": { "pivot-retract": 1, "legs-turn": 0 } }, … { "t": 262000, "motions": { "legs-turn": 7 } } |
lights | En un fotograma clave: la luminancia, en cd/m², de cada una de las luces propias de su modelo, por el nombre del material de la luz en el archivo glTF — para que un mismo cuerpo lleve luces que hacen cada una lo suyo, una blanca fija en cada extremo y una roja que destella entre ambas. El modelo dice dónde está cada luz, su tamaño y su color; la pista dice cuánto brilla y cuándo. Cada luz se interpola entre los fotogramas clave que la nombran y se mantiene tras el último, así que un encendido o apagado son dos fotogramas clave separados por un milisegundo; una luz que ningún fotograma clave nombra brilla con su parte de appearance.luminanceCdM2. Una luz demasiado pequeña para verse se ve por su deslumbramiento, y lo que se interponga entre ella y el ojo — el propio casco del cuerpo, un puente — la oculta. La luz roja de Silly-le-Long: { "t": 499, "lights": { "front-red": 1500 } }, { "t": 500, "lights": { "front-red": 0 } } |
outlineNode | El nodo del modelo que es lo que dibujó el observador ("hull" para una nave cuyas patas no están en el dibujo): aquello por lo que se mide su contorno |
smoke | En la propia interpretación: lo que hace arder en el suelo, como { eastM, northM, fromT, untilT? }, visto por su humo arrastrado por el viento de la grabación halfLifeS dice a qué velocidad decae, en segundos hasta perder la mitad de su espesor (20 por defecto): un fuego de matorral llamea y luego arde sin llama. Nunca se detiene del todo antes de untilT. |
Eventos del cielo#
Lo que ocurrió en el cielo durante la grabación, como hechos: un disparo láser, un lanzamiento de cohete, una reentrada. Cada uno ocurrió lo viera alguien o no: no es la interpretación, que lee el relato, ni el decorado, que dura más que la observación (una casa, un árbol). Se declaran bajo skyEvents, en el primer nivel de la grabación; una grabación que los ponía en su interpretation, como hacían las versiones anteriores, se sigue leyendo.
{
"skyEvents": {
"beams": [{
"id": "meudon-paris",
"path": [
{ "lat": 48.805055, "lng": 2.231171, "altitudeM": 172.5 },
{ "lat": 48.83632, "lng": 2.33702, "altitudeM": 88 }
],
"wavelengthNm": 532,
"powerW": 10
}]
}
}
| Campo | Significado |
|---|---|
reentries | Las reentradas atmosféricas que ocurrieron, un satélite o una etapa de cohete que se desintegra en pedazos que arden. No son cuerpos: una reentrada arde entre 70 y 100 km de altura y se ve a cientos de kilómetros, así que se sitúa sobre la Tierra y se ve a través de su curvatura desde donde estaba el observador. Su track da el punto de cabeza en instantes de la grabación, { t, lat, lng, altitudeKm }, unidos por círculos máximos; cada uno de sus fragments sigue el mismo camino lagS segundos detrás, se ve desde fromT hasta apagarse en untilT, brilla con su absoluteMagnitude (a 100 km, como un bólido) llevada a su distancia real, en su color, con una estela de los últimos trainS segundos de su camino. Su luz es propia: se ve tanto si el Sol la alcanza como si no. object nombra lo que cayó (name, cosparId, norad). Nada se propaga desde elementos orbitales, errados en minutos en la última órbita: el camino es lo que establecen las fuentes, con su procedencia |
launches | Los lanzamientos de cohete que ocurrieron, iluminado por un Sol que se puso para el suelo pero no para la estela, la «medusa espacial». Situados sobre la Tierra como una reentrada: su track da la etapa en instantes de la grabación, { t, lat, lng, altitudeKm } (puede empezar antes que la grabación), y burnFromT y burnUntilT los segundos en que el motor ardió. La estela es una fila de bocanadas soltadas a lo largo de ese camino, cada una expandiéndose con la edad; lo que se ve de cada una es la luz del Sol que difunde hacia el observador. La sombra de la Tierra (dónde el Sol ilumina o no a la altura de la bocanada, y cuánto aire rozó su luz, lo que la enrojece o azulea), el ángulo de difusión y la expansión se calculan con el Sol real en la fecha real: nada se declara de ellos. Un plume opcional sustituye los valores por defecto: exhaustKgPerS (273, un Merlin Vacuum), condensedShare (0,1, el único número que nadie ha medido), particleRadiusUm, expansionKmPerS, initialRadiusKm, lifetimeS, y para el collar (el escape recién soltado, ancho y pronto desaparecido, junto a la estela estrecha que queda) collarShare (0,85), collarExpansionKmPerS (2,5), collarLifetimeS (20). vehicle nombra lo que voló y, en engine, el motor cuyo escape es: thrustKN y specificImpulseS (de los que se deducen el caudal de escape y su velocidad, y con ellos lo ancho del collar) y propellant (rp1-lox, methane-lox, hydrogen-lox, hypergolic o solid, que dice qué parte se vuelve partículas y de qué tamaño). Lo que dice plume prevalece sobre lo que dice el motor. La estela necesita la fecha de la grabación: sin ella no hay Sol que la ilumine vehicle.mission nombra la misión que cumplía ("Starlink Group 10-49"). |
beams | Los haces de luz enviados por el aire desde el suelo, un disparo láser o un reflector. Cada uno tiene un path de al menos dos puntos { lat, lng, altitudeM } (altitudes sobre el mar): donde sale del emisor, donde un espejo lo desvía si lo hay, y donde termina. Entre dos puntos es una recta a través del espacio, no a lo largo del suelo, que desciende bajo ella. wavelengthNm es su color (532 para un láser verde), powerW su potencia óptica media, divergenceMrad lo rápido que se ensancha (0,1 por defecto) y apertureM su anchura al salir (0,01 m por defecto); fromT y untilT dicen cuándo está encendido. Nada de su brillo se declara: lo que se ve de cada metro es lo que el aire allí (moléculas y bruma, a su longitud de onda) difunde hacia el ojo de la potencia que le queda, según el ángulo que la luz debe girar; por eso es mucho más vivo visto remontándolo que viéndolo alejarse. Lo oculta lo que está delante y se detiene donde encuentra el suelo. |
Otra lectura: una interpretación es otra observación#
La lectura que otro hace de un relato (la de un analista, de un investigador, una comparación hecha para
ponerla a prueba) no forma parte del relato: es otra observación, la que ocurrió tal como la sostiene su autor.
Por eso se lista en el caso como el original, como un evento de tipo sighting, marcado como lectura
con interpretationOf, y tiene una grabación propia en url:
{
"id": "McMinnville1950",
"events": [
{ "type": "event", "eventType": "sighting", "id": "trent", "title": "Paul Trent", "url": "observer-mcminnville.json" },
{ "type": "event", "eventType": "sighting",
"interpretationOf": "trent",
"time": "2013-06",
"by": [{ "people": "CousynAntoine" }, { "people": "LouangeFrancois" }],
"title": "A model on a thread under the line",
"url": "interpretation-mcminnville-2.json" }
]
}
| Campo | Significado |
|---|---|
interpretationOf | El id del evento del caso del que es lectura ("trent"), o una lista de ids cuando una lectura sirve a varios relatos (las fotografías y un primer plano). Lo que la distingue de un relato: los eventos sin este campo son los observadores del caso |
time | Cuándo se elaboró la interpretación, como RR0 escribe un tiempo ("2013-06"): no cuándo ocurrió la observación |
by | Quién la sostiene: { "people": id } o { "org": id }, que nombran una entrada que vive en otro sitio (en RR0, un directorio de personas u organizaciones), o una persona descrita en el valor. Ausente en una comparación que nadie sostiene |
title | Cómo se llama la lectura en el menú del reproductor y el selector del editor: unas palabras, una cadena o una por idioma |
url | Su grabación, leída relativa a la dirección del archivo del caso, como la de un observador |
La grabación en url es una grabación como las demás. Comparte el lugar, la hora y la pose del observador
del relato que lee, de modo que un cuerpo situado desde el observador, o en metros desde donde estaba, significa lo
mismo en ambas; no dibuja ninguna forma (una timeline vacía); y guarda los cuerpos en su propia
interpretation, descrita arriba. El explains de un cuerpo nombra las formas del relato.
{
"version": 1,
"id": "1950-05-11-TrentPaul-interpretation-2",
"time": { "year": 1950, "month": 5, "day": 11, "hour": 19, "minute": 45 },
"utcOffsetHours": -7,
"place": [{ "value": { "lat": 45.104167, "lng": -123.330556 } }],
"observerTrack": { "keyframes": [{ "t": 0, "pose": { "lat": 45.104167, "lng": -123.330556, "headingDeg": 41.3, "pitchDeg": 14.85, "fovDeg": 33.4 } }] },
"tags": ["interpretation"],
"timeline": { "keyframes": [], "order": [], "groups": [] },
"interpretation": {
"title": "A model on a thread under the line",
"bodies": [{
"id": "model",
"explains": ["ufo-1"],
"model": { "id": "disc" },
"track": [
{ "t": 0, "eastM": -52, "northM": 118, "altitudeAboveGroundM": 7.5,
"sizeM": { "widthM": 0.3, "lengthM": 0.3, "heightM": 0.1 } }
]
}]
}
}
El reproductor lista los observadores del caso a partir de los eventos sin interpretationOf y ofrece
cada lectura junto al relato que nombra, una cada vez (el botón ◌ la mide contra el relato). Una grabación sola no
tiene más lectura que su propia interpretation. La forma antigua, un evento de tipo
interpretation que nombra la grabación en sighting con sus cuerpos en línea o en un
archivo en url, se sigue leyendo. El editor abre un caso: su selector sobre el render lista los
relatos y las lecturas, cada uno abriéndose como la grabación que es, con un botón para añadir una lectura (una
grabación nueva que comparte el lugar, la hora y la pose del relato, y un evento para ella), otro para eliminarla,
y otro para exportar el caso y cada grabación añadida o modificada en un zip. Pruébalo con
case-mcminnville.json
(reproducirlo,
editarlo).
El tiempo, y sus nubes#
Un fotograma clave weather expresa las condiciones del cielo en un momento del reloj
de la grabación; entre dos fotogramas clave cada número se interpola, y el tipo de precipitación y la
tormenta se mantienen. Contiene:
| Campo | Significado |
|---|---|
cloudLayers | Las nubes, como una lista de capas — véase más abajo. Si falta, las describen los campos antiguos de las filas vecinas, adaptados a una capa de agua y un velo de cirros; una lista vacía significa un cielo despejado que alguien miró |
cloudCover, lowerCloudCover, highCloudCover | Fracciones de cielo (0–1): el total, solo las capas de agua, y solo el velo helado. Escritas por grabaciones hechas antes de que hubiera capas, y que el editor sigue manteniendo al día como resumen de ellas |
cloudBaseM, cloudDarkness | La base única de esa misma época, en metros sobre el suelo de referencia, y un tono único (0 blanco, 1 muy oscuro) |
iceCrystalAlignment | 0–1, con qué regularidad caían los cristales de hielo — lo que convierte un simple anillo en parhelios, arcos y un pilar. Ningún registro lo mide; una capa de cirros lleva el suyo |
rareIceCrystals | 0–1, la proporción de los cristales de un velo de cirros que son de tipos raros: columnas con extremos piramidales (los halos de radio impar, a 9°, 20° y 35°) y placas libres de girar en torno a un eje horizontal (los arcos de Lowitz). Ausente significa 5%, un velo ordinario. Como la alineación, ningún registro los cuenta: se declara. La simulación que se deriva se ha comprobado coherente con Atmospheric Optics |
relativeHumidity | 0–1, cerca del suelo. Decide lo lechoso que es el cielo despejado: la bruma se hincha de agua a medida que el aire se acerca a la saturación. Un registro consultado la trae (a partir de la temperatura y el punto de rocío de ERA5); si falta, una bruma típica |
precipitationType, precipitationIntensity | none/rain/snow/hail, y 0–1. Indicada en un fotograma clave, reproducida como cae: un chubasco empieza en el fotograma clave que lo inicia con sus primeras gotas, y no alcanza la intensidad indicada más deprisa que una lluvia real (de nada a lo más fuerte en veinte segundos); se detiene del mismo modo. Un cambio que los fotogramas clave reparten en más tiempo se sigue tal cual precipitationAmount (0–1, ausente significa toda) dice qué parte de esa precipitación cae ya. |
windDirectionDeg, windSpeed | El viento general: el rumbo HACIA el que sopla, en sentido horario desde el norte, y metros por segundo. Es lo que arrastra las nubes — desde el instante cero, de modo que buscar y volver a reproducir dan el mismo cielo |
storm | Relámpagos y truenos, con el retraso correcto |
Cada capa de cloudLayers es un manto de nubes a una altura real,
y sigue siendo ella misma de un fotograma clave al siguiente:
| Campo | Significado |
|---|---|
id | Estable entre fotogramas clave — las capas se emparejan por él, nunca por su posición en la lista. Una capa presente en un fotograma clave y ausente del siguiente se desvanece; reordenarlas no cambia nada |
type | cumulus, stratus, stratocumulus, cirrus o unknown. Decide la forma de las cimas y lo fino que es el velo; un cirro es además el que refracta los halos. Cambia en el fotograma clave, no se interpola |
baseM, thicknessM | Metros. La base está sobre el suelo de REFERENCIA de la grabación, no sobre un observador que sube; un observador por encima de la base está dentro del manto o sobre él, y el cielo se dibuja en consecuencia |
coverage | 0–1, y significa lo que dice: la fracción del cielo que cubre esta capa, sea cual sea el tamaño de sus nubes |
sizeM | La anchura característica de una nube, en metros. Independiente de la cobertura: la misma fracción de cielo puede ser muchas nubes pequeñas o unas pocas grandes |
density | 0–2, lo opaca que es la materia de la nube; 0 es transparente. También independiente de la cobertura |
darkness | De 0 blanco a 1 muy oscuro. Si falta, el cloudDarkness del fotograma clave |
seed | Qué patrón, de entre los infinitos que los mismos números pueden dibujar. Si falta, uno derivado del id, y por eso el id no debe cambiar |
windDirectionDeg, windSpeed | El viento propio de esta capa, cuando difiere del general — la capa alta suele hacerlo. Si falta, el viento general |
iceCrystalAlignment | Solo para un cirro |
instances | Nubes individuales dentro de esta capa — véase más abajo |
Una nube individual en instances es una nube de su capa que el
archivo sitúa con exactitud, porque el relato lo hizo: aquella tras la que pasó el fenómeno, la que
estaba allí y en ningún otro sitio. Se dibuja como una más de su capa — la misma textura, el mismo
umbral —, sin distinguirse de sus vecinas más que por dónde está y lo grande que es,
y está ahí incluso cuando la coverage de la capa es nula. Se desplaza con el viento de
la capa como las demás, y oculta un fenómeno ante el que pasa.
| Campo | Significado |
|---|---|
id | Estable entre fotogramas clave, misma regla que para una capa |
eastM, northM | Dónde estaba su centro en el instante cero, en metros desde el punto de partida del observador. El viento la arrastra desde allí |
baseM, thicknessM | Su propia base y su propia altura, en metros — una nube puede estar más baja o alzarse más que su manto |
widthM, depthM, rotationDeg | Su huella, en metros, y el rumbo hacia el que está girada esa huella |
density, darkness | Las suyas propias; si falta la oscuridad, la de la capa |
{
"weather": {
"cloudLayers": [
{
"id": "low", "type": "cumulus",
"baseM": 1500, "thicknessM": 800,
"coverage": 0.55, "sizeM": 1400, "density": 1, "darkness": 0.15,
"instances": [
{ "id": "the-one", "eastM": 0, "northM": 4200,
"baseM": 1500, "thicknessM": 800,
"widthM": 1900, "depthM": 1300, "rotationDeg": 12, "density": 1 }
]
},
{ "id": "high", "type": "cirrus", "baseM": 8000, "thicknessM": 400,
"coverage": 0.2, "sizeM": 2200, "density": 0.35, "iceCrystalAlignment": 0.65 }
],
"precipitationType": "none", "precipitationIntensity": 0,
"windDirectionDeg": 90, "windSpeed": 5, "storm": false
}
}
Una grabación cuyo tiempo fue consultado (tiene un weatherSource)
guarda la respuesta del registro, no un enlace a él: ERA5 da las bandas baja, media y alta como tres
capas llamadas record-low, record-mid y record-high, la
base baja estimada a partir de la diferencia entre temperatura y punto de rocío, las otras dos a 3 500 m
y 8 000 m. Su tipo es unknown (cirro para la alta), su tamaño y su densidad
son supuestos de dibujo: un reanálisis sabe qué parte de cada banda estaba cubierta, no qué aspecto
tenían las nubes. Vuelve a pedir el registro desde el editor y las capas se reescriben; edita
una capa a mano y la grabación pasa a ser del autor, y la fuente se elimina.
De dónde viene cada valor#
Cualquier valor de una grabación puede escribirse tal cual, o envuelto con su procedencia:
{
"durationSeconds": {
"value": 15,
"basis": "derived",
"rationale": "De 13 a 18 s en la síntesis del investigador; se toma el punto medio"
}
}
basis es stated (lo dijo el observador, y es lo que significa un valor
sin envolver), derived (deducido de lo que dijo más algo comprobable: la anchura de una
carretera, un mapa, un dibujo medido; rationale da el razonamiento) o
assumed (elegido para que la reconstrucción tenga un valor, sin base en nada de lo que
dijo el observador). La lista de valores assumed es la lista de lo que hay que volver a
preguntar al observador o buscar en el expediente, y por eso vale la pena escribirla incluso cuando no se escribe nada más.
Comprobar un archivo#
El formato se publica también como JSON Schema, generado a partir de los mismos tipos que el reproductor: todas las claves que conoce, lo que puede contener cada una, y las palabras que acepta una lista cerrada. Una clave mal escrita o un valor desconocido no lo superan. No dice nada de lo que puede omitirse, que es una cuestión de sentido que responde esta página. Para ver el resultado, abre el archivo en el reproductor, desde un enlace, o desde tu disco con las imágenes y los modelos que nombra. El reproductor lo comprueba del mismo modo al cargar, e indica tras un ⚠ sobre la imagen lo que no pudo reproducir tal como está escrito: una clave que nada lee, una palabra fuera de su lista, y lo que tuvo que inventar porque el primer fotograma clave de una forma lo omitía (un campo mantenido desde el fotograma clave anterior es la regla de arriba, no un problema).
Un archivo completo#
La grabación más pequeña que aún expresa algo — un óvalo silencioso que cruza el cielo en doce segundos, en una fecha real y en un lugar real. Todo lo demás del formato es opcional, y todo lo que sigue cumple una función:
{
"version": 1,
"description": "The smallest recording that still states something: one silent orange oval, a degree and a half wide, crossing the south-western sky from left to right over twelve seconds.",
"time": { "year": 2024, "month": 8, "day": 12, "hour": 22, "minute": 30 },
"durationSeconds": 12,
"utcOffsetHours": 2,
"place": [{ "lat": 45.19, "lng": 5.72, "name": "Grenoble, Isère, France" }],
"timeline": {
"keyframes": [
{
"t": 0,
"shapes": [
{
"sourceId": "ufo-1",
"shape": {
"kind": "oval",
"bounds": { "x": 150, "y": 150, "width": 10, "height": 3 },
"angular": { "widthDeg": 1.6, "heightDeg": 0.5 },
"color": "#ff8c1a",
"angle": 0,
"transparency": 0,
"haloScale": 1.2,
"selected": false
}
}
]
},
{
"t": 12000,
"shapes": [
{
"sourceId": "ufo-1",
"shape": {
"kind": "oval",
"bounds": { "x": 480, "y": 130, "width": 10, "height": 3 },
"angular": { "widthDeg": 1.6, "heightDeg": 0.5 },
"color": "#ff8c1a",
"angle": 0,
"transparency": 0,
"haloScale": 1.2,
"selected": false
}
}
]
}
]
},
"observerTrack": {
"keyframes": [
{
"t": 0,
"pose": { "lat": 45.19, "lng": 5.72, "elevationM": 0, "headingDeg": 215, "pitchDeg": 20, "fovDeg": 60 }
}
]
},
"soundTrack": { "keyframes": [{ "t": 0, "sound": { "kind": "none", "volume": 0, "pitchHz": 100 } }] }
}
Para modificarlo y verlo reproducirse, pégalo en el editor, que completa cada clave que tiene el formato, ofrece las palabras que acepta cada una, y dice lo que el modelo dice de ella.
Es /demo-data/example-minimal.json
en este sitio, así que puedes descargarlo, y
reproducirlo antes de cambiar
nada. Observa que aparecen tanto angular como bounds: el ángulo es lo que
el archivo SIGNIFICA, y los píxeles se vuelven a derivar de él al cargar — escribe el ángulo, y deja
que se te corrija una estimación errónea de los píxeles.
Otros más grandes para leer#
Cada demo de este sitio es un simple archivo que puedes abrir. Estos cuatro son los que vale la pena leer para ver cómo se construye una grabación real:
| Archivo | Qué mirar en él |
|---|---|
observer-chiles.json | Un caso real: un observador, un id de caso compartido con una segunda grabación, diez fotogramas clave, un weatherTrack consultado con su weatherSource |
sky-test-halos.json | Ningún fenómeno — un cielo preparado por un weatherTrack cuyos fotogramas clave cambian la alineación de los cristales, la proporción de cristales raros, la cobertura de cirros y un manto de cúmulos, contemplado a través de un observerTrack que recorre el conjunto y luego se detiene |
sky-test-clouds.json | Tres capas de nubes con altitud, espesor, tamaño, densidad y viento en metros, evolucionando en la línea de tiempo meteorológica — y en la primera una entrada instances: una nube del campo, situada y dimensionada en metros, que crece y se oscurece a lo largo de los dos minutos |
sky-test-aircraft.json | Un instrument, un exposureSeconds y un iso, y una aeronave de decor con una track y nueve lights a sus cadencias de destello reales, luces de aterrizaje incluidas |
sky-test-reentry.json | Ningún fenómeno: skyEvents con una reentries, el lanzador de Zond 4 desintegrándose sobre Kentucky en 1968, su camino derivado y su horario, alturas y brillo supuestos, cada valor con su procedencia |
sky-test-launch-plume.json | Ningún fenómeno: skyEvents con una launches, el escape de Starlink Grupo 10-49 (Falcon 9, 25 de agosto de 2026, 05:33 EDT) iluminado en el crepúsculo y visto desde Hoboken (Nueva Jersey), el camino de la etapa supuesto con su procedencia y la sombra, la expansión y la luz calculadas |
sky-test-laser-meudon.json | Ningún fenómeno: skyEvents con un beams, el láser verde de 10 W que el Observatorio de París disparó desde su cúpula de Meudon a su cúpula de París el 9 de octubre de 2026, visto desde el parque de Meudon, la altura del emisor y la apertura supuestas con su procedencia, la luz calculada |
instrument-instamatic.json | El mismo avistamiento que observer-socorro.json, cambiado en un solo campo. Compara los dos |
Cuatro reglas que deciden lo que significa un archivo#
- Los campos discretos se mantienen, los continuos se interpolan. Una forma omitida en
un fotograma clave posterior se queda como estaba, y lo mismo cualquier campo que un fotograma clave omita en una forma
que sí vuelve a indicar: un fotograma clave que solo da un nuevo
aimmueve la forma y conserva todo lo demás (volver a indicarboundssinaimniangularse entiende como moverla por sus píxeles); una cuyo primer fotograma clave está a los cinco segundos ya está pintada, en ese estado, desde cero. Para que algo deje de ser visible, ponle un fotograma clave contransparency: 1. - Solo ángulos. No se guarda en ninguna parte ningún tamaño real ni ninguna distancia real. Los metros
se deducen, como desigualdades, de aquello por detrás o por delante de lo cual se dijo que pasó el fenómeno
(
decor[].occludesSourceIds). - Lo declarado prevalece sobre lo deducido.
occludesSourceIdsregistra afirmaciones del observador. Nada en este formato puede deducirlas: describe una apariencia en un campo de visión, no una posición en el espacio. - Ausente no es cero. Que no haya pista de sonido significa que nadie preguntó;
kind: "none"significa que el observador declaró no haber oído nada. La misma distinción recorre el tiempo y la nube de hielo.
Esta página es la referencia del formato. El razonamiento detrás de cada campo está en los comentarios de documentación de su tipo, con los que completan los extractos de arriba, y en el código fuente.
Los componentes#
Tres de los elementos estándar tratan de una observación: la escena en que se reproduce, el reproductor que la muestra y el editor que la describe. El editor de casos y el editor de entrevistas tienen sus secciones en las páginas que hablan de ellos.
Estándar, y ese es todo el diseño#
Son cinco Web Components — el estándar del propio navegador para un elemento personalizado, no un componente del framework de nadie. Lo que de ello se deriva merece explicarse, porque es lo que permite ponerte la herramienta en las manos:
- Funcionan en cualquier página. Un sitio estático, WordPress, una aplicación
React o Vue, una wiki, un archivo HTML escrito a mano. Son elementos: una página que puede
contener un
<video>puede contener estos. - Nada que compilar. Ni bundler, ni paso de compilación, ni configuración en tu proyecto. El módulo registra su elemento al importarlo y el navegador hace el resto.
- Nada que mantener al día. No hay versión de framework con la que coincidir, así que la nueva versión mayor de otro no puede dejarlos obsoletos.
- Su interior es suyo. Cada uno lleva su marcado y sus estilos en un shadow root, así que el CSS de tu página no puede romperlos y ellos no pueden romper tu página.
Se componen en una línea: tanto <rr0-sighting> como
<rr0-sighting-editor> contienen un <rr0-scene>, y la escena
contiene la capa de reproducción — la línea de tiempo, los controles, el lienzo del puntero. Así
que todo aquello a lo que responde la escena está disponible en los tres — mediante
.scene y .scene.ufoElement desde el más externo, ya que la composición
vive en un shadow root.
Para qué sirve cada uno#
<rr0-scene>— el fenómeno en el mundo que lo rodea. La forma que dibujó un observador, su color, su halo y su movimiento, situada en el cielo, el horizonte, el tiempo y el suelo reales de una fecha, una hora y un lugar declarados — oculta por lo que había delante. Útil también por sí solo, para un cielo en el que no hay nada.<rr0-sighting>— el relato, para verlo. Una escena más quién testifica, los metadatos de la observación, sus créditos y las líneas que permiten a un lector llevarlo a otra parte. Así es como se ve un avistamiento publicado.<rr0-sighting-editor>— el relato, para reconstruirlo. Todo lo anterior más la barra de herramientas de edición: describir una observación, o corregir una.<rr0-case-editor>— un caso, para armar. Contiene un<rr0-sighting-editor>y le presenta una grabación de uncase.jsoncada vez: los relatos de los observadores y las lecturas que se hacen de ellos. Los añade, los selecciona y los elimina, y exporta el caso.<rr0-date-input>— una fecha, con su precisión. Un selector para un instante completo, un texto para menos (EDTF), y el grado de certeza. Los editores lo usan para el inicio y el fin de una observación y para la fecha de un caso; dice lo que contiene con un eventodatechange.
Cómo encajan entre sí#
Nunca escribes el anidamiento. Cada elemento construye el de debajo dentro de su propio shadow root, así que lo que contiene tu página es una sola etiqueta:
<rr0-sighting> quién testifica, el panel de metadatos, las líneas de inserción
└─ <rr0-scene> el cielo, el horizonte, el tiempo y el decorado reales, el fenómeno, la reproducción
<rr0-sighting-editor> los ocho paneles de edición
└─ <rr0-scene> una escena, no un avistamiento: un editor tiene su propia barra de herramientas
Por eso una sola etiqueta de script trae consigo los de debajo:
| Cargar esto | registra |
|---|---|
/lib/rr0-scene.mjs | <rr0-scene> |
/lib/rr0-sighting.mjs | <rr0-sighting>, <rr0-scene> |
/lib/rr0-sighting-editor.mjs | <rr0-sighting-editor>, <rr0-scene> |
Así, una página que muestra un avistamiento y, más abajo, un cielo propio sin nada necesita un solo script y dos etiquetas — el segundo elemento ya está registrado.
Se puede entrar en una composición, una propiedad cada vez:
const sighting = document.querySelector("rr0-sighting")
sighting.scene // el <rr0-scene> que compone
sighting.scene.ufoElement // y la capa de reproducción debajo
sighting.scene.ufoElement.play() // así que la reproducción está a dos propiedades
<rr0-sighting-editor> se guarda su composición para sí: lo que ofrece a una
página es el registro — sightingData — y el evento que avisa de que ha cambiado.
Cuál necesitas#
No son variantes de un mismo bundle: cada uno es autónomo, así que carga solo el que necesites. Los tres incluyen Three.js y un catálogo de estrellas, que es lo que cuesta un cielo real.
| Lo que estás haciendo | Componente | Módulo | gzip |
|---|---|---|---|
| Mostrar un avistamiento ovni — un expediente, un artículo, un informe | <rr0-sighting> | /lib/rr0-sighting.mjs | 249 KB |
| Dejar que alguien describa o corrija uno | <rr0-sighting-editor> | /lib/rr0-sighting-editor.mjs | 293 KB |
| Mostrar un cielo sin nada — cómo se veían esa noche un halo, un cometa o el paso de un satélite | <rr0-scene> | /lib/rr0-scene.mjs | 238 KB |
| Mostrar un avistamiento dentro de una escena propia, sin barra de herramientas encima | <rr0-scene> | /lib/rr0-scene.mjs | 238 KB |
| No estás seguro | <rr0-sighting> | /lib/rr0-sighting.mjs | 249 KB |
Ponerlo en una página son dos líneas.
Integrarlo en tu aplicación#
Tras npm install @rr0/ufoathome:
import "@rr0/ufoathome/scene" // registra <rr0-scene>
import "@rr0/ufoathome/sighting" // registra <rr0-sighting>
import "@rr0/ufoathome/editor" // registra <rr0-sighting-editor>
O copia el contenido de los directorios dist-embed* del paquete en tu propio
servidor y apunta allí el <script src>. Cada módulo referencia sus propios
recursos — el catálogo de estrellas, el audio meteorológico — de forma relativa a sí mismo,
así que sigue funcionando desde cualquier ruta; basta con mantener juntos los archivos de cada
bundle. Nada depende entonces de este sitio.
Idioma#
Cada etiqueta se traduce por detección, sin selector: primero el idioma declarado por la propia
página — el atributo lang más cercano, así que <html lang="fr">
obtiene etiquetas en francés —, luego las preferencias del navegador y, por último, el inglés.
Una página que no declara nada recurre al navegador exactamente como antes.
<rr0-sighting>#
La vista estándar de un avistamiento
La opción por defecto para un avistamiento real, con uno o varios observadores. Compone un
<rr0-scene> y añade la barra de herramientas: quién da su relato, y el panel i
con los metadatos propios de la observación y sus créditos, y un botón de compartir: el enlace que la reproduce, y sus líneas de inserción.
<rr0-sighting src="sighting.json"></rr0-sighting>
<rr0-sighting src="case.json"></rr0-sighting> <!-- un caso, y todos sus observadores -->
| Miembro | Tipo | Qué hace |
|---|---|---|
src | atributo | Una sola grabación, o un caso cuyos eventos sighting enumeran varias — se distinguen por su forma. Un simple array de grabaciones se rechaza: enuméralas como los eventos sighting de un caso |
observerUrls | propiedad | Las grabaciones que mostrar, como simple array de URL, en lugar de src. Volver a asignarla mantiene el observador mostrado si la nueva lista aún lo contiene |
sightingData | propiedad | Una grabación, asignada directamente — para una página que la tiene en memoria en lugar de en una URL |
scene | propiedad (lectura) | El <rr0-scene> compuesto, y a través de scene.ufoElement los miembros de reproducción |
loadFromSrc(url) | método (async) | Lo que el atributo desencadena |
show-labels | atributo | La franja de chips que enuncian la grabación bajo la imagen, agrupados (resumen, observación, posición, momento, tiempo, sonido, observador): la fecha dicha con palabras y su día de la semana, y un chip Descripciónque muestra las primeras palabras del relato y abre el texto entero, con desplazamiento pasada una altura máxima, en lugar de los chips. Desactivada por defecto en el elemento — la página del reproductor la activa — y un lector puede abrirla o cerrarla desde el panel i |
show-observer-map / hide-milestones | atributo | Se transmiten a través del <rr0-scene> compuesto hasta el reproductor que los posee |
start-time | atributo | Dónde se abre la grabación, como una duración desde su inicio: segundos (125), 1:30, 1m30s o una duración ISO 8601 (PT1M30S). Se aplica una vez, a la grabación que el elemento carga a continuación; un valor más allá del final abre al final |
start-clock | atributo | Dónde se abre la grabación, como una hora dicha durante la observación, en su hora local: 02:33:15, o con el día 2026-08-11T02:33:15. El inicio de la grabación la sitúa; prevalece sobre start-time cuando puede, y se ignora en una grabación que no dice su hora |
compare-account | atributo | Empieza con el relato del observador mostrado junto a la interpretación elegida, y medido contra ella |
Una grabación que no nombra a ningún observador no muestra ninguna línea “relato de”, que es lo exacto que cabe decir de un cielo preparado para mostrar un halo.
La grabación de cada observador se carga en cuanto se conoce la lista, así que elegir otra
es inmediato. La lista nombra a cada uno por su title, si no por sus nombres y apellido,
si no por su id; uno que no nombra a nadie se numera según su lugar en la lista.
El panel i
se abre como un popover, que Escape o un clic fuera cierran (solo un clic
fuera, en un navegador sin popover). Indica el caso, la fecha, el lugar, el
relato y las etiquetas; fecha, lugar y etiquetas desaparecen de él mientras la franja show-labels
ya los indica. La fecha está en la hora del propio observador (utcOffsetHours, o
una aproximada a partir de la longitud), no en la del lector. La versión al pie abre esta
observación en el editor. La descripción también lo deja mientras los chips se muestran: está en su caja
Resumen
, que se abre con un clic.
El botón Compartir
, entre los del reproductor, abre una sola ventana que da el enlace o el código para insertar
(el código en un editor que ajusta las líneas y se puede modificar), para el reproductor o para el editor, con
las opciones de la página de compartir, cada una ofrecida tal como está el reproductor. El código carga el elemento desde dondequiera que esta copia
se cargó a su vez, así que un fragmento copiado desde una copia local o de pruebas apunta de vuelta a esa
copia.
Lo que emite
| Evento | Cuándo | Dónde escucharlo |
|---|---|---|
observerchange | Cuando cambia la grabación mostrada: cargada, asignada mediante sightingData, u otro observador elegido en la lista. detail.src es su dirección, vacía para una grabación asignada por script | En este elemento. No hace bubbling: escucha en el propio <rr0-sighting> y luego vuelve a leer su sightingData (su descripción, su id) |
recordingissues | Una vez que una grabación cargada se ha comprobado contra el formato: detail.issues enumera lo que no se reprodujo tal como estaba escrito (una clave que nada lee, un valor de tipo erróneo o fuera de su lista, un valor inventado porque el archivo lo omitía), cada uno con su kind y su path. Vacía cuando no hay nada que decir. La misma lista se muestra sobre la imagen tras un ⚠, y se escribe en la consola | En cualquier parte por encima del elemento: se propaga fuera de todas las raíces shadow |
Ponerlo en tu página
<script type="module" src="https://ufoathome.org/lib/rr0-sighting.mjs"></script>
<rr0-sighting src="sighting.json"></rr0-sighting>
sighting.json es un archivo de avistamiento. O bien, tras npm install @rr0/ufoathome: import "@rr0/ufoathome/sighting".
El bundle pesa 249 KB comprimido con gzip y registra la etiqueta por sí mismo — no hay nada más que llamar.
La presentación de arriba explica qué más supone, y
compartir una observación tiene el ejemplo completo, para probarlo y copiarlo.
<rr0-scene>#
El fenómeno, el cielo y el suelo
La forma que dibujó un observador, situada en el cielo, el horizonte, el tiempo meteorológico y el suelo reales de la fecha, la hora y el lugar de la grabación, y oculta por lo que hubiera delante — con los controles de reproducción debajo. Es el elemento sobre el que se construyen los otros dos.
<rr0-scene src="sighting.json"></rr0-scene>
| Miembro | Tipo | Qué hace |
|---|---|---|
src | atributo | URL de una grabación, cargada al conectarse y cada vez que cambia |
sightingData | propiedad | La grabación como objeto simple (véase el formato) — para leerla de nuevo tras editarla, o para asignarla en lugar de usar src |
loadFromSrc(url) | método (async) | Lo que el atributo desencadena internamente. Espéralo cuando necesites que la grabación esté YA cargada antes de hacer cualquier otra cosa |
ufoElement | propiedad (lectura) | La capa de reproducción que compone — la línea de tiempo, los controles, el lienzo sobre el que actúa el puntero — y, a través de ella, todos los miembros de reproducción de más abajo |
sceneRenderer | propiedad (lectura) | El motor de renderizado 3D, para lo que nada más expone |
show-compass | atributo | Las etiquetas N/NE/E/… alrededor del horizonte. Desactivado por defecto: útil al fijar un rumbo, ruido al mirar |
star-catalog-src / deep-star-catalog-src | atributo | De dónde cargar el catálogo de estrellas, cuando alojas tu propia copia en lugar de la que acompaña al bundle: el nivel básico (hasta la magnitud 7,5, cargado por toda escena) y el nivel profundo (de 7,5 a 9, cargado solo por una grabación cuyo instrumento llega más allá de 7,5) |
max-pixel-ratio | atributo | El máximo de píxeles de la pantalla por píxel CSS con que la escena puede dibujar; el de la propia pantalla, hasta 2, si falta. La escena lo reduce por sí misma mientras las imágenes llegan tarde |
show-observer-map / hide-milestones | atributo | Se transmiten tal cual a la capa de reproducción de debajo — escríbelos en la etiqueta que tu página contenga realmente |
Al pasar el puntero por encima, nombra lo que hay debajo — una estrella con su magnitud y su altura, un planeta, un cometa, un edificio, otro observador — y no dice nada donde el suelo oculta lo que señalas.
El botón ©
de su esquina enumera los créditos de lo que muestra — las imágenes del
suelo y del mapa, los modelos, las fotos del lugar, los sonidos. Dentro de
<rr0-sighting> el botón está oculto: están en su panel i
.
La reproducción, en ufoElement
Todo lo relativo a reproducir la grabación vive una propiedad más abajo, en la capa de reproducción —
scene.ufoElement.play() —, la misma capa a la que los otros dos componentes llegan a través
de su propia scene.
| Miembro | Tipo | Qué hace |
|---|---|---|
src | atributo | URL de una grabación, cargada al conectarse y cada vez que cambia |
sightingData | propiedad | La grabación como objeto simple (véase el formato) — para leerla de nuevo tras editarla, o para asignarla en lugar de usar src |
sighting | propiedad (lectura) | El modelo vivo: la hora y el lugar reales más la línea de tiempo de la grabación |
loadFromSrc(url) | método (async) | Lo que el atributo desencadena internamente. Espéralo cuando necesites que la grabación esté YA cargada antes de hacer cualquier otra cosa — reproducir antes de que se resuelva encuentra una línea de tiempo de longitud cero |
play() / pause() | método | Dicen qué estado se quiere, en lugar de invertir el actual |
togglePlayPause() | método | Lo que hacen el botón, el clic y la barra espaciadora |
playbackState | propiedad (lectura) | "stopped", "playing" o "paused" |
currentTime | propiedad | El cabezal de reproducción, en las unidades propias de la línea de tiempo — no en milisegundos reales, véase positionLabel |
seekableDuration | propiedad (lectura) | El intervalo que puede tomar currentTime |
autoReplayEnabled | propiedad | La repetición en bucle, desactivada por defecto: una reproducción se ejecuta una vez y luego emite ended. Actívala para un bucle |
positionLabel / durationLabel | propiedad (lectura) | La posición y la duración ya formateadas por el elemento: la hora del reloj cuando la observación indica una fecha y se conoce su duración, el tiempo transcurrido en otro caso. Un clic en cualquiera de los dos contadores bajo la barra (o Intro sobre él) cambia de uno a otro, y emite timedisplaychange |
refresh() | método | Vuelve a leer la duración y repinta — llámalo tras modificar sighting.timeline desde fuera |
canvasElement / renderer | propiedad (lectura) | El <canvas>, y el renderizador que pinta en él |
enableClickToPlay | propiedad | Si un clic alterna la reproducción y un doble clic alterna la pantalla completa (ambas cosas, o ninguna). El doble clic también devuelve la reproducción al estado en que estaba antes de su primer clic. Ponlo a false donde el lienzo te sirva para otra cosa |
fullscreenTarget | propiedad | Qué elemento amplía el botón de pantalla completa. <rr0-scene> lo fija en su propio escenario, para que sea el cielo lo que pase a pantalla completa y no solo la capa superpuesta. Donde el navegador no ofrece pantalla completa (un iPhone, un iframe sin allow="fullscreen"), el elemento llena la ventana en su lugar, y Escape sale de ella igualmente |
show-observer-map | atributo | Si el mapa de dónde se encontraba el observador empieza abierto: presente, lo abre; "false" lo mantiene cerrado. Ausente, decide la grabación: su propio observerMap si lo indica, y si no abierto cuando el observador se desplazó (un paseo por un campo, un trayecto en coche, un vuelo), cerrado cuando se quedó donde estaba. Decide el estado inicial del mapa, no si existe: el botón está ahí para toda grabación que indique un lugar |
toggleObserverMap() | método | Lo que hace ese botón. En el propio mapa, la rueda amplía alrededor del puntero, un arrastre desplaza el terreno, y sus propios botones amplían y vuelven al trayecto completo. Ampliado, se recentra en el observador cada vez que este llega a su borde, para que nunca salga de él |
observerPlacing | propiedad | Si un clic en el suelo despejado del mapa emite observerplace con { lat, lng } — desactivado por defecto, ya que decir dónde se encontraba el observador corresponde a la grabación. El editor lo activa y escribe la posición en el cabezal de reproducción |
hide-milestones | atributo | Quita los momentos con nombre del relato — las marcas a lo largo de la barra, el rótulo que nombra el que se está reproduciendo y los puntos con letra del mapa. Aparecen allí donde una grabación nombra alguno, así que esta es la única manera de indicar lo contrario |
toggleMilestones() | método | Lo que hace ese botón |
Esos dos son los únicos valores por defecto positivo y negativo que tiene este elemento, y la diferencia es deliberada. Los momentos con nombre de una grabación son sus propias palabras sobre sí misma, así que se muestran allí donde existen; el mapa cuesta peticiones de teselas a un tercero la primera vez que se abre, y no le corresponde a una página gastarlas en nombre de un lector sin decirlo. En ambos casos el lector conserva los dos botones, junto al de pantalla completa — que una página fije un valor por defecto no significa que prohíba lo contrario.
La barra de herramientas y los botones de la esquina solo se muestran mientras el puntero está sobre la imagen, en reproducción o en pausa, o cuando el teclado lleva el foco hasta ellos. Una pantalla táctil, que no tiene puntero con el que pasar por encima, los mantiene visibles.
Con la barra de tiempo enfocada, las teclas funcionan como en un sitio de vídeos: ← retrocede 5 s, → avanza 5 s y Espacio reproduce o pausa. Reproducir o pausar, con una tecla, con el botón o con un clic en la imagen, muestra su símbolo un instante en el centro de la imagen.
Lo que emite
| Evento | Cuándo | Dónde escucharlo |
|---|---|---|
ended | Una vez, cuando la reproducción llega al final sin repetirse en bucle. No al pausar, ni al arrastrar hasta el final | En cualquier parte: es bubbling y composed, así que sale de <rr0-scene> y de <rr0-sighting> y llega al elemento que pusiste en la página. Así se reproducen varias grabaciones una tras otra |
timedisplaychange | Cuando los contadores cambian entre la hora del reloj y el tiempo transcurrido | En cualquier parte, igual que arriba |
timeupdate | En cada paso de la reproducción y en cada salto, con detail.time | Solo en este elemento. No es bubbling ni composed, así que una página que contiene un <rr0-scene> tiene que llegar a su ufoElement — está pensado para los elementos que componen este |
Ponerlo en tu página
<script type="module" src="https://ufoathome.org/lib/rr0-scene.mjs"></script>
<rr0-scene src="sighting.json"></rr0-scene>
sighting.json es un archivo de avistamiento. O bien, tras npm install @rr0/ufoathome: import "@rr0/ufoathome/scene".
El bundle pesa 238 KB comprimido con gzip y registra la etiqueta por sí mismo — no hay nada más que llamar.
La presentación de arriba explica qué más supone, y
compartir una observación tiene el ejemplo completo, para probarlo y copiarlo.
<rr0-sighting-editor>#
El editor
Todo lo anterior más la barra de herramientas de edición. Ponlo en una página donde la gente deba poder describir o corregir una observación por sí misma.
<rr0-sighting-editor></rr0-sighting-editor>
<rr0-sighting-editor src="sighting.json"></rr0-sighting-editor>
Su lienzo es una superficie de edición, así que enableClickToPlay está desactivado ahí: un clic
selecciona y arrastra una forma en lugar de alternar la reproducción. Lo que hacen los ocho grupos de su barra de herramientas
está en la página del propio editor.
| Miembro | Tipo | Qué hace |
|---|---|---|
ufoElement | propiedad (lectura) | Da acceso al lienzo, a la línea de tiempo y al trabajo de apariencia |
appearance | propiedad | Cómo será la próxima forma dibujada: { presetId, color, transparency, haloScale, blur, brightness }, siendo presetId "oval" o "polygon" y los demás los campos de forma del mismo nombre. Asignarla solo toma los campos que le des |
sightingchange | evento | Se emite tras cada edición — la única señal de que la grabación ha cambiado |
Lo que emite
| Evento | Cuándo | Dónde escucharlo |
|---|---|---|
sightingchange | Tras una edición: un campo escrito, un instrumento elegido, una zona horaria deducida, una forma desplazada a lo largo de la línea de tiempo | En este elemento. No hace bubbling, así que escucha en el propio <rr0-sighting-editor> — y luego vuelve a leer su sightingData |
Ponerlo en tu página
<script type="module" src="https://ufoathome.org/lib/rr0-sighting-editor.mjs"></script>
<rr0-sighting-editor></rr0-sighting-editor>
O bien, tras npm install @rr0/ufoathome: import "@rr0/ufoathome/editor".
El bundle pesa 293 KB comprimido con gzip y registra la etiqueta por sí mismo — no hay nada más que llamar.
La presentación de arriba explica qué más supone, y
compartir una observación tiene el ejemplo completo, para probarlo y copiarlo.
Fuentes y decisiones#
Nada de lo que dibuja la herramienta es inventado. Cada valor procede de una fuente con nombre, leída en un momento declarado, y donde no existe ningún registro la interfaz lo dice en lugar de rellenar el hueco.
Los principios#
- Una fuente solo se lee cuando se necesita. Los catálogos se construyen una vez en el repositorio; los servicios solo se llaman para una grabación que los necesita (un lugar, una fecha dentro de su periodo, un botón pulsado), y nunca para una fecha anterior al inicio de su registro.
- Lo que puede desaparecer se aloja aquí. Los datos que un tercero podría retirar o que no pueden leerse desde un navegador (elementos orbitales, modelos 3D) se copian, se reducen y se sirven desde ufoathome.org con su crédito, para que cualquier página que integre una escena los obtenga.
- Lo medido gana a lo modelado, y lo modelado gana a lo supuesto. Un brillo es una observación publicada cuando existe; una fórmula solo completa lo que nadie midió, y un objeto sin ninguna de las dos se calcula pero no se dibuja.
- Cada servicio es intercambiable. Meteorología, relieve, imágenes, lugar, zona horaria, modelos y redacción pasan por un mismo registro: la fuente es una elección visible, con su crédito al lado, y se puede añadir una segunda sin tocar el resto.
- Los límites se declaran. Cada fuente de abajo dice dónde se detiene: antes de 1940 para la meteorología, antes de 1957 para los satélites, antes de febrero de 2021 para los pasos individuales.
El cielo · El aire · Satélites · Aviones y estelas · Meteorología · El suelo · Lugar y hora · Decorado, fotos y sonido
El cielo
| Fuente | Qué proporciona | Cuándo se lee | Alojamiento y crédito | Decisiones y límites |
|---|---|---|---|---|
| astronomy-engine | Posiciones y magnitudes del Sol, la Luna y los planetas; la fase de la Luna; coordenadas celestes; y, para un eclipse, qué parte del Sol oculta la Luna desde este lugar en este instante. | En la página, para toda grabación con fecha. | Biblioteca incluida, MIT. | Unas efemérides completas en lugar de fórmulas aproximadas: reconstruir un cielo solo tiene sentido si es correcto. Su precesión también lleva los catálogos del año 2000 (estrellas, la Galaxia, radiantes de meteoros, novas) a la fecha observada. |
| HYG Database | Posiciones, magnitudes y colores de las estrellas; nombres de las estrellas hasta la magnitud 3. | Construido una vez (build:stars). La página carga las estrellas hasta la magnitud 7,5, y hasta 9 solo para un instrumento que llega tan lejos. | Servido con el bundle de la escena. CC BY-SA. | Cortado en 9 porque el propio catálogo se vuelve incompleto más allá: los recuentos de estrellas dejan de crecer como deberían. |
| JPL Horizons | La órbita de cada cometa visible a simple vista desde 1910, tal como era en el perihelio de esa aparición. | Construido una vez (build:comets); la página propaga la órbita por sí misma, sin petición. | Generado en el código. NASA/JPL. | El brillo NO se toma de JPL: sus parámetros de magnitud dejan a NEOWISE 4 magnitudes demasiado débil. Las magnitudes máximas observadas en su momento se introducen a mano, con sus fechas. Solo se dibuja una cola cuando se registró su longitud. |
| AAVSO, via Strope, Schaefer & Henden 2010 | La curva de luz medida de cada nova desde 1891 que alcanzó la magnitud 5, agrupada a partir de las observaciones de la AAVSO. | Construido una vez (build:novae) con las supernovas de abajo; la página interpola la curva, sin petición. | Generado en el código. Catálogo VizieR J/AJ/140/34. | Una curva registrada en lugar de una fórmula de declive: las leyes habituales fallan con la mayoría de las novas reales, y dibujarían DQ Herculis brillante durante un año cuando el polvo la había atenuado diez magnitudes en pocas semanas. No se dibuja nada antes de la primera observación ni después de la última. RS Oph 2021 y T CrB 1866 reutilizan la curva de su propia erupción anterior, desplazada sobre su máximo registrado. |
| Historical supernovae | Las supernovas de 1006, 1054, 1181, 1572, 1604 y 1987A: dónde estaban y qué brillo tenían cada noche. | Construido una vez (build:novae). | Generado en el código. Posiciones de SIMBAD; 1572 y 1604 reducidas por Ruiz-Lapuente (2004, 2017) a partir de las estimaciones de Tycho, de Kepler y de los astrónomos coreanos; 1006, 1054 y 1181 según las crónicas (Stephenson & Green); 1987A del Open Supernova Catalog. | Cada curva dice de qué tipo es, porque su calidad difiere en dos órdenes de magnitud: de 1054 y 1181 solo hay un máximo y el día en que se vieron por última vez, y el declive de 1006 se toma prestado de 1572, el mismo tipo de explosión. Las fechas del calendario juliano se leen como tales. V1369 Cen (2013), cuyo registro AAVSO no es accesible para un script y del que no se ha publicado ninguna tabla, se lee en los marcadores vectoriales de una figura publicada (Izzo 2017, arXiv:1704.07214), dentro de la parte que muestra esa figura. |
| IMO meteor shower list | Radiante, periodo de actividad, tasa horaria en el máximo y velocidad de las lluvias anuales; un fondo esporádico. | Tabla en el código, calculada para cualquier fecha. | En el código. International Meteor Organization. | La tasa horaria es una media de varios años, no una previsión para una noche: los estallidos y tormentas no están incluidos. |
| Global Meteor Network, trajectories | Los bólidos que sus cámaras triangularon desde diciembre de 2018: dónde empezó y terminó cada uno, a qué altura, cuánto duró y con qué brillo en su máximo. | Reducido una vez (build:fireballs). Una escena solo descarga el mes de su grabación, y nada para una fecha anterior. | Servido desde ufoathome.org/fireballs/, acreditado en los créditos del reproductor. CC BY 4.0. | De tres millones y medio de meteoros, solo se conservan los de magnitud absoluta -3 o más brillantes: los más débiles son el fondo esporádico que calcula la escena. Más brillantes que -9 se descartan: pasado -8 su número deja de bajar como el de los meteoros y forma una cola hasta -45, la fotometría de una cámara saturada. Un mismo suceso resuelto dos veces se conserva una vez. El brillo dibujado es el del máximo a lo largo de todo el camino, suavizado en los extremos, ya que el registro da el máximo y no la curva de luz. Las detecciones de FRIPON también están archivadas pero no se usan: su sitio pide que se le contacte para cualquier uso. |
| Milky Way, zodiacal light, sky brightness | El resplandor de la Galaxia y del polvo zodiacal, y el brillo del cielo en el crepúsculo y a la luz de la Luna. | Calculado en la página, sin descargar datos. | Modelos de la literatura: Leinert et al. 1998 y Hong 1985 (luz zodiacal), Patat et al. 2006 y Krisciunas & Schaefer 1991 (brillo del cielo con el que se comparan los resplandores; la luz del propio cielo está en el apartado del aire). | Ninguna fotografía de la Vía Láctea: una Galaxia modelo integrada a lo largo de la línea de visión, contrastada con tres mediciones en lugar de ajustada a una sola. |
| World Atlas of the artificial night sky brightness (Falchi et al. 2016) | Cuán brillante es el cielo nocturno de un lugar con sus ciudades, el cenit de una noche sin Luna en magnitudes por segundo de arco cuadrado; lo que convierte un cielo despejado en uno contaminado. | Recortado una vez en teselas pequeñas (build:light-pollution). El editor descarga una tesela, unos kilobytes, cuando un lugar no tiene valor declarado; el reproductor lee el valor que lleva la grabación. | Teselas servidas junto a la página, luego desde ufoathome.org, con el crédito guardado en su índice. El atlas es CC BY-NC 4.0, una licencia no comercial: su uso en un sitio público aún está por decidir. | Una medición de 2015 vale para cualquier fecha: el atlas no puede decir cómo se ha iluminado o apagado una ciudad desde entonces. Es solo lo que propone el editor: un valor declarado por el testigo o el investigador (una lectura de Sky Quality Meter) prevalece, y una grabación sin ninguno se reproduce bajo un cielo natural. |
| NASA LOLA shape map of the Moon (LDEM_16) | El relieve del borde de la Luna, para que el limbo no sea un círculo perfecto: las montañas y los cráteres que dejan pasar la última luz del Sol como perlas de Baily. | Recortado una vez (build:lunar-limb) en un archivo cargado con la escena, la primera vez que un eclipse se acerca a la totalidad. | Servido con el bundle de la escena, unos 2 MB. NASA, Planetary Data System. | 16 muestras por grado, y solo la banda en la que puede caer el limbo (libración y paralaje del observador incluidas), guardada en unidades de 100 m: suficiente para las perlas, una fracción del mapa de 33 MB. Qué eclipse hay, y qué parte del Sol está cubierta, nunca se enumera: se calcula a partir de las posiciones reales de los dos astros. |
El aire
La luz del cielo se calcula, no se dibuja: la luz del Sol y de la Luna se sigue a través de una atmósfera esférica de aire, bruma y ozono en quince longitudes de onda, y luego se muestra como la vería un ojo adaptado o una cámara. Cada dato de entrada de abajo es una medición o un modelo publicado; los dos anclajes de visualización son las únicas decisiones.
| Fuente | Qué proporciona | Cuándo se lee | Alojamiento y crédito | Decisiones y límites |
|---|---|---|---|---|
| Hillaire 2020; Bruneton & Neyret 2008 | El método: dispersión simple a lo largo de cada línea de visión, y todos los órdenes superiores reunidos en una tabla de la luz que llega a cada altura para cada altura del Sol. | Tablas construidas en la tarjeta gráfica una vez por página y por nivel de bruma (alrededor de un segundo de GPU, compartido por todas las escenas de la página); la vista del cielo se redibuja cuando se mueven el Sol, la Luna o el observador. | Implementado en el código, dos veces: una referencia en TypeScript y su gemelo en GPU. | Elegido por ser lo bastante rápido para una página web. Contrastado con un cálculo de Monte Carlo de la misma atmósfera: dentro de 0,25 magnitudes y 0,012 de color desde un mediodía brumoso hasta un Sol a -16°, salvo la sombra de la Tierra en el crepúsculo náutico, 0,7 magnitudes demasiado oscura. La resolución de las tablas se midió, no se eligió: tablas más gruesas desviaban un cenit a -10° en más de media magnitud. |
| Bodhaine et al. 1999 | Con qué intensidad dispersa el aire la luz en cada longitud de onda. | Calculado en la página. | Fórmula del artículo. | Derivado del índice de refracción del aire, medido con muchas cifras: nada que ajustar. |
| Serdyuchenko-Gorshelev ozone cross-sections | La absorción del ozono en el visible (la banda de Chappuis), que hace azul un cenit crepuscular. | Promediadas una vez en el código. | IUP Bremen, Gorshelev et al. 2014 y Serdyuchenko et al. 2014 (Atmos. Meas. Tech. 7). | Tomadas a 223 K, la temperatura de la estratosfera; la banda cambia un 3 % como máximo entre 193 y 293 K. Sin ella, un cenit seis grados después de la puesta del Sol sale casi blanco (Hulburt, 1953), y un test comprueba que así es. |
| ASTM E 490-00a | La luz del Sol por encima de la atmósfera, longitud de onda a longitud de onda. | Promediado una vez en el código. | La tabla 3 de la norma. | Promediado sobre 20 nm, lo que borra las líneas de Fraunhofer: correcto para un cielo, erróneo para un espectrógrafo. Suma la iluminancia medida del Sol, de 128 a 133 mil lux, lo que comprueba un test. El cielo de la Luna usa el mismo espectro, escalado según la magnitud de la Luna. |
| Kasten 1969; Hänel 1976 | Lo lechoso que es el cielo despejado: el espesor óptico de la bruma, a partir de la humedad relativa del registro meteorológico. | Con la meteorología: la humedad sale de la temperatura y el punto de rocío de ERA5 (fórmula de Magnus, Alduchov & Eskridge 1996). | Ley de crecimiento de la literatura. | Las partículas de bruma se hinchan de agua a medida que el aire se acerca a la saturación; una carga continental típica se hincha como (1 - humedad) elevado a -0,3, lo que da el 0,1 habitual al 50 %. Cuántas partículas había (una ciudad, un incendio, la historia del viento) no figura en ningún registro, y no se adivina. Limitada al 95 %: más allá, es neblina. |
| Patat et al. 2006 (Paranal) | El brillo medido del cenit durante el crepúsculo, la comprobación que un cielo real aporta al modelo. | En los tests, y en la página para saber si la Vía Láctea y la luz zodiacal podían verse. | El ajuste en banda V del artículo, tabla 1. | Nunca se ajusta a él: el modelo lo alcanza dentro de media magnitud de -6° a -16°. Leer el ajuste publicado también corrigió una tabla de la herramienta que dejaba el crepúsculo civil diez veces demasiado oscuro. |
| Krawczyk et al. 2005; Thompson et al. 2002 | Cómo muestra ese cielo un ojo adaptado a él: una respuesta compresiva que sigue el propio brillo del cielo, y el paso a un gris azulado tenue cuando los bastones toman el relevo. | En la página, para cada píxel del cielo. | Mezcla de los bastones según Krawczyk, Myszkowski y Seidel; azul nocturno según Thompson, Shirley y Ferwerda, tomado a medio camino hacia el blanco. | Las únicas decisiones de la cadena, declaradas como tales: el cenit de un día despejado y el de una noche sin Luna se fijan donde la herramienta los mostraba antes, y todo lo intermedio sigue. Una cámara (un soporte de grabación) no tiene bastones, y su ganancia sobre el ojo aclara lo que registra. |
Satélites
Dos niveles. Para cualquier fecha desde el Sputnik, lo que permitía la sombra de la Tierra y cuántos objetos había en órbita. Desde febrero de 2021, qué satélites cruzaron realmente el cielo, dónde y con qué brillo.
| Fuente | Qué proporciona | Cuándo se lee | Alojamiento y crédito | Decisiones y límites |
|---|---|---|---|---|
| CelesTrak SATCAT | Fecha de lanzamiento y de reentrada de cada objeto seguido: el número en órbita cada mes, y cuándo existió cada clase (Echo, destellos de Iridium, ISS, Starlink). | Construido una vez (build:satellites); también da las fechas de lanzamiento al archivo de elementos orbitales. | Generado en el código. CC BY 4.0. | Aquí solo se leen las dos columnas de fechas (la lista de reentradas de abajo lee también la inclinación). Sus columnas de órbita describen el ÚLTIMO estado de cada objeto: Echo 1 aparece a 400 km cuando volaba cerca de 1.500. Los desechos no se cuentan. |
| CORDS, The Aerospace Corporation | Cada reentrada que siguió desde 2000: su hora prevista con la incertidumbre declarada, y para un centenar la hora a la que se la vio caer y desde dónde. | Reducido una vez (build:reentries), con los días de reentrada del SATCAT para todos los años desde 1957; el editor solo descarga el año de la grabación. | Servido desde ufoathome.org/reentries/. | Archivado a mano, porque el sitio no puede leerse con un script. Una reentrada se enuncia con su precisión y nada más fino: una observación registrada a menos de una hora y 1.500 km, una predicción cuya ventana alcanza la observación, o un simple día de reentrada. Solo la primera dice que pudo cruzar este cielo. Una órbita cuya inclinación la mantiene fuera de la vista de la latitud del observador nunca se lista: el frenado baja una órbita pero no cambia su plano, por eso se lee esta única columna orbital del SATCAT. |
| Orbital element archive, Laurent Chabin (SCEAU) | Los conjuntos de elementos públicos guardados una o dos veces al día desde el 22 de febrero de 2021: la lista de objetos visibles a simple vista, todos los Starlink y, hasta enero de 2025, el catálogo completo. | Reducido una vez (build:tle). La página solo descarga las dos semanas en torno a la observación, y solo para una fecha que cubre el archivo; el propio propagador solo se carga entonces. | Servido desde ufoathome.org/tle/, acreditado en los créditos del reproductor. | Alojado aquí porque el servidor original no puede leerse desde un navegador. 2,8 GB de instantáneas se conservan en 113 MB: cada día para los objetos visibles a simple vista y para los Starlink en sus primeros 60 días (los trenes), un conjunto por semana en los demás casos. Se descartan los desechos y los objetos que nadie midió. Un conjunto nunca se usa a más de 7 días de su época, así que un hueco en el archivo (tres meses a finales de 2025) se señala como hueco en lugar de rellenarse con una órbita caducada. |
| satellite.js (SGP4) | El propagador estándar para estos conjuntos de elementos, y la posición del Sol; la umbra y la penumbra de la Tierra se calculan encima. | Cargado bajo demanda, solo para las fechas cubiertas. | Biblioteca incluida, MIT. | Mantenido en la versión anterior a la que incluye una compilación WebAssembly que rompe el bundle, sin ninguna ganancia aquí. |
| Satellite brightness: McCants, Stellarium, Mallama et al. | Lo brillante que se ve cada objeto: magnitudes estándar (McCants, completadas con la lista de Stellarium para los objetos recientes), y medias publicadas para las constelaciones que nadie catalogó (Starlink, OneWeb, BlueBird). | Fusionadas en el archivo al construirlo; aplicadas en la página. | Starlink 5,93 y luego 7,21 (arXiv:2006.08422, 2101.00374), 4,58 por debajo de 357 km mientras eleva su órbita (2405.12007); OneWeb 7,18 (2012.05100); BlueBird 3,77 y luego 4,32 (2608.23668). | Sin el valor de elevación de órbita nunca se dibujaría ningún tren de Starlink. Una etapa de cohete no medida toma la mediana de al menos tres etapas idénticas medidas; cualquier otro objeto no medido se calcula pero no se dibuja. Los reflejos y destellos no se modelan: solo pueden hacer un satélite más brillante. |
Aviones y estelas
Desde 2022, los aviones que estaban en el cielo del observador a la hora de una grabación, el aire en el que volaban y la estela que sus motores dejaban en él. Lo que se dibuja es un candidato compatible, nunca una identificación, y un cielo vacío en el registro no excluye nada.
| Fuente | Qué proporciona | Cuándo se lee | Alojamiento y crédito | Decisiones y límites |
|---|---|---|---|---|
| adsb.lol open history | Dónde estaba cada avión que emitió su posición, desde 2022: su trayectoria, su tipo, su matrícula y su categoría. Cada uno se dibuja con su tamaño real, sus luces (desde el anochecer, según el tipo de aeronave), el Sol que aún lo ilumina cuando el suelo ya lo ha perdido, la bruma intermedia y el sonido que hace si puede oírse. | Reducido una vez al día (build:aircraft) a un archivo empaquetado por hora y por casilla de un grado. La página solo lee las casillas a menos de 150 km del observador, para la hora de la grabación y los cinco minutos anteriores, y nunca para una fecha anterior a 2022. El código que dibuja, etiqueta y reproduce los aviones solo se carga si una escena los tiene. | Construido a partir de las publicaciones diarias del historial de adsb.lol (ODbL 1.0), acreditado en los créditos del reproductor. Aún no alojado: hasta que el archivo se sirva desde ufoathome.org/aircraft/, los aviones solo se muestran desde una copia local. | Una sola instancia basta: prod-0, con staging-0 de respaldo, contienen los mismos vuelos con una diferencia del 0,02 %. Solo se conservan las posiciones del día UTC propio de cada publicación, para que el resultado no dependa del orden en que se leyeron los días; se descartan los vehículos de aeropuerto. Lo que ningún receptor oyó está ausente: aviones ligeros, planeadores, globos y militares que apagan su transpondedor están infrarrepresentados, y uno de cada siete aviones no indica tipo, así que se dibuja como un avión de línea genérico. |
| amvlab aircraft models (A320, 737, A350, A380, 787) | La célula de un Airbus A320, A350 o A380, o de un Boeing 737 o 787, para un avión de esos tipos lo bastante cerca como para que se vea su forma: motores, puntas de ala, cola. | Cargado por la página solo para un avión de esos tipos a menos de unas 130 veces su propia longitud del observador (5 km para un A320, 10 km para un A380), una vez para la escena (170 a 250 KB cada uno). Más lejos un avión son unos píxeles, y se dibuja la forma integrada con sus luces. | Reubicados en ufoathome.org/models/ con su licencia, CC BY 4.0, © 2026 amvlab, y acreditados en los créditos del reproductor. | Las variantes sin librea, ya que no se conoce la aerolínea. Un modelo para toda la familia A320, uno para todos los 737, uno para el A350 (-900 y -1000), uno para el A380 y uno para el 787 (-8, -9 y -10), cada uno escalado a la longitud real del tipo (un A321 es el modelo A320 dibujado más largo). Qué variante representa cada uno, y con qué fidelidad, su autor no lo documenta. Todos los demás tipos conservan la forma integrada: un modelo es una entrada de catálogo y una fila de una tabla, no código. |
| Open-Meteo, historical forecast API | Temperatura, humedad y viento a 500, 400, 300, 250, 200 y 150 hPa, hora a hora, desde 2022: el aire en el que vuelan los aviones. | Cargado por la página, una vez por grabación que tiene aviones, para el lugar del observador y las horas de la ventana: nunca para una fecha anterior a 2022, ni para una escena sin aviones. | Open-Meteo.com, CC BY 4.0, sin clave, acreditado en los créditos del reproductor. | No es la reanálisis que usa la meteorología: su archivo no sirve niveles de presión. Son los análisis propios de los modelos de predicción, que se sabe que subestiman la frecuencia con que el aire a altitud de crucero está sobresaturado respecto al hielo, de modo que una estela que dura en el cielo puede ser una que el registro dice que no debería. Se lee solo en el lugar del observador: un avión a cien kilómetros vuela en un aire que el modelo puede describir de otro modo. La humedad es relativa al agua (comprobado con el techo que dan los datos en la saturación respecto al hielo, cerca del 60 % a -47 C). |
| Schmidt-Appleman criterion (Schumann 1996) | Si el escape de un motor deja una estela en ese aire, y si dura. El escape se enfría a lo largo de una recta fijada por el rendimiento del motor y la presión; se forma una estela si esa recta cruza la saturación respecto al agua, y solo dura donde el aire está saturado respecto al hielo. | Calculado en la página para cada posición de cada avión, a la presión que da su altitud barométrica (una altitud barométrica es una presión), y arrastrado por el viento de ese nivel. | Fórmula y constantes en el código, con las presiones de saturación de Murphy y Koop (2005). | El motor es uno típico del tipo de aeronave, no el de esa célula: rendimiento global 0,38 para un fuselaje ancho, 0,34 para un pasillo único, 0,30 para un jet ejecutivo, 0,22 para un caza. Hélices, rotores, planeadores y globos no tienen estela. Cómo envejece una estela es una parametrización de órdenes de magnitud observados, no una simulación: su anchura crece con la cizalladura del viento entre los dos niveles a cada lado del avión (cuánto cambia el viento con la altura) y una difusión turbulenta fija, su profundidad se supone, y se dibuja igual de ancha a través de la línea de visión sea cual sea el sentido de la cizalladura; cómo se desvanece y cuánto dura una corta también se suponen. Una estela dibujada es estimada, nunca un hecho; y falta la de un avión que ya se había ido antes de los cinco minutos que se piden al registro. |
Meteorología
| Fuente | Qué proporciona | Cuándo se lee | Alojamiento y crédito | Decisiones y límites |
|---|---|---|---|---|
| Open-Meteo: ERA5 (Copernicus/ECMWF), then its forecast model for the last days | Nubosidad horaria por nivel, precipitación, nieve, código meteorológico, viento, temperatura y punto de rocío, en el lugar y la hora de la observación. | Descargado por el editor en cuanto se conocen una fecha y un lugar, solo desde 1940. Para los últimos cinco días, que ERA5 aún no ha alcanzado, se lee el análisis del modelo de previsión (el archivo dice cuál respondió). | API de archivo y de previsión de Open-Meteo, sin clave. © Copernicus/ECMWF. | Un reanálisis en una malla de ~28 km, no una estación: puede faltar un chubasco local. Las bases de las nubes se deducen (temperatura y punto de rocío para el nivel bajo), no se miden. Cada campo puede desbloquearse y sustituirse por el relato. No hay perfil vertical disponible en modo archivo, que es lo que necesitarían las anomalías de propagación de radar. |
El suelo
| Fuente | Qué proporciona | Cuándo se lee | Alojamiento y crédito | Decisiones y límites |
|---|---|---|---|---|
| IGN LiDAR HD (bare-earth model, MNT) and RGE ALTI | El relieve alrededor del observador en Francia, tal como el láser midió la tierra desnuda, un punto por metro: sin árboles ni tejados. | Descargado con el relieve, una imagen del cuadrado a cuatro metros por píxel (menos de un megabyte), primero del láser y, donde aún no ha volado, del RGE ALTI, el modelo anterior de un metro que cubre todo el país. | © IGN, Licence Ouverte 2.0, servido por el WMS de la Géoplateforme, que responde a los navegadores desde cualquier sitio. Fuera de Francia, o cuando el servicio no responde en doce segundos, se usa el relieve mundial de abajo. | El relieve mundial es un modelo de la superficie a quince metros por píxel: medido contra el láser, se desvía uno o dos metros cerca del observador, y de cinco a veinte bajo el bosque o junto a una carretera en terraplén, lo que hunde o eleva todo edificio colocado encima. La malla nunca se mezcla de dos levantamientos vértice a vértice, lo que dibujaría su empalme como un acantilado. Donde responde, el suelo es una malla con un vértice cada siete metros, no 28: una carretera en terraplén mide treinta metros de ancho, y una malla más gruesa hundía la autopista de Silly-le-Long dos metros y la hacía dar tumbos. Donde el láser vio el tablero de un puente, el suelo se eleva hasta el tablero (el láser quita los puentes de la tierra desnuda, de modo que la carretera se hundiría en una zanja en cada paso elevado); un viaducto sobre un valle ancho deja allí un dique del ancho de un tablero. Para un observador inmóvil cuyo decorado se extiende más allá de los primeros 900 m (los silos en el horizonte de Maffliers), el parche de suelo real se ensancha, hasta 3 km como máximo, para que lo que se levanta allí descanse sobre el relieve y no sobre un disco plano; los parches de un trayecto lo siguen y no se ensanchan. |
| AWS Terrain Tiles (SRTM, ETOPO1) | El relieve alrededor del observador. | Descargado cuando una escena tiene un lugar real, fuera de Francia o donde el relieve del IGN de arriba no responde. | Amazon S3, sin clave. © AWS Open Data. | Sin clave y sin límite de peticiones, lo que necesita un componente integrable. El modelo de relieve es demasiado grueso para árboles y edificios: una foto del lugar alineada en la escena es la forma de declararlos. |
| Esri World Imagery | Imágenes aéreas extendidas sobre el relieve, y el mapa del observador. | Descargadas con el relieve, y al abrir el mapa. | Teselas de Esri, sin clave. © Esri, Maxar, Earthstar Geographics. | Una fotografía actual del suelo, sea cual sea el año del relato; la escena la oscurece según la hora. Se puede elegir en su lugar EOX Sentinel-2 cloudless. |
Lugar y hora
| Fuente | Qué proporciona | Cuándo se lee | Alojamiento y crédito | Decisiones y límites |
|---|---|---|---|---|
| Nominatim (OpenStreetMap) | Buscar un lugar por su nombre, y nombrar un punto. | Solo cuando el autor pulsa Intro o el botón de búsqueda, nunca con cada pulsación de tecla. | © colaboradores de OpenStreetMap. | Conoce aldeas, granjas, carreteras y aeródromos, donde ocurren los relatos; su política de uso es la razón de que no se envíe nada mientras se escribe. |
| Open-Meteo time zones and the IANA database | La zona horaria de un lugar, y luego su desfase legal en la fecha del relato. | En cuanto se conoce un lugar; el desfase histórico lo da el navegador. | © Open-Meteo; base de datos tz en el navegador. | El desfase actual nunca se usa para una fecha antigua: Francia estaba en UTC+1 todo el año en 1965. |
Decorado, fotos y sonido
| Fuente | Qué proporciona | Cuándo se lee | Alojamiento y crédito | Decisiones y límites |
|---|---|---|---|---|
| IGN LiDAR HD (canopy height model and classification) and BD TOPO (map vectors) | Los árboles, edificios, puentes y líneas aéreas alrededor de un lugar, en su lugar, altura y anchura medidos: del láser, la altura de todo lo que sobresale del suelo y lo que se tomó cada punto (planta, tejado), como imágenes de un cuadrado de cien metros; del mapa (BD TOPO), el eje de cada puente, la anchura de la carretera que lleva y cada línea eléctrica con su tensión; los nombres de lo que nombra (un ayuntamiento, una oficina de correos, la carretera que lleva un puente). En Francia las carreteras de la escena vienen del mismo mapa, con sus nombres, y no de OpenStreetMap, con una acera a cada lado de sus calles urbanas (el mapa dice cuáles lo son), y pintura en las carreteras asfaltadas lo bastante anchas para dos sentidos: según lo que el mapa dice de cada tramo: una calzada de autopista tiene sus bordes continuos (el de la mediana, y el del arcén donde acaban sus carriles) y una línea discontinua entre sus carriles; una carretera de doble sentido tiene el centro en trazos, continuo en las curvas, y los bordes continuos desde siete metros o 80 km/h, en trazos cortos por debajo; una carretera de cuatro carriles tiene una doble línea continua en el centro; nada en una rotonda, un camino o una pista. Donde el mapa no da carriles ni sentido (las carreteras de OpenStreetMap a menudo no los tienen), la carretera se pinta como cualquier carretera ancha, una línea de borde a cada lado y el centro en trazos. El mapa no tiene barreras: se dibuja una, a medio camino, entre dos calzadas de autopista que van en sentidos opuestos una junto a otra. Todo sobre un grano moteado de asfalto, a menos de 450 m del parche de suelo, y su código solo se carga para una escena que tenga una carretera así. | Por sí sola, del levantamiento que el autor eligió con el selector junto a la lista (el láser y el mapa juntos por defecto, uno u otro solo, o ninguno), cuando el autor da al registro un lugar que el levantamiento cubre (Francia, una caja que el propio servicio estrecha al no responder nada donde no ha volado), un momento después del último cambio de lugar; nunca cuando un registro solo se carga. | © IGN, Licence Ouverte 2.0, servido por el WMS de la Géoplateforme, que responde a los navegadores de cualquier origen. El servicio no da la fecha del levantamiento. Los puentes y las líneas vienen del WFS de la misma Géoplateforme; los pilones están en los vértices de la línea como la dibuja el mapa, de 22 m para 90 kV donde el láser no los midió. | El modelo de altura solo toma un tejado por un roble (291 m en la torre Eiffel), así que también se pide la clasificación y solo se conservan sus plantas y sus tejados. Es un barrido de un día, y un registro es de otro: lo que aporta se marca como procedente de un levantamiento, se sustituye cuando cambia el lugar y se deja como está donde el autor ha colocado árboles o edificios. |
| IGN aerial photograph (ORTHOIMAGERY.ORTHOPHOTOS) | El color del tejado de cada edificio, visto desde arriba: la mediana de la fotografía bajo su contorno, sin los verdes, algo aclarada porque la fotografía ya está iluminada por el sol. | Con el decorado de un levantamiento (véase arriba), en la misma petición: un cuadrado de mil píxeles como máximo. | © IGN, Licence Ouverte 2.0, del WMS de la Géoplateforme. La fotografía es del día del vuelo, no del registro. | La forma de un tejado (plano, dos vertientes, cuatro, hacia dónde corre la cumbrera) se lee en las alturas del láser dentro del contorno, solo dentro de 150 m; un tejado que no se sabe leer sigue siendo una caja y no una suposición. |
| INSEE, Enquête Emploi du temps 2009-2010 (via Rauch, Économie et statistique 522-523, 2021) | Cuándo está levantada la gente de una ciudad, para cuántas ventanas de sus edificios están encendidas según la hora del reloj: la mitad duerme a las 22:40, la mitad está levantada a las 7:00, nueve de cada diez duermen de 1:00 a 6:00. | Integrada en las ventanas encendidas de la escena; no se descarga nada. | Publicada por el INSEE; solo se usan las tres cifras anteriores. | La encuesta da medianas y una cota, no una curva: la dispersión alrededor de las medianas, los dos de cada cien siempre despiertos y la mitad de las ventanas encendidas cuando todos están despiertos son hipótesis, y el empleo del tiempo de Francia se toma para cualquier lugar. |
| OpenStreetMap buildings (Overpass) | Los edificios alrededor de un lugar en cualquier parte del mundo, como los dibujaron los voluntarios de OpenStreetMap: cada contorno como un rectángulo (o rectángulos), su altura donde la da (height, building:levels), su tejado (roof:shape, roof:height, roof:colour), el color y el material de sus muros, su nombre. Sin árboles. | Por sí sola, para un lugar fuera del alcance de los levantamientos del IGN cuando no se ha elegido ninguno (o cuando el láser del IGN resulta no haber volado allí, como sobre Bélgica), o cuando el autor la elige en la lista. | © colaboradores de OpenStreetMap (ODbL), a través de las instancias públicas de Overpass, una petición cada vez como las carreteras. Están saturadas: los edificios de una ciudad pueden tardar un minuto o más, y el indicador sobre la imagen se detiene eligiendo «Ninguno». | La mayoría de los edificios solo llevan building=yes: se dibujan con las medidas ordinarias (dos plantas, un tejado plano, un enlucido claro). Solo lo que está escrito se dibuja como está escrito. La cobertura vale lo que valen los voluntarios: una ciudad belga cuenta 4.600 edificios en un kilómetro y medio cuadrado, un pueblo del Oeste americano un puñado. |
| OpenStreetMap street lamps (Overpass) | Las farolas públicas alrededor de un lugar: cada farola cartografiada (highway=street_lamp), y una farola cada 35 m, alternando lados, a lo largo de cada calle marcada lit=yes. Se encienden con la oscuridad (el Sol bajo el horizonte), y las ocho más cercanas iluminan la escena. | Con el decorado de un levantamiento (véase arriba), en el mismo momento. | © colaboradores de OpenStreetMap (ODbL), a través de las instancias públicas de Overpass, una petición cada vez como las carreteras. | Los voluntarios marcan una calle como iluminada mucho más de lo que colocan sus farolas (tres farolas y ocho calles iluminadas en el centro de Saint-Lô), así que las farolas a lo largo de las calles iluminadas se dibujan, no se levantan. Una calle sin marcar no es necesariamente oscura. Muchas ciudades francesas apagan su alumbrado por la noche: un registro de una noche así debe tener sus farolas retiradas o apagadas. |
| 3D models (Kenney, Jagobo, Jungle Jim, Nicholas-3D, amvlab, Poly by Google, MakeHuman) | Coches, una casa, árboles, una farola, aviones de línea (A320, 737, A350, A380, 787), personas; y las naves y seres de los casos, construidos por el proyecto a partir de sus relatos. | Cuando un objeto del decorado o un cuerpo nombra un modelo; el propio catálogo se lee una vez. | Realojados en ufoathome.org, cada uno con su archivo de licencia: CC0 (Kenney, MakeHuman y los propios del proyecto), CC BY 4.0 (los árboles, los aviones de amvlab, la cabina del A320 de davidmarton1987), CC BY 3.0 (Poly by Google). El catálogo se lee primero de /models/index.json junto a la página, y luego de ufoathome.org, para que un sitio pueda servir su propia copia. Cada crédito se muestra en los créditos del reproductor. | Alojados aquí porque los kits libres están en réplicas de permanencia incierta. Un modelo cuyo crédito se desconoce no se dibuja; los modelos de Google Earth se rechazaron por su licencia, y el árbol de hoja ancha estilizado por no ser lo bastante realista. Las personas se construyen solo con los activos de sistema de MakeHuman, de licencia CC0: no se usan los paquetes de la comunidad, sus licencias difieren. Una nave o un ser se hace a partir de los documentos de su caso con un script que dice cuáles de sus detalles son supuestos, y cualquier modelo mejor lo sustituye tomando su id. Cada modelo es un sustituto del tipo correcto, no de una marca ni un año concretos, y el selector lo dice. Un modelo publica sus propios ajustes (un traje, el follaje, un casco, el tren recogido, qué luces y qué ruido le convienen), que el editor ofrece y que una grabación declara en modelParameters. Siempre que no se puede obtener un modelo, y cuando el observador está dentro del objeto, se dibuja en su lugar la forma integrada. |
| Panoramax | Fotografías y panorámicas a pie de calle cerca del lugar, cada una con su posición y dirección. | Solo cuando el autor busca fotos en el editor. | API de Panoramax, acreditada con el autor y la licencia de cada foto. | Abierta y legible desde cualquier página. Google Street View se rechazó: sus condiciones mantienen las fotos dentro de los visores de Google. |
| Weather sounds (OpenGameArt) | Lluvia, viento y trueno. | Cargados cuando la meteorología de la escena los necesita. | Incluidos. Lluvia y viento CC0; trueno de Jerimee, CC BY 3.0, acreditado en el reproductor. | El sonido propio del fenómeno se sintetiza a partir de su descripción, no se toma de una grabación. |
El detalle de cada decisión, con las mediciones que la zanjaron, está en los comentarios del código de cada fuente en el repositorio.