Библиотека визуализации дерева - та, которая вычисляет все координаты узла и линии для данных данного дерева - PullRequest
2 голосов
/ 05 декабря 2011

(Visual) мир C ++. У меня есть древовидная структура, хочу ее визуализировать. Более конкретно:

У меня есть данные дерева. Мне нужна библиотека, которая обрабатывает эти данные и вычисляет координаты (в любом логическом координатном пространстве, скажем, 2000x2000 логических пикселей) для каждого узла и для каждой линии, соединяющей их. Линия, соединяющая два узла, может не быть простой прямой линией, это может быть кривая или какой-то путь, состоящий из отрезков прямой линии. В идеале мне бы хотелось, чтобы линия, определяющая путь, была рассчитана и для координат заданных узлов дерева, в случае, если пользователь будет перетаскивать и переставлять узлы.

Вскоре мне нужна библиотека, которая вычислит все необходимые геометрические координаты для меня, для данного графика. Затем я буду использовать эти координаты для рисования графика, как я хочу, используя GDI.

Я слышал о Graphviz, точечном языке и тому подобном. Но я не уверен, что он (или его альтернативы, такие как OGDF или igraph) могут делать то, что я хочу. Идея, которую я хочу реализовать, состоит в том, чтобы визуализировать график самостоятельно, но мне нужна помощь в создании координат. Кроме того, пользователь должен иметь возможность перемещать узлы, поэтому пересчет пути линии, который соединяет переставленные узлы, должен быть возможен, например, чтобы линии не пересекают существующие узлы.

1 Ответ

3 голосов
/ 05 декабря 2011

Да , графвиз может сделать это.

Макет ориентированного графа

Допустим, у вас есть следующий график в tree.gv:

digraph g{
  a[label="I"];
  b[label="am"];
  c[label="a"];
  d[label="tree"];
  e[label="with"];
  f[label="7"];
  g[label="nodes"];

  a -> b -> c;
  b -> d -> e;
  d -> f;
  d -> g;
}

dot может выложить этот график: dot tree.gv, что приводит к

digraph g {
    node [label="\N"];
    graph [bb="0,0,208,252"];
    a [label=I, pos="63,234", width="0.75", height="0.5"];
    b [label=am, pos="63,162", width="0.75", height="0.5"];
    c [label=a, pos="27,90", width="0.75", height="0.5"];
    d [label=tree, pos="99,90", width="0.75", height="0.5"];
    e [label=with, pos="27,18", width="0.75", height="0.5"];
    f [label=7, pos="99,18", width="0.75", height="0.5"];
    g [label=nodes, pos="176,18", width="0.89579", height="0.5"];
    a -> b [pos="e,63,180.1 63,215.7 63,207.98 63,198.71 63,190.11"];
    b -> c [pos="e,35.304,107.15 54.65,144.76 50.288,136.28 44.853,125.71 39.959,116.2"];
    b -> d [pos="e,90.696,107.15 71.35,144.76 75.712,136.28 81.147,125.71 86.041,116.2"];
    d -> e [pos="e,41.796,33.385 84.43,74.834 74.25,64.938 60.476,51.546 48.969,40.359"];
    d -> f [pos="e,99,36.104 99,71.697 99,63.983 99,54.712 99,46.112"];
    d -> g [pos="e,159.91,33.626 114.58,74.834 125.4,65.003 140,51.723 152.26,40.582"];
}

Все координаты можно найти в выходных данных. Если вам нужно больше подробностей о том, как рисовать график, вы можете попробовать использовать формат xdot: dot -Txdot tree.gv

digraph g {
    node [label="\N"];
    graph [bb="0,0,208,252",
        _draw_="c 9 -#ffffffff C 9 -#ffffffff P 4 0 -1 0 252 209 252 209 -1 ",
        xdotversion="1.2"];
    a [label=I, pos="63,234", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 63 234 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 63 228 0 5 1 -I "];
    b [label=am, pos="63,162", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 63 162 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 63 156 0 17 2 -am "];
    c [label=a, pos="27,90", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 27 90 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 27 84 0 7 1 -a "];
    d [label=tree, pos="99,90", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 99 90 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 99 84 0 21 4 -tree "];
    e [label=with, pos="27,18", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 27 18 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 27 12 0 24 4 -with "];
    f [label=7, pos="99,18", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 99 18 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 99 12 0 7 1 -7 "];
    g [label=nodes, pos="176,18", width="0.89579", height="0.5", _draw_="c 9 -#000000ff e 176 18 32 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 176 12 0 34 5 -nodes "];
    a -> b [pos="e,63,180.1 63,215.7 63,207.98 63,198.71 63,190.11", _draw_="c 9 -#000000ff B 4 63 216 63 208 63 199 63 190 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 67 190 63 180 60 190 "];
    b -> c [pos="e,35.304,107.15 54.65,144.76 50.288,136.28 44.853,125.71 39.959,116.2", _draw_="c 9 -#000000ff B 4 55 145 50 136 45 126 40 116 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 43 114 35 107 37 118 "];
    b -> d [pos="e,90.696,107.15 71.35,144.76 75.712,136.28 81.147,125.71 86.041,116.2", _draw_="c 9 -#000000ff B 4 71 145 76 136 81 126 86 116 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 89 118 91 107 83 114 "];
    d -> e [pos="e,41.796,33.385 84.43,74.834 74.25,64.938 60.476,51.546 48.969,40.359", _draw_="c 9 -#000000ff B 4 84 75 74 65 60 52 49 40 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 51 38 42 33 47 43 "];
    d -> f [pos="e,99,36.104 99,71.697 99,63.983 99,54.712 99,46.112", _draw_="c 9 -#000000ff B 4 99 72 99 64 99 55 99 46 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 103 46 99 36 96 46 "];
    d -> g [pos="e,159.91,33.626 114.58,74.834 125.4,65.003 140,51.723 152.26,40.582", _draw_="c 9 -#000000ff B 4 115 75 125 65 140 52 152 41 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 155 43 160 34 150 38 "];
}

Подробную информацию об этом формате можно найти на веб-сайте graphviz.

Компоновка только ребер / пересчитать ребра

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

neato -n tree.modified.gv

Это пересчитает только края (более подробную информацию о опциях neato dot и neato можно найти на их страницах справочника ).

Ниже вы можете увидеть пример неизмененного и измененного макета - я изменил позиции для узлов b и g .

Автоматическая раскладка:

Autolayout

Модифицированный макет:

Modified layout

...