Как я могу предотвратить дублирование в генераторе генеалогического древа?

Я создаю интерактивный создатель генеалогического древа, в отличие от более простых версий, которые представляют собой простые схемы / деревья родословных.

Требования к моему (на основе familyecho.com):

  • несколько партнеров против просто двух родителей на одного ребенка, которых вы обычно видите.
  • несколько братьев и сестер
  • партнерам необязательно иметь детей
  • не всегда обязательно должна быть родительская "пара", может быть только отец / мать-одиночка

Проблема, с которой я столкнулся: я генерирую смещения на основе «текущего» узла / члена семьи, и когда я прохожу мимо первого поколения, скажем, с двумя родителями, они перекрываются.

Пример перекрытия и изображения партнера не на одной оси X:

введите здесь описание изображения

Вот актуальное приложение и main js file, где у меня возникла проблема. А вот созданный мной упрощенный jsfiddle, демонстрирующий проблему родительского / смещения, хотя мне действительно нужно решить перекрытие для этого в целом, в дополнение к тому, чтобы убедиться, что партнеры нарисованы на той же оси x, что и другие партнеры.

Как я могу решить этот и возможные в будущем конфликты, которые накладываются друг на друга? Нужна ли мне какая-то функция перерисовки, которая обнаруживает коллизии и корректирует смещения каждого блока при обнаружении ? Я пытаюсь сделать его бесшовным, поэтому выполняется ограниченное количество перерисовок.

Пример вычисления смещения относительно «контекста» или текущего узла:

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 );
                        }

person meder omuraliev    schedule 01.12.2015    source источник
comment
Чтобы ответить на вопрос о пересечении дедушки и бабушки, все, что вам нужно сделать, это увеличить расстояние между рассматриваемыми родителями, возможно?   -  person Rodrigo    schedule 05.12.2015
comment
Вы пробовали размещать узлы сверху вниз вместо нынешнего подхода снизу вверх? Вы получаете перекрытие, потому что (по крайней мере, в примере JavaScript) вы позиционируете родителей в зависимости от положения ребенка. Это терпит неудачу, потому что при добавлении новых родителей не учитываются родственные узлы, а просто сбрасывается их туда и надеется на лучшее.   -  person aroth    schedule 05.12.2015
comment
@Rodrigo - кажется, я пробовал это, но наткнулся на кое-что еще. Попробую воссоздать на другой скрипке.   -  person meder omuraliev    schedule 05.12.2015
comment
@aroth - В настоящее время это просто снизу вверх, и я считаю, что мне, возможно, придется иметь функцию, которая запускается при каждом новом добавлении узла, она будет проверять коллизии и / или повторно обновлять каждый узел. На самом деле я пытался повторить все это в d3js, используя подход сверху вниз, но я столкнулся с аналогичными проблемами, поэтому я мог бы просто решить их здесь.   -  person meder omuraliev    schedule 05.12.2015
comment
Вот мое быстрое и грязное исправление коллизий при добавлении узлов (должно устранить основную проблему, но, конечно, вызовет некоторые проблемы с вертикальным выравниванием ... которые можно решить отдельно): jsfiddle.net/efLbbt01/10   -  person aroth    schedule 05.12.2015
comment
Я считаю, что самый простой способ - пройтись по дереву целиком, измерив общую высоту и ширину. Тогда вы сможете правильно нарисовать дерево.   -  person Rodrigo    schedule 05.12.2015
comment
@Rodrigo - вы имеете в виду каждый узел и исключая строки? Каждый блок 100x90 пикселей, холст будет 5000x5000, но я могу сделать его больше.   -  person meder omuraliev    schedule 05.12.2015
comment
Да, вы узнаете размер холста только после итерации всего дерева.   -  person Rodrigo    schedule 05.12.2015
comment
Разве это не умножение общего количества узлов на блок 100x90?   -  person meder omuraliev    schedule 05.12.2015
comment
@aroth - хорошо, но как бы ты сделал так, чтобы мама и папа всегда были рядом?   -  person meder omuraliev    schedule 05.12.2015
comment
@meder - делая рендеринг менее безгражданским. Реализация примера на jsfiddle просто как бы добавляет узлы в DOM и надеется на лучшее. На практике я бы подошел к этому типу вещей, чтобы явно поддерживать древовидную структуру в памяти и иметь ее доступную при рендеринге, чтобы у меня было больше контекста относительно того, как узел, с которым я работаю, относится к другие узлы. Хотя также я полагаю, что должны быть уже существующие JS-библиотеки для красивого рендеринга направленных ациклических графов / деревьев?   -  person aroth    schedule 05.12.2015
comment
@aroth - Ничего подобного, что я видел для конкретного использования. Включая goJS, jTree, диаграммы Google и другие. Ближайшим из них может быть gojs.net/latest/samples/genogram.html.   -  person meder omuraliev    schedule 05.12.2015
comment
@aroth - то, что я собирался сделать, похоже на ваше объяснение. Вместо того, чтобы рисовать каждый узел по отдельности, пройдитесь по всему дереву при каждом добавлении узла и нарисуйте каждый узел или настройте (существующий) в зависимости от окружающего + поколения, но это становится сложным, я думаю, потому что, если я скажу, поколение за поколением, может быть несогласованность по вертикали по оси Y, если это имеет смысл. Вы бы порекомендовали начать с вершины дерева и спускаться поколение за поколением?   -  person meder omuraliev    schedule 05.12.2015


Ответы (3)


Я собираюсь дать сложный ответ, потому что эта ситуация сложнее, чем вы думаете. Алгоритмы построения графиков - активная область исследований. Легко попытаться применить алгоритм, который проще простого, а затем он резко потерпит неудачу, если вы сделаете необоснованные и обычно скрытые предположения.

В общем, графы генетического наследования не плоские (см. Планарные графы на Википедия). Хотя это редкость, но, конечно, бывает, что все родовые отношения не связаны с уникальными людьми. Так бывает, например, когда у троюродных братьев есть дети.

Другая неплоская ситуация может возникнуть в ситуации детей от немоногамных родителей. Самый простой пример - двое мужчин и две женщины, у каждой пары с детьми (то есть как минимум четверо). Вы не можете выложить даже четыре родительские пары в один ряд без изогнутых линий.

Это только примеры. Я уверен, что вы откроете для себя больше, работая над своим алгоритмом. Настоящий урок здесь состоит в том, чтобы явным образом смоделировать класс отношений, который может определить ваш алгоритм, и иметь код проверки в алгоритме, чтобы определять, когда данные не соответствуют этим требованиям.

Однако вопрос, который вы на самом деле задаете, гораздо более простой. У вас возникают основные трудности, потому что вам нужно использовать обход в глубину график. Это (самый простой) полный вариант того, что значит выкладывать «сверху вниз» (в одном из комментариев). Это только один из многих алгоритмов обхода дерева.

Вы строите ориентированный граф с (по крайней мере) неявным понятием ранга. Субъект имеет ранг 0; родители - 1 ранг; дедушки и бабушки на 2-м месте. (Что касается предупреждений выше, ранжирование не всегда уникально.) Большая часть таких графов относится к родословной. Если вы не разместите сначала листовые узлы, у вас нет никакой надежды на успех. Идея состоит в том, что сначала вы размещаете узлы с наивысшим рангом, постепенно добавляя узлы с более низким рангом. Обход в глубину - наиболее распространенный способ сделать это.

Я бы рассматривал это как алгоритм перезаписи графа. Базовая структура данных представляет собой гибрид визуализированных подграфов и нижележащего графа предков. Отрендеренный подграф - это (1) поддерево всего графа с (1a) набором потомков, все предки которого визуализируются, и (2) набором данных визуализации: положения узлов и линий и т. Д. Начальное состояние гибрида представляет собой весь граф и не имеет отрисованных подграфов. Конечное состояние - это визуализированный весь граф. Каждый шаг алгоритма преобразует некоторый набор элементов на границе листа гибридного графа в (более крупный) визуализированный подграф, уменьшая количество элементов в гибриде. В конце есть только один элемент, граф рендеринга в целом.

person eh9    schedule 05.12.2015
comment
Ага, ты прав, я пришел к этому осознанию. Хотя мне действительно трудно переварить последние 2 абзаца того, что вы сказали. Можно ли придумать более простое объяснение? - person meder omuraliev; 05.12.2015
comment
@meder Я добавил несколько ссылок и расширил последние абзацы. - person eh9; 08.12.2015
comment
Есть ли шанс, что вы можете объяснить с помощью этих данных, как вы пройдете через него, используя путешествие на глубину? Я прочитал о концепции, но все еще немного запутался. Итак, вы сказали, что расположить узлы с наивысшим рангом, но включить узлы с более низким рангом - разве это не подход в ширину? Вот образец дерева - как бы вы его прошли? i.imgur.com/o1OunBa.png. Вы бы начали с самого высокого ранга Джона Рэймонда Бетти и пошли вниз? Или вы начинаете с одного из трех предков и спускаетесь до самого нижнего ребенка? - person meder omuraliev; 25.12.2015
comment
static.arounds.org/tree-new Это моя попытка визуализировать его по уровням. Корень - уровень 0. Все, что ниже - -1, все, что выше - больше 0. Вы предлагаете такую ​​визуализацию? Очевидно, мне нужно будет действительно реорганизовать его, чтобы учесть положение детей по отношению к их родителям. - person meder omuraliev; 25.12.2015
comment
Добавленные изображения и данные заслуживают отдельного вопроса. Правильно их решать не лучше в комментариях. Свяжите здесь новый вопрос, а затем добавьте здесь комментарий с последующим вопросом. - person eh9; 29.12.2015
comment
будет делать после того, как я попробую DFS еще раз. Спасибо! - person meder omuraliev; 29.12.2015
comment
Я добавил сюда новый вопрос: stackoverflow.com/questions/34539786/. Был бы признателен, если бы у вас была возможность посмотреть. Спасибо. - person meder omuraliev; 31.12.2015

Поскольку вы уже используете Family Echo, я бы посоветовал вам посмотреть, как они создают свою онлайн-диаграмму генеалогического древа. , поскольку они, кажется, решили вашу проблему.

Когда я ввожу ваш образец диаграммы в Family Echo, я могу построить красивое дерево, которое кажется именно тем, что вы ищете, без пересечения.

введите здесь описание изображения

Хотя они создают свои диаграммы с помощью html и css, вы можете добавлять людей к их диаграммам один за другим, а затем проверять, где расположены блоки с точки зрения расположения левого и верхнего пикселей каждого элемента.

введите здесь описание изображения

Если бы у меня было больше опыта в JavaScript, я бы попытался создать код, чтобы воспроизвести часть того, что делает Family Echo, но, боюсь, это не мое моджо.

person lkessler    schedule 05.12.2015
comment
Код действительно слишком запутан, чтобы его можно было понять. Там много математики и есть фреймы. Не так-то просто понять, как это делает familyecho. Следовательно, в основном спрашивается, как это сделать аналогичным образом. - person meder omuraliev; 05.12.2015
comment
Тогда вместо того, чтобы изобретать велосипед, почему бы не попытаться использовать какой-нибудь код javascript, который для этого создали многие другие. Например, кажется, есть несколько приличных, которые вы могли бы использовать как есть или изменять на GitHub, например: github.com/chandlerprall/FamilyTreeJS или github.com/wamacdonald89/ftree.js или github.com/djfun/geneajs - person lkessler; 05.12.2015
comment
Также см. Этот связанный вопрос о stackoverflow, у которого могут быть некоторые идеи для вас: stackoverflow.com/questions/5639142/ - person lkessler; 05.12.2015
comment
Я исследовал почти все соответствующие вопросы и проекты SO, и ни один из них не соответствовал потребностям. github.com/djfun/geneajs может показаться хорошим началом. - person meder omuraliev; 05.12.2015
comment
Ссылка на philogb.github.io/jit/static / v20 / Jit / Examples / Hypertree / - это потребует обширных настроек для моей диаграммы, что в основном будет таким же объемом работы / переделкой того, что я делаю. - person meder omuraliev; 05.12.2015
comment
Я бы не рекомендовал нестандартную или трехмерную визуализацию схем генеалогического древа. Большинству людей (включая меня) они не нравятся. - person lkessler; 05.12.2015
comment
Что ж, если вы встретите диаграмму, которая похожа на ту, которая мне нужна, дайте мне знать! Я искал, но еще не нашел. - person meder omuraliev; 05.12.2015

вам нужно будет отрегулировать все ответвления от узла, на который вы воздействуете, каждая ветвь должна будет пересчитать положение своих узлов, и каждый узел придется пересчитывать локально, достигая листьев. чтобы пересчитать все время до резервного копирования, все это рекурсивно. Это похоже на настоящее дерево, когда вы физически добавляете ветвь к стволу ... другие ветки перемещаются самостоятельно, чтобы оставить место, все листы автоматически сбрасываются, так что вы должны представить. И смоделируйте этот процесс на своей диаграмме. Обрабатывает каждую ветвь до каждого листа и пересчитывает, чтобы пересчитать измененные соседи узла. (на один уровень выше, чем вы начали) Это непростая задача.

person Community    schedule 11.12.2015
comment
Можете ли вы уточнить, что вы подразумеваете под одной работой? - person meder omuraliev; 12.12.2015
comment
может быть вам это полезно: github.com/mbostock/d3/wiki/Gallery третья галерея № 30 (Развернутое дерево): bl.ocks.org/robschmuecker/7880033 - person ; 13.01.2016
comment
Или это (Collapsible Force Layout): mbostock.github.com/d3/ talk / 20111116 / force-collapsible.html в той же галерее: github.com/mbostock / d3 / wiki / Галерея - person ; 13.01.2016