Я хочу сгенерировать это:
С этой структурой данных (ids являются случайными, btw не последовательными):
var tree = [
{ "id": 1, "name": "Me", "dob": "1988", "children": [4], "partners" : [2,3], root:true, level: 0, "parents": [5,6] },
{ "id": 2, "name": "Mistress 1", "dob": "1987", "children": [4], "partners" : [1], level: 0, "parents": [] },
{ "id": 3, "name": "Wife 1", "dob": "1988", "children": [5], "partners" : [1], level: 0, "parents": [] },
{ "id": 4, "name": "son 1", "dob": "", "children": [], "partners" : [], level: -1, "parents": [1,2] },
{ "id": 5, "name": "daughter 1", "dob": "", "children": [7], "partners" : [6], level: -1, "parents": [1,3] },
{ "id": 6, "name": "daughter 1s boyfriend", "dob": "", "children": [7], "partners" : [5], level: -1, "parents": [] },
{ "id": 7, "name": "son (bottom most)", "dob": "", "children": [], "partners" : [], level: -2, "parents": [5,6] },
{ "id": 8, "name": "jeff", "dob": "", "children": [1], "partners" : [9], level: 1, "parents": [10,11] },
{ "id": 9, "name": "maggie", "dob": "", "children": [1], "partners" : [8], level: 1, "parents": [] },
{ "id": 10, "name": "bob", "dob": "", "children": [8], "partners" : [11], level: 2, "parents": [12] },
{ "id": 11, "name": "mary", "dob": "", "children": [], "partners" : [10], level: 2, "parents": [] },
{ "id": 12, "name": "john", "dob": "", "children": [10], "partners" : [], level: 3, "parents": [] },
{ "id": 13, "name": "robert", "dob": "", "children": [9], "partners" : [], level: 2, "parents": [] },
{ "id": 14, "name": "jessie", "dob": "", "children": [9], "partners" : [], level: 2, "parents": [15,16] },
{ "id": 15, "name": "raymond", "dob": "", "children": [14], "partners" : [], level: 3, "parents": [] },
{ "id": 16, "name": "betty", "dob": "", "children": [14], "partners" : [], level: 3, "parents": [] },
];
Чтобы дать описание структуры данных, задан корневой/начальный node (me). Любой партнер (жена, бывший) находится на одном уровне. Все ниже становится уровнем -1, -2. Все, что указано выше, это уровень 1, 2 и т.д. Для родителей, братьев и сестер, детей и партнеров существуют свойства, определяющие идентификаторы для этого конкретного поля.
В предыдущем question, eh9 описал, как он это решит. Я пытаюсь это сделать, но, как я выяснил, это непростая задача.
Моя первая попытка показывает это по уровням сверху вниз. В этой более упрощенной попытке я в основном гнездю всех людей по уровням и отбрасываю их сверху вниз.
Моя вторая попытка дает это с одним из узлов-предков с использованием поиска глубины.
Мой главный вопрос:. Как я могу применить этот ответ к тому, что у меня есть? Во второй попытке я пытаюсь сделать первый проход, но как я могу даже начать учитывать расчёт, необходимый для смещения сеток, чтобы он соответствовал тому, как я хочу сгенерировать это?
Кроме того, мое понимание/реализация идеала глубины в первом случае, или я могу пройти это по-другому?
Узлы, очевидно, перекрываются в моем втором примере, поскольку у меня нет кода вычисления смещения/расстояния, но я теряюсь, чтобы понять, как я могу начать это.
Вот описание функции ходьбы, которую я сделал, где я пытаюсь выполнить первый проход глубины:
// this is used to map nodes to what they have "traversed". So on the first call of "john", dict would internally store this:
// dict.getItems() = [{ '12': [10] }]
// this means john (id=10) has traversed bob (id=10) and the code makes it not traverse if its already been traversed.
var dict = new Dictionary;
walk( nested[0]['values'][0] ); // this calls walk on the first element in the "highest" level. in this case it "john"
function walk( person, fromPersonId, callback ) {
// if a person hasn't been defined in the dict map, define them
if ( dict.get(person.id) == null ) {
dict.set(person.id, []);
if ( fromPersonId !== undefined || first ) {
var div = generateBlock ( person, {
// this offset code needs to be replaced
top: first ? 0 : parseInt( $(getNodeById( fromPersonId ).element).css('top'), 10 )+50,
left: first ? 0 : parseInt( $(getNodeById( fromPersonId ).element).css('left'), 10 )+50
});
//append this to the canvas
$(canvas).append(div);
person.element = div;
}
}
// if this is not the first instance, so if we're calling walk on another node, and if the parent node hasn't been defined, define it
if ( fromPersonId !== undefined ) {
if ( dict.get(fromPersonId) == null ) {
dict.set(fromPersonId, []);
}
// if the "caller" person hasn't been defined as traversing the current node, define them
// so on the first call of walk, fromPersonId is null
// it calls walk on the children and passes fromPersonId which is 12
// so this defines {12:[10]} since fromPersonId is 12 and person.id would be 10 (bob)
if ( dict.get(fromPersonId).indexOf(person.id) == -1 )
dict.get(fromPersonId).push( person.id );
}
console.log( person.name );
// list of properties which house ids of relationships
var iterable = ['partners', 'siblings', 'children', 'parents'];
iterable.forEach(function(property) {
if ( person[property] ) {
person[property].forEach(function(nodeId) {
// if this person hasnt been "traversed", walk through them
if ( dict.get(person.id).indexOf(nodeId) == -1 )
walk( getNodeById( nodeId ), person.id, function() {
dict.get(person.id).push( nodeId );
});
});
}
});
}
}
Требования/ограничения:
- Это для редактора и будет похоже на familyecho.com. Практически любые бизнес-правила, не определенные, могут быть приняты через это.
- Разведение в семье не поддерживается, так как это слишком сложно. Не беспокойтесь об этом.
- Поддерживаются несколько партнеров, поэтому это не так просто, как традиционное "семейное древо" с двумя родителями и одним ребенком.
- Существует только один "корень" node, который является только стартовым node.
Примечания: familyecho.com, похоже, "скрывает" ветвь, если есть множество листовых узлов и есть столкновение. Возможно, потребуется выполнить это.