Om du vill att en Graphviz-hierarki ska läsas som en indragen disposition på din Mac ger du varje nod en rad och en indragspunkt och renderar sedan med neato -n2. Det bevarar föräldra–barn-kanterna samtidigt som du kan styra läsordningen.
Den här genomgången skapar ett exempel med sex noder och exporterar en PDF. Målet är specifikt: en nod per rad, underordnade noder direkt under sin förälder och samma indrag för noder på samma djup. Graphviz dokumenterar rendering med fasta positioner via sitt -n-kommandoradsalternativ.
Varför ser inte ett vanligt Graphviz-träd ut som en disposition?
En hierarki beskriver relationer; en indragen disposition anger också en läsordning. I det här exemplet innehåller roten två grenar, och den första grenens underordnade noder måste visas före den andra grenen. Den önskade ordningen är:
Nod R
Nod A
Nod C
Nod D
Nod B
Nod E
Grafens relationer går från roten till A, från roten till B, från A till C, från A till D och från B till E. Det finns ingen relation från D till B bara för att B står på nästa rad. DOT uttrycker riktade kanter med operatorn ->; noddeklarationer och deras presentationsattribut är separata delar av språket. Se den officiella referensen för DOT-språket.
Graphviz-motorn dot skapar hierarkiska eller skiktade ritningar. Den strävar efter att rikta kanter i en gemensam riktning och samtidigt minska korsningar och kantlängder. Det målet passar ett förgrenat diagram, men definierar inte dispositionen med en nod per rad som visas ovan. Se dokumentationen för layouten dot.
Flera välbekanta attribut löser bara en del av problemet:
| Inställning | Dokumenterat syfte | Vad den inte löser |
|---|---|---|
rankdir=LR |
Ändrar layoutriktningen till vänster till höger | Anger inte en vertikal ordning för dispositionen |
rank=same |
Placerar noderna i en delgraf på samma nivå | Tilldelar inte varje nod en egen rad i dispositionen |
ordering=out |
Begränsar utgående kanter så att de visas från vänster till höger i indatans ordning | Definierar inte indrag efter djup och radkoordinater |
Dessa begränsningar framgår av de officiella referenserna för rankdir, rank och ordering. För den exakta radordningen i den här artikeln ger uttryckliga koordinater en mer direkt konstruktion än att kombinera dessa attribut.
Hur förbereder du Graphviz på en Mac?
Öppna Terminal. Om du redan använder Homebrew installerar du Graphviz med följande kommando. Den officiella nedladdningssidan för Graphviz listar den här installationsmetoden för Mac:
brew install graphviz
Om du i stället använder MacPorts listar samma nedladdningssida sudo port install graphviz. Välj den pakethanterare du redan använder. Om ingen av dem är installerad följer du den relevanta installationslänken från den sidan innan du återgår till den här genomgången.
Kontrollera att renderaren är tillgänglig:
neato -V
Alternativet -V skriver ut versionsinformation för Graphviz. Spara den angivna versionen när du jämför resultat mellan datorer; du behöver inte en viss versionssiffra som anges i den här artikeln. Graphviz dokumenterar det här alternativet i sin kommandoradsreferens.
Hur skapar du den indragna hierarkin?
Följande kompletta skalblock skapar en ny arbetsmapp och skriver DOT-filen där. Kör det i Terminal; mappsökvägen skrivs ut när det är klart. Den citerade heredoc-avgränsaren bevarar DOT-texten som den är skriven.
outline_dir=$(mktemp -d "$HOME/graphviz-outline.XXXXXX")
if [ -n "$outline_dir" ] && cd "$outline_dir"; then
cat > hierarchy.dot <<'DOT'
digraph Hierarchy {
graph [splines=ortho, bgcolor=white];
node [
shape=box,
width=1.2,
height=0.35,
fixedsize=true,
fontname="Courier",
fontsize=12
];
r [label="Node R", pos="100,300"];
a [label="Node A", pos="136,252"];
c [label="Node C", pos="172,204"];
d [label="Node D", pos="172,156"];
b [label="Node B", pos="136,108"];
e [label="Node E", pos="172,60"];
r -> a;
r -> b;
a -> c;
a -> d;
b -> e;
}
DOT
pwd
fi
Nodernas positioner kodar dispositionen. Varje efterföljande rad flyttas ned 48 punkter, och varje ytterligare djup flyttas 36 punkter åt höger. De talen är illustrativa avståndsval, inte Graphviz-standardvärden. Dokumentationen för pos anger att nodpositioner avser nodernas mittpunkter och att neato tolkar positioner som punkter när det används med -n.
| Nod | Djup | Rad, med start på noll | Mittposition |
|---|---|---|---|
| Nod R | 0 | 0 | 100,300 |
| Nod A | 1 | 1 | 136,252 |
| Nod C | 2 | 2 | 172,204 |
| Nod D | 2 | 3 | 172,156 |
| Nod B | 1 | 4 | 136,108 |
| Nod E | 2 | 5 | 172,60 |
I den här konstruktionen är koordinatreglerna x = 100 + 36 × depth och y = 300 − 48 × row. Lägg märke till återgången från Nod D till Nod B: raden flyttas framåt, men djupet minskar. Det är den övergången som får ritningen att läsas som en disposition i stället för en kedja.
Alla rutor har samma mått, så lika mittkoordinater gör också att deras vänsterkanter ligger i linje. De syntetiska etiketterna med samma längd gör det enkelt att jämföra textplaceringen. Med fixedsize=true använder Graphviz de angivna nodmåtten i stället för att förstora rutorna så att innehållet ryms; för stora etiketter ger en varning. Se referensen för fixedsize.
Hur renderar och granskar du resultatet?
Kör följande i samma Terminal-session och arbetsmapp:
neato -n2 -Tpdf hierarchy.dot -o hierarchy.pdf
Här behåller -n2 den angivna nodordningen utan överlappsjustering och beräknar rutter för kanter som saknar egna positioner. Därför måste varje nod ha ett värde för pos. Alternativen -Tpdf och -o väljer PDF-utdata och dess mål. Dessa funktioner dokumenteras i kommandoradsreferensen.
Öppna arbetsmappen i Finder och öppna hierarchy.pdf. PDF-utdata kräver en Graphviz-version som innehåller Cairo-renderaren, enligt Graphvizs sida om PDF-utdata. Exemplet har kontrollerats mot dokumentationen, men har inte renderatestats här eftersom Graphviz saknades i forskningsmiljön.
Granska tre saker var för sig:
- Läs nedåt: R, A, C, D, B och E ska ligga på efterföljande rader.
- Jämför indragen: A och B ska ligga i linje; C, D och E ska ligga ett steg längre åt höger.
- Följ relationerna: R ansluter till A och B; A ansluter till C och D; B ansluter till E.
De två första kontrollerna bedömer koordinatkonstruktionen. Den tredje kontrollerar själva grafen. Genom att hålla kontrollerna åtskilda blir det lättare att upptäcka ett diagram som ser välordnat ut men har en felaktig föräldra–barn-kant.
Kommer kopplingarna att se exakt ut som ett träd i en filhanterare?
Nodernas rader och indrag är uttryckligen angivna; kopplingarnas rutter beräknas fortfarande. Exemplet begär splines=ortho, som drar kanter genom axelparallella segment. Graphvizs dokumentation anger också att den här routningen inte hanterar portar, så kompassportar är inte ett dokumenterat sätt att tvinga fram ett visst mönster av rätvinkliga hörn. Se referensen för splines.
Den här konstruktionen ger därför en indragen hierarki med automatiskt routade rätvinkliga kopplingar. Den föreskriver inte en enda gemensam vertikal linje med exakt placerade förgreningspunkter. Om den kopplingsgeometrin är viktig krävs ytterligare en konstruktion med uttryckligen angivna kantbanor; splines=ortho uttrycker inte ensamt det kravet.
För en ren disposition utan synliga kopplingar ändrar du diagraminställningen till splines=none och renderar igen. DOT-filen innehåller fortfarande föräldra–barn-kanterna, medan renderaren utelämnar deras streck. Det här är ett dokumenterat renderingsalternativ i samma referens för splines.
Hur anpassar du exemplet utan att ändra dess betydelse?
Börja med att skriva den tänkta läsordningen separat från kantlistan. Besök först en förälder och sedan dess första barn och barnets underordnade noder, innan du går vidare till nästa barn. Tilldela varje nod i den ordningen en rad. Tilldela sedan indrag efter djup.
Om du till exempel vill lägga till ytterligare ett barn under Nod A efter Nod D infogar du det i läsordningen före Nod B. Ge det djup två, flytta senare rader nedåt och lägg till en kant från A till den nya noden. De befintliga föräldrarelationerna ändras inte bara för att radnumren ändras.
Använd följande felsökningsordning när en redigerad version ser felaktig ut:
- Ritningen får en annan spridning: kontrollera att kommandot fortfarande använder
neato -n2. Exemplet bygger på angivna positioner i stället för vanlig automatisk layout. - Renderingen rapporterar att en position saknas: kontrollera varje nod-ID, även ID:n som bara nämns i kantinstruktioner. I det här arbetsflödet behöver varje nod en positionsangiven deklaration.
- En etikett sticker utanför sin ruta: öka de gemensamma rutmåtten eller korta etiketten. Rutor med fasta mått expanderar inte automatiskt.
- Rader överlappar efter att rutorna har förstorats: öka radavståndet. Det valda renderingsläget bevarar positionerna i stället för att korrigera överlappningar.
- En gren ansluter till fel nod: rätta kantinstruktionen. Det går inte att reparera en felaktig relation genom att flytta en ruta.
Förhållandena vid saknade positioner och överlappningar följer Graphvizs dokumenterade -n2-beteende; etikettförhållandet följer dess beteende för fixedsize. Att öka avståndet är motsvarande designjustering för det här manuellt positionerade exemplet.
Låt hierarkins kantlista vara källan till relationerna och koordinattabellen källan till presentationen. För ett litet diagram på en Mac-dator gör den uppdelningen resultatet enkelt att underhålla: ändra kanter när hierarkin ändras, ändra rader när läsordningen ändras och ändra avstånden när etiketterna behöver mer utrymme.
Källor
- DOT-språket — Graphviz
- dot — Graphviz
- rankdir — Graphviz
- rank — Graphviz
- ordering — Graphviz
- Nedladdning — Graphviz
- Kommandorad — Graphviz
- pos — Graphviz
- fixedsize — Graphviz
- PDF — Graphviz
- splines — Graphviz