Merge pull request #223 from IliesAllali/fix/plusieurs-conjoints-isoles

Placement : plusieurs conjoints isolés ne se chevauchent plus
This commit is contained in:
IliesAllali authored and GitHub committed 2026-11-11 13:01:00 +01:00
commit 3f1d8f9ccd
5 files changed
+45 -3

No files matched your search

@@ -0,0 +1,5 @@
H1────•────G────•───H2────h3─h4
│ │
┬────────┬────┴───┬ ┴──┬
│ │ │ │
K1 K2 K3 K4
@@ -0,0 +1,5 @@
Pa────•───Ma
│
┬─┴
│
h1──G─h2──h3
+8 -2
View File
@@ -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,
+20
View File
@@ -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.',
+7 -1
View File
@@ -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