diff --git a/frontend/src/components/galaxy/__snapshots__/archetypes/plusieurs-petits-conjoints.txt b/frontend/src/components/galaxy/__snapshots__/archetypes/plusieurs-petits-conjoints.txt new file mode 100644 index 0000000..2d70e1b --- /dev/null +++ b/frontend/src/components/galaxy/__snapshots__/archetypes/plusieurs-petits-conjoints.txt @@ -0,0 +1,5 @@ + H1────•────G────•───H2────h3─h4 + │ │ + ┬────────┬────┴───┬ ┴──┬ + │ │ │ │ +K1 K2 K3 K4 diff --git a/frontend/src/components/galaxy/__snapshots__/archetypes/trois-petits-conjoints.txt b/frontend/src/components/galaxy/__snapshots__/archetypes/trois-petits-conjoints.txt new file mode 100644 index 0000000..50679de --- /dev/null +++ b/frontend/src/components/galaxy/__snapshots__/archetypes/trois-petits-conjoints.txt @@ -0,0 +1,5 @@ +Pa────•───Ma + │ + ┬─┴ + │ +h1──G─h2──h3 diff --git a/frontend/src/components/galaxy/elkLayout.js b/frontend/src/components/galaxy/elkLayout.js index c7d06dc..242cb52 100644 --- a/frontend/src/components/galaxy/elkLayout.js +++ b/frontend/src/components/galaxy/elkLayout.js @@ -33,7 +33,11 @@ export function chainGap(a, b, spacing) { const compactUnion = a?._compact && a._type === 'union' ? a : b?._compact && b._type === 'union' ? b : null if (!compactUnion) return spacing const other = compactUnion === a ? b : a - return other?._compact ? 0 : COMPACT_JOIN_GAP + if (other?.id === compactUnion._compactLone) return 0 + if (other?.id === compactUnion._compactPartner) return COMPACT_JOIN_GAP + // Plusieurs conjoints isolés à la suite : le voisin n'est pas ce couple, l'écart normal laisse la place + // aux noms et aux dates (sinon les petits portraits s'enchaînaient à 40 px, libellés les uns sur les autres) + return spacing } function makePairKey(a, b) { @@ -355,6 +359,7 @@ export function computeLayout(graphData = null, referenceId = null) { const isLoneSpouse = (pid) => !linkedByFiliation.has(pid) && unionCount.get(pid) === 1 const compactPartnerOf = new Map() // conjoint isolé → partenaire const compactUnionIds = new Map() // union de conjoint isolé → partenaire + const compactLoneOfUnion = new Map() // union de conjoint isolé → le conjoint isolé unions.forEach(u => { if (!u.partner1Id || !u.partner2Id) return let lone = null, partner = null @@ -363,6 +368,7 @@ export function computeLayout(graphData = null, referenceId = null) { if (!lone) return compactPartnerOf.set(lone, partner) compactUnionIds.set(`u-${u.id}`, `p-${partner}`) + compactLoneOfUnion.set(`u-${u.id}`, `p-${lone}`) }) // ---------------------------------------------------------- @@ -522,7 +528,7 @@ export function computeLayout(graphData = null, referenceId = null) { for (const { unionElkId, otherKey } of neighbors) { pushNode({ id: unionElkId, width: compactUnionIds.has(unionElkId) ? 0 : UNION_W, height: UNION_H, - ...(compactUnionIds.has(unionElkId) ? { _compact: true, _compactPartner: compactUnionIds.get(unionElkId) } : {}), + ...(compactUnionIds.has(unionElkId) ? { _compact: true, _compactPartner: compactUnionIds.get(unionElkId), _compactLone: compactLoneOfUnion.get(unionElkId) } : {}), _type: 'union', _data: unionEntryByElkId.get(unionElkId) || { id: unionElkId }, _generation: gen, diff --git a/tools/layout-bench/archetypes.mjs b/tools/layout-bench/archetypes.mjs index 7c67006..c2a08cd 100644 --- a/tools/layout-bench/archetypes.mjs +++ b/tools/layout-bench/archetypes.mjs @@ -63,6 +63,26 @@ export const archetypes = [ filiations: [L('E1', 'u', 1), L('E2', 'u', 2), L('K', 'u1')], }, }, + { + slug: 'plusieurs-petits-conjoints', + note: 'G a quatre conjoints : H1 (trois enfants), H2 (un enfant), H3 et H4 sans parent ni enfant dans l arbre. Les petits portraits ne se chevauchent pas, leurs noms non plus.', + reference: 'K1', + graph: { + persons: ids(['G', 'H1', 'H2', 'H3', 'H4', 'K1', 'K2', 'K3', 'K4']), + unions: [U('u1', 'H1', 'G', 1), U('u2', 'G', 'H2', 2), U('u3', 'G', 'H3', 3), U('u4', 'G', 'H4', 4)], + filiations: [L('K1', 'u1', 1), L('K2', 'u1', 2), L('K3', 'u1', 3), L('K4', 'u2')], + }, + }, + { + slug: 'trois-petits-conjoints', + note: 'G a trois conjoints sans parent ni enfant dans l arbre, et ses parents. Aucun petit portrait ni nom ne se chevauche.', + reference: 'G', + graph: { + persons: ids(['Pa', 'Ma', 'G', 'H1', 'H2', 'H3']), + unions: [U('u', 'Pa', 'Ma'), U('u1', 'G', 'H1', 1), U('u2', 'G', 'H2', 2), U('u3', 'G', 'H3', 3)], + filiations: [L('G', 'u')], + }, + }, { slug: 'fratrie-12', note: 'Douze enfants, chacun marié, les six premiers avec deux enfants, les autres avec un. La ligne de fratrie est longue, c est normal.', diff --git a/tools/layout-bench/invariants.mjs b/tools/layout-bench/invariants.mjs index 38de306..7be9238 100644 --- a/tools/layout-bench/invariants.mjs +++ b/tools/layout-bench/invariants.mjs @@ -83,8 +83,14 @@ export function checkInvariants(result, coupleBarMeta, graph, referenceId = null if (!spousesOf.has(p1.id)) spousesOf.set(p1.id, new Set()) if (!spousesOf.has(p2.id)) spousesOf.set(p2.id, new Set()) spousesOf.get(p1.id).add(p2.id); spousesOf.get(p2.id).add(p1.id) + } + // Une personne ne touche que deux conjoints sur sa rangée, un de chaque côté : à partir de trois, les suivants + // s'enchaînent plus loin, ce n'est pas un défaut du placement + for (const c of coupleBarMeta) { + const p1 = byId.get(c.p1Key), p2 = byId.get(c.p2Key) + if (!p1 || !p2) continue if (p1._generation !== p2._generation) couples_rangee++ - else if (Math.abs(p1.x - p2.x) > maxAdj) couples_separes++ + else if (Math.abs(p1.x - p2.x) > maxAdj && spousesOf.get(p1.id).size <= 2 && spousesOf.get(p2.id).size <= 2) couples_separes++ } // Fratries : contiguës (seuls les frères, sœurs et leurs conjoints entre le premier et le dernier) et dans l'ordre choisi