如何防止在族树生成器中重叠?

时间:2015-12-01 03:19:02

标签: javascript charts jsplumb family-tree genealogy

我正在创建一个交互式家谱树创建者,不像更简单的版本是简单的谱系图表/树。

我的要求(基于familyecho.com)是:

  • 多个合作伙伴与您通常看到的简单2父母对1个孩子。
  • 多个兄弟姐妹
  • 合作伙伴不一定需要生孩子
  • 并不总是必须是父母"对",只有一个父亲/母亲

我遇到的问题是:我根据"当前"生成偏移量。节点/家庭成员,当我经过第一代时,说2个父母,它重叠。

重叠的示例以及未在同一X轴上绘制的合作伙伴:

enter image description here

以下是actual appmain js file我遇到问题的地方。这里是我创建的simplified jsfiddle,它演示了父/偏移问题,但我确实必须解决这个一般的重叠问题,此外还要确保合作伙伴在同一个x轴上绘制作为其他伙伴。

我如何解决这个问题以及未来可能发生的重叠冲突?我是否需要某种重绘功能来检测collisions并在检测到时调整每个块的偏移量?我试图让它无缝化,因此进行了有限的重绘。

计算相对于"上下文的偏移量的示例"或当前节点:

var offset = getCurrentNodeOffset();

                        if ( relationship == RELATIONSHIPS.PARTNER ) {
                            var t = offset.top; // same level
                            var l = offset.left + ( blockWidth + 25 );
                        } else {
                            var t = offset.top - (blockHeight + 123 ); // higher
                            var l = offset.left - ( blockWidth - 25 );
                        }

3 个答案:

答案 0 :(得分:18)

我将给出一个复杂的答案,那是因为这种情况比你想象的要复杂得多。图形布局算法是一个活跃的研究领域。尝试一种比一般算法简单的算法更容易,然后当你做出无根据的,通常是隐藏的假设时,它会以惊人的方式失败。

一般来说,遗传继承图是平面(见维基百科上的Planar Graphs)。虽然不常见,但肯定会发生所有祖先关系都没有被独特的人填补。例如,当第二代堂兄弟有孩子时就会发生这种情况。

在非一夫一妻制的父母的情况下,可能会出现另一种非平面情况。最简单的例子是两个男人和两个女人,每个女人与孩子配对(因此至少有四个)。如果没有曲线,你甚​​至不能在一个等级中布置四个父对。

这些仅是示例。我相信你在研究你的算法时会发现更多。这里真正的教训是明确地对您的算法能够布局的关系类进行建模,并在算法中使用验证码来检测数据何时不符合这些要求。

然而,你实际问的问题要基本得多。您遇到了基本的困难,因为您需要使用图表的depth-first traversal。这是“从上到下”(在其中一条评论中)布局的最简单的完整版本。这只是tree traversal的许多算法之一。

你正在制作一个有(至少)隐含的等级概念的有向图。主题是0级;父母是1级;排名第2的祖父母。(上述警告,排名并不总是唯一的。)这些图的大部分区域都在祖先。如果您没有首先布置叶节点,那么您没有任何成功的希望。我们的想法是首先布置排名最高的节点,逐步合并排名较低的节点。深度优先遍历是执行此操作的最常见方式。

我会将其视为图形重写算法。基本数据结构是渲染子图和基础祖先图的混合体。渲染子图是(1)整个图的子树,其中(1a)是一组后代,其所有祖先都被渲染,(2)渲染数据的集合:节点和线的位置等。初始状态混合的是整个图形,没有渲染的子图。最终状态是渲染的整个图形。算法的每一步都将混合图的叶边界处的一些元素集转换为(更大的)渲染子图,从而减少混合中元素的数量。最后只有一个元素,即整个渲染图。

答案 1 :(得分:3)

由于您已经在使用Family Echo,我建议您查看他们如何开发在线家谱图,因为它们似乎已经解决了您的问题。

当我将示例图输入到Family Echo中时,我可以构建一个漂亮的树,看起来像是你正在寻找的没有交叉的。

enter image description here

虽然他们使用html和css创建图表,但您可以逐个将人员添加到他们的图表中,然后根据每个元素的左侧和顶部像素位置检查框的放置位置。

enter image description here

如果我有更多的JavaScript专业知识,我会尝试构建一些代码来复制Family Echo所做的一些事情,但我担心这不是我的魔力。

答案 2 :(得分:1)

你必须调整你所影响的节点上的所有分支,每个分支都必须重新计算其节点的位置,并且每个节点都必须在本地重新计算到达叶子。你计算一旦叶子是将不得不重新计算所有的方式进行备份,所有这些都是递归的。它就像一棵真正的树,当你向树干添加物理分支时...其他分支单独移动以留出一些空间,所有工作表都会自动重置,所以你必须想象。并在图表中模拟此过程。处理每个分支到达每个叶子,并重新计算以重新计算已修改的节点邻居。 (比你开始高一级)这不容易或单一工作。