сложная графическая структура дерева - PullRequest
11 голосов
/ 25 мая 2010

Я пытаюсь создать древовидную структуру с графвизом. Я открыт либо для написания кода GraphViz вручную, либо для использования ruby-graphviz gem для ruby. Учитывая приведенную ниже картинку, может ли кто-нибудь дать представление о необходимом коде? Проигнорируйте, что линии не являются прямыми ... они должны быть, когда graphviz строит граф. Я открыт для точек / точек, когда линии также пересекаются.

Я играл с ruby-graphviz и классом генеалогического дерева ... это помогает мне пройти часть пути, но мне действительно нужно, чтобы все линии были прямыми и пересекались под прямым углом, а не из коробки кажется, код этого не делает.

Код должен быть достаточно универсальным, чтобы в поле «C» могли также быть дети, и чтобы в группе «A» также было больше детей.

Цвета не имеют значения ... примеры могут исключать любую окраску.

http://docs.google.com/drawings/pub?id=1lUTfgKP_LN0x7C3ItbsFjfLBuDTL84AtmoaW7YFn32Y&w=1036&h=713

Ответы [ 3 ]

12 голосов
/ 13 января 2011

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

digraph {
    splines=false;
    ranksep=0.05;

    node[shape=box, color=lightblue, style=filled];
    A;B;C;D;E;

    node[shape=none, color=none, style=solid];
    i1[label="Item 1"];
    i2[label="Item 2"];
    i3[label="Item 3"];

    node[label="", width=0, height=0];
    edge[arrowhead=none, color=blue];

    {rank=same; n2; n1; n3;}
    n2; n1; n3;
    A -> n1;
    n2 -> n1 -> n3;

    {rank=same; B; C;}
    n2 -> B;
    n3 -> C;

    {rank=same; n4; D;}
    B -> n4 -> D;

    {rank=same; n6; n5; i1;}
    D -> n5 -> i1;
    n4 -> n6;

    {rank=same; n7; E;}
    n6 -> n7 -> E;

    {rank=same; n8; i2;}
    E -> n8 -> i2;

    {rank=same; n9; i3;}
    i2 -> n9 -> i3;
}

Прямые линии обеспечиваются:

  • splines=false - скажи нет сплайнам
  • невидимые узлы (узлы n1, n2, ... n9)
  • размещение узлов на одном уровне с rank=same

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

Вывод выглядит так:

graphviz output

Пока у C нет дочерних узлов, вам придется применить еще несколько хитростей (невидимых узлов), чтобы отобразить их полностью вправо.

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

4 голосов
/ 30 мая 2010

Насколько я знаю, это требует небольшого обходного решения; Я буду делать это только на языке Graphviz DOT. Сначала я дам вам решение, а затем объясню, как вы можете его расширить.

Это итоговая цифра:

outfile.png

Это код Graphviz, создающий фигуру:

graph atree {
  Item1 [shape=none,label="Item 1",pos="2.2,1.1!"];
  Item2 [shape=none,label="Item 2",pos="2.2,0.1!"];
  Item3 [shape=none,label="Item 3",pos="2.9,-0.3!"];
  A [shape=box,color=lightblue,style=filled,pos="2,3!"];
  B [shape=box,color=lightblue,style=filled,pos="1,2.1!"];
  C [shape=box,color=lightblue,style=filled,pos="3,2.1!"];
  D [shape=box,color=lightblue,style=filled,pos="1.5,1.5!"];
  E [shape=box,color=lightblue,style=filled,pos="1.5,0.5!"];
  D0 [style=invisible,fixedsize=true,width=0,height=0,pos="2,2.5!",label=""];
  D1 [style=invisible,fixedsize=true,width=0,height=0,pos="1,2.5!",label=""];
  D2 [style=invisible,fixedsize=true,width=0,height=0,pos="3,2.5!",label=""];
  D3 [style=invisible,fixedsize=true,width=0,height=0,pos="1,1.5!",label=""];
  D4 [style=invisible,fixedsize=true,width=0,height=0,pos="1,0.5!",label=""];
  D5 [style=invisible,fixedsize=true,width=0,height=0,pos="1.5,1.1!",label=""];
  D6 [style=invisible,fixedsize=true,width=0,height=0,pos="1.5,0.1!",label=""];
  D7 [style=invisible,fixedsize=true,width=0,height=0,pos="2.2,-0.3!",label=""];
  A -- D0 -- D1 -- B -- D3 -- D4 -- E [color=blue];
  E -- D6 -- Item2 -- D7 -- Item3 [color=blue];
  D0 -- D2 -- C [color=blue];
  D3 -- D -- D5 -- Item1 [color=blue];
}

Если вы поместите его в файл с именем inputfile.dot, вы можете получить полученный файл изображения с помощью команды neato -Tpng inputfile.dot > outfile.png.

Теперь пара комментариев о том, как это работает: код, строящий дерево с A, B, C, D, E, Item1, Item2, Item3, прост (атрибуты просто задают цвета и стили ящиков). Хитрость для получения прямых и ортогональных линий состоит в 1) добавлении невидимых узлов с нулевым размером к графику и 2) позиционировании всех объектов в абсолютных координатах на холсте. Вспомогательные узлы D1, D2, D3, D4, D5, D6, D7 необходимы для шага 1), а опции pos="x,y!" необходимы для шага 2). Обратите внимание, что вам нужен знак ! в конце команды pos, так как в противном случае позиции не будут считаться окончательными, а расклад все равно будет изменен.

Вы можете добавить дополнительные узлы, сначала разместив новый узел (используя код для узлов A ... Item3 в качестве шаблона), добавив невидимый вспомогательный узел (с pos таким образом, чтобы все соединения с ним и с него были ортогональный), а затем добавление соединения к графику через <StartingNode> -- <AuxiliaryNode> -- <NewNode>.

3 голосов
/ 13 сентября 2012

Еще одна версия, использующая splines=ortho, которая требует меньше скрытых узлов и дает аналогичный визуальный результат.

digraph example {
    splines=ortho;
    ranksep=0.05;

    node[shape=box, color=lightblue, style=filled];
    A;B;C;D;E;

    node[shape=none, color=none, style=solid];
    i1[label="Item 1"];
    i2[label="Item 2"];
    i3[label="Item 3"];

    node[label="", width=0, height=0];
    edge[arrowhead=none, color=blue];
    n1; n2; n3; n4; n5;

    {rank=same; B; C;}
    A -> n1;
    n1 -> B;
    n1 -> C;

    {rank=same; n2; D;}
    B -> n2;
    n2 -> D;

    {rank=same; n3; i1;}
    D -> n3;
    n3 -> i1;

    {rank=same; n4; E;}
    n2 -> n4;
    n4 -> E;

    {rank=same; n5; i2;}
    E -> n5;
    n5 -> i2;

    {rank=same; n6; i3;}
    i2 -> n6;
    n6 -> i3;
}

dot image drawn via PlantUML.com

...