GraphViz - Як підключити підграф?


166

У DOTмові для GraphViz, я намагаюся уявити діаграму залежності. Мені потрібно мати можливість мати вузли всередині контейнера та вміти робити вузли та / або контейнери залежними від інших вузлів та / або контейнерів.

Я використовую subgraphдля представлення своїх контейнерів. Зв'язування вузлів працює чудово, але я не можу зрозуміти, як підключити підграф.

З огляду на нижченаведену програму, мені потрібно вміти підключатися cluster_1і cluster_2зі стрілкою, але все, що я намагався, створює нові вузли замість підключення кластерів:

digraph G {

    graph [fontsize=10 fontname="Verdana"];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Renders fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Both of these create new nodes
    cluster_1 -> cluster_2;
    "Container A" -> "Container C";
}

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


2
У мене така ж проблема, але вони мають природний приклад, коли підграграфи діють як вузли, graphviz.org/content/fdpclust .
nlucaroni

1
@nlucaroni мені цікаво, чи вирішена ця проблема. цей приклад дає мені неправильний графік: краї з'єднують центри підграфа. ти не знаєш, як змусити його працювати так, як у прикладі?
k102

1
@ k102, я знаю. Перевірте цю сторінку ще раз; там написано, що потрібно використовувати fdp. Зв'язаний приклад і той, що знаходиться над обома роботами (в останньому рядку в прикладі тут потрібно використовувати назви підграфів, а не мітку, і може бути непогано включити довжини рядків для графіка); це трохи тісно, ​​як є).
nlucaroni

1
@nlucaroni Використовуючи fdpv2.28.0 та копіюючи / вставляючи джерело з прикладу, лінії підключаються до центру підграфу, а не до країв. Якщо ви відкриєте .dot в OmniGraffle, вони належним чином підключені, тоді як neatoі dotобидва створюють зайві вузли для кластера.
Фрогз

Відповіді:


190

Посібник користувача DOT дає наступний приклад графіку з кластерами з краями між кластерами:

ВАЖЛИВО: Початкове compound=trueповідомлення обов'язкове.

digraph G {
  compound=true;
  subgraph cluster0 {
    a -> b;
    a -> c;
    b -> d;
    c -> d;
  }
  subgraph cluster1 {
    e -> g;
    e -> f;
  }
  b -> f [lhead=cluster1];
  d -> e;
  c -> g [ltail=cluster0,lhead=cluster1];
  c -> e [ltail=cluster0];
  d -> h;
}

... і краї між вузлами та кластерами:

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


14
Спасибі - це працює, але це справді відчуває себе некрасивим злом. Я сподіваюся, що у мене немає сценарію, де у мене є контейнер без вузлів.
Вінстон Сміт

5
Якщо когось цікавить, це може спричинити проблеми з позиціонуванням, якщо у вас є мічені посилання (ребра). Хоча голова або хвіст краю можуть бути сховані під кластером, мітка все ще розташована в середині точки, тобто деякі крайові мітки, схоже, плавають над кластером, а не розміщуються самим краєм.
Вінстон Сміт

58
@WinstonSmith: Старе питання, але у мене була подібна проблема, і я вирішив її невидимим макетним вузлом на кластер, який можна пов’язати, навіть якщо кластер порожній інакше. DUMMY_0 [shape=point style=invis]
DevSolar

2
Я виявив, що мої міжкластерні краї згортаються лише на головки стрілок, коли використовуються кластери, які з'єднані лише вертикально. Я виправив це з міленом = 1 по краях. c -> g [ltail = cluster0, lhead = cluster1, minlen = 1];
Фріннерд

3
Ось посилання на посібник із прикладом: graphviz.org/Documentation/dotguide.pdf (стор. 30).
Кирило Булигін

90

Для зручності посилання рішення, описане у відповіді HighPerformanceMark, застосованому безпосередньо до оригінального питання, виглядає приблизно так:

digraph G {

    graph [fontsize=10 fontname="Verdana" compound=true];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Edges between nodes render fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Edges that directly connect one cluster to another
    "Item 1" -> "Item 3" [ltail=cluster_0 lhead=cluster_1];
    "Item 1" -> "Item 5" [ltail=cluster_0 lhead=cluster_2];
}

compound=trueУ graphдекларації має життєво важливе значення. Це дає результат:

графік із підключеними кластерами

Зауважте, що я змінив ребра на опорні вузли в кластері, додав атрибути ltail і lhead до кожного краю, вказавши ім'я кластера, і додав атрибут рівня графа 'складова = істина'.

Що стосується занепокоєння, що, можливо, захочеться з'єднати кластер без вузлів всередині нього, моє рішення було завжди додавати вузол до кожного кластеру, наданий у стилі style = plaintext. Використовуйте цей вузол для позначення кластера (замість вбудованого атрибута "label" кластера, який слід встановити на порожню рядок (в Python, label='""'). Це означає, що я більше не додаю ребра, які безпосередньо з'єднують кластери, але це працює в моїй конкретній ситуації.


24
Примітка: 'graph [fontsize = 10 fontname = "Verdana" з'єднання = вірно];' важливо - якщо ви пропустите, що посилання на ltail / lhead не працює.
с.Даніель

1
@JonathanHartley, Відповідно до вашого останнього абзацу, чи є який-небудь спосіб відцентрувати цей вузол прямо посередині кластера?
Pacerier

також назва кластера не повинна починатися з великої літери
JCLL

7
@ s.Daniel Це просто з'єднання = правда; що потрібно
доктор Макс Вьолкель

Замість скидання lhead та ltail при посиланні "Пункт 1" -> "Пункт 3", як я пов’язую cluster_0 та cluster_1 із значущим кодом? Я мам, cluster_0 -> cluster_1подарувати, коли ви виходите. Оскільки може бути багато елементів у посиланні cluster_0 до інших багатьох елементів кластера_1 (багато до багатьох або один до багатьох). Було б добре просто зв'язати два.
Мітріл

11

Переконайтеся, що ви використовуєте fdpмакет для файлу. Я не думаю, що neatoпідтримує кластери.


2
Я теж експериментально встановив, що neatoдвигун не підтримує кластери .. Я не впевнений, це помилка чи ні ..
Росс Роджерс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.