El árbol tiene 46.454 personas y llega hasta 151 generaciones atrás. Cuando se eligen dos personas, el visor dice exactamente cómo están emparentadas. No hay magia: hay una idea muy vieja y muy bonita de las matemáticas llamada grafo. Esta página lo explica sin tecnicismos primero y con el detalle después.
01Todo es un grafo
Un grafo es solo dos cosas: puntos y flechas que los unen. En este árbol, cada punto es una persona y cada flecha va de un hijo hacia un padre. La persona raíz —en este caso Julián, el autor— es el punto de abajo del todo; sus ancestros se van apilando hacia arriba.
Eso es todo el «mapa». Una vez que el computador tiene esa lista de puntos y flechas, puede responder preguntas que a un humano le tomarían semanas con un árbol de papel.
▶Para curiosos (lo técnico)
Los datos vienen de FamilySearch y se preprocesan a un JSON con dos listas: nodes (personas) y edges (pares [padre, hijo]). Al cargar, se construyen dos diccionarios para movernos rápido en ambos sentidos:
for (const [padre, hijo] of edges) {
childrenOf.get(padre).push(hijo); // hacia abajo
parentsOf.get(hijo).push(padre); // hacia arriba
}Con parentsOf subo hacia los ancestros; con childrenOf bajo hacia la descendencia. Casi todo lo demás se construye sobre estos dos mapas.
02Conectar dos personas: el antepasado común
Esta es la parte más vistosa. Al elegir dos personas, el árbol dibuja dónde se juntan sus líneas de sangre. La idea es como seguir dos ríos hacia su nacimiento: se sube por los padres de A y por los de B, y el primer ancestro que aparece en ambos caminos es el punto donde esas dos personas «se vuelven familia».
Por ejemplo, el abuelo paterno y la abuela materna de Julián parecían dos ramas independientes; el árbol encontró que sus líneas convergen varias generaciones atrás en un mismo antepasado. Eso sí es revelador: en el fondo venían del mismo tronco.
▶Para curiosos (lo técnico)
Se hace con una BFS (búsqueda en anchura) hacia arriba desde cada persona, guardando a qué distancia queda cada ancestro. Luego se busca el ancestro común que minimiza la suma de distancias: el más reciente (en genealogía, el «MRCA»).
const sube = (inicio) => { // ancestros y su distancia
const dist = new Map([[inicio, 0]]);
const cola = [inicio];
for (let i = 0; i < cola.length; i++)
for (const p of parentsOf.get(cola[i]) ?? [])
if (!dist.has(p)) { dist.set(p, dist.get(cola[i]) + 1); cola.push(p); }
return dist;
};
const a = sube(A), b = sube(B);
let nca = null, mejor = Infinity;
for (const [id, da] of a) // ancestro en ambos
if (b.has(id) && da + b.get(id) < mejor)
{ mejor = da + b.get(id); nca = id; }Si una persona es ancestro de la otra, el «punto de encuentro» es ella misma y sale la línea directa. Si no comparten ningún ancestro, el árbol lo dice en vez de inventar una conexión.
03Por qué no a través de la raíz
Hubo un detalle delicioso aquí. La primera versión buscaba el camino más corto entre las dos personas… y para dos ancestros de ramas distintas, ¡el camino más corto baja hasta el único punto donde se tocan: la propia persona raíz! Técnicamente correcto, pero inútil: «el abuelo y la abuela se conectan… en su nieto». Cierto, pero obvio.
La corrección fue cambiar la pregunta: no «¿cuál es el camino más corto?», sino «¿dónde convergen sus líneas hacia atrás?». Por eso ahora el árbol siempre sube a buscar el antepasado común, y nunca baja a través de la raíz.
04Las parejas: un puente rosado
Los datos no dicen «estos dos estuvieron casados». Pero se puede deducir: si dos personas comparten un hijo, eran pareja. Con esa regla se marcan las 24.558 parejas del árbol con un puente rosado que las une, distinto de las líneas grises de padre-hijo, para que de un vistazo se lea «estos dos → estos hijos».
▶Para curiosos (lo técnico)
Resultó que el 92,7% de las parejas ya quedaban pegadas en el dibujo (el recorrido que ordena el árbol visita a los dos padres seguidos), así que el puente casi siempre es un arquito corto. Se dibuja con una curva de Bézier por encima del par y solo cuando hay suficiente zoom, para no saturar la vista general.
05Dibujar 46.000 puntos sin morir
Un árbol así, dibujado con elementos normales de una página web, ahogaría al navegador. El truco es pintarlo en un canvas (un lienzo de píxeles) y hacer trampa con inteligencia: solo se dibuja lo que cae dentro de la pantalla en cada momento, y al alejar el zoom, los puntos lejanos ni se calculan.
▶Para curiosos (lo técnico)
Cada cuadro se redibuja sobre <canvas> con la transformación de zoom/paneo de d3-zoom. Antes de pintar cada punto se descarta lo que está fuera del «viewport» (culling), así el costo depende de lo que ves, no de los 46k totales. Detalles que costaron sangre: forzar un radio mínimo en pantalla para que los puntos no desaparezcan al alejar, reencuadrar la cámara al cambiar la profundidad, y —el bug más escurridizo— asegurarse de que el dibujante siempre use el estado más reciente y no una copia vieja capturada al montar el componente.
06En resumen
Se modela la familia como puntos y flechas; subir por las flechas lleva a los ancestros, bajar a la descendencia. Con eso, «¿cómo se conectan dos personas?» se vuelve «¿dónde se cruzan sus caminos hacia atrás?», y «¿son pareja?» se vuelve «¿comparten un hijo?». El resto es pintarlo rápido y con cariño.
Lo más bonito: estas ideas tienen décadas y sirven para mapas, redes sociales, rutas de buses o un árbol familiar. Aquí sirvieron para trazar de dónde viene una familia entera.