|
|
|
|
@@ -74,14 +74,19 @@ export function ComplexFamilyTree(p: {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const exportPDF = async () => {
|
|
|
|
|
const docWidth = treeWidth(p.tree) * 60;
|
|
|
|
|
const docHeight = treeHeight(p.tree) * 41;
|
|
|
|
|
|
|
|
|
|
const doc = new jsPDF({
|
|
|
|
|
orientation: "l",
|
|
|
|
|
format: [900, 1200],
|
|
|
|
|
format: [docHeight, docWidth],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Clone the SVG to manipulate it
|
|
|
|
|
const container = document.createElement("div");
|
|
|
|
|
container.classList.add("f3", "f3-export");
|
|
|
|
|
container.style.width = docWidth + "px";
|
|
|
|
|
container.style.height = docHeight + "px";
|
|
|
|
|
document.body.appendChild(container);
|
|
|
|
|
applyTree(container);
|
|
|
|
|
|
|
|
|
|
@@ -105,11 +110,13 @@ export function ComplexFamilyTree(p: {
|
|
|
|
|
`class="text-overflow-mask" fill="transparent"`
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
dstSVG = dstSVG.replaceAll(`>UNKNOWN<`, `fill="#000">INCONNU<`);
|
|
|
|
|
|
|
|
|
|
target.innerHTML = dstSVG;
|
|
|
|
|
|
|
|
|
|
await doc.svg(target, {
|
|
|
|
|
height: 3508,
|
|
|
|
|
width: 2480,
|
|
|
|
|
height: docHeight,
|
|
|
|
|
width: docWidth,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
container.remove();
|
|
|
|
|
@@ -134,6 +141,37 @@ export function ComplexFamilyTree(p: {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function treeHeight(node: FamilyTreeNode): number {
|
|
|
|
|
let res =
|
|
|
|
|
node.down?.reduce((prev, node) => Math.max(prev, treeHeight(node)), 0) ?? 0;
|
|
|
|
|
|
|
|
|
|
node.couples?.forEach(
|
|
|
|
|
(c) =>
|
|
|
|
|
(res = Math.max(
|
|
|
|
|
res,
|
|
|
|
|
c.down.reduce((prev, node) => Math.max(prev, treeHeight(node)), 0)
|
|
|
|
|
))
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return res + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function treeWidth(node: FamilyTreeNode): number {
|
|
|
|
|
const values = new Array(treeHeight(node)).fill(0);
|
|
|
|
|
treeWidthRecurse(node, values, 0);
|
|
|
|
|
return Math.max(...values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function treeWidthRecurse(node: FamilyTreeNode, vals: number[], level: number) {
|
|
|
|
|
vals[level] += 1 + (node.couples?.length ?? 0) + (node.down ? 1 : 0);
|
|
|
|
|
|
|
|
|
|
node.down?.forEach((n) => treeWidthRecurse(n, vals, level + 1));
|
|
|
|
|
|
|
|
|
|
node.couples?.forEach((c) =>
|
|
|
|
|
c.down.forEach((n) => treeWidthRecurse(n, vals, level + 1))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function treeToF3Data(node: FamilyTreeNode, isUp: boolean): f3Data[] {
|
|
|
|
|
const availableMembers = new Set<number>();
|
|
|
|
|
getAvailableMembers(node, availableMembers);
|
|
|
|
|
|