Улучшение диаграммы Тикза

Я только что закончил свою первую диаграмму в Tikz. Выглядит так, как я хотел, но я недоволен тем, как я это «закодировал»:

\begin{tikzpicture}
[node distance=14mm,
 item/.style={rounded corners,rectangle,
   thick,
   minimum width=20mm, minimum height=10mm}]

\node[item,draw=blue!50,fill=blue!20] (stack) {1394 Stack};
\node[item,left=of stack,draw=green!50,fill=green!20,yshift=-9mm] (app1) {Application};
\node[item,left=of stack,draw=green!50,fill=green!20,yshift=9mm] (app2) {Application};
\node[item,right=of stack,draw=orange!50,fill=orange!20] (ohci) {OHCI};
\node[item,right=of ohci,yshift=-15mm,draw=yellow!70,fill=yellow!35] (dev1) {Device};
\node[item,right=of ohci,yshift=0mm,draw=yellow!70,fill=yellow!35] (dev2) {Device};
\node[item,right=of ohci,yshift=15mm,draw=yellow!70,fill=yellow!35] (dev3) {Device};

\draw[thick] (app1) -- (stack)
             (app2) -- (stack)
             (stack) -- (ohci)
             (ohci) -- (dev1)
             (ohci) -- (dev2)
             (ohci) -- (dev3);

\node[xshift=7mm,yshift=1mm] (topUser) at (app1.east |- dev3.north) {};
\node[xshift=7mm,yshift=-1mm,label=above left:User space] (botUser) at (app1.east |- dev1.south) {};
\draw[dashed] (topUser) -- (botUser);

\node[xshift=7mm,yshift=1mm] (topKern) at (stack.east |- dev3.north) {};
\node[xshift=7mm,yshift=-1mm,label=above left:Kernel space,
label=above right:Hardware\phantom{p}] (botKern) at (stack.east |- dev1.south) {};
\draw[dashed] (topKern) -- (botKern);
\end{tikzpicture}

Что меня не устраивает:

Как я вручную переместил узлы «Приложение» и «Устройство», используя yshift, чтобы отделить их друг от друга; Я уверен, что должен быть более элегантный способ создания простой древовидной структуры.

Линии (topKern -- botKern и topUser -- botUser), идущие от верха изображения до низа; они вручную выравниваются по оси x, чтобы они находились между двумя узлами, используя xshift=7mm.

Я использую \phantom{p}, чтобы гарантировать, что метка «Оборудование» имеет такую ​​же основу, что и две другие метки.


person Freddie Witherden    schedule 07.08.2010    source источник
comment
К вашему сведению, такого рода вопросы можно найти на сайте TeX / LaTeX Stack Exchange, который сейчас находится на стадии публичной бета-версии. Если хотите, можете закрыть этот вопрос и опубликовать его на другом сайте.   -  person David Z    schedule 08.08.2010


Ответы (1)


Чтобы построить древовидную структуру, обратитесь к pgfmanual.pdf, Как заставить деревья расти.

Для линий я бы создал узлы, представляющие середину двух узлов, а затем использовал бы перпендикулярную систему координат, как вы. Также вы можете использовать current bounding box для обозначения «границы».

Чтобы правильно выровнять базовые линии, укажите text height и text depth. В вашем случае например в стиле every label. Но, как видите, я сделал надписи как узлы ниже ...

\begin{tikzpicture}[level distance=35mm,node distance=15mm,text height=1.5ex,text depth=0.25ex]

\begin{scope}[every node/.style={rounded corners,rectangle,thick,minimum width=20mm, minimum height=10mm}]
\begin{scope}[level 1/.style={sibling distance=19mm,nodes={fill=green!20,draw=green!50}}]
\node[draw=blue!50,fill=blue!20] (stack) {1394 Stack} [grow=left]
  child {node (app2) {Application}}
  child {node (app1) {Application}};
\end{scope}

\begin{scope}[level 1/.style={sibling distance=15mm,nodes={fill=yellow!70,draw=yellow!35}}]
\node[right= of stack,draw=orange!50,fill=orange!20] (ohci) {OHCI} [grow=right]
  child {node {Device}}
  child {node {Device}}
  child {node {Device}};
\end{scope}
\end{scope}

\node[below=0mm of app1] (userspace) {User space};
\node at (userspace -| stack) (kernel) {Kernel};
\node at (userspace -| ohci) (hardware) {Hardware}; 

\path (app1) -- (stack) node[coordinate,midway] (between1) {};
\draw (ohci) -- (stack) node[coordinate,midway] (between2) {};

\draw[dashed] (current bounding box.north -| between1) -- (current bounding box.south -| between1);
\draw[dashed] (current bounding box.north -| between2) -- (current bounding box.south -| between2);

\end{tikzpicture}
person grddev    schedule 08.08.2010
comment
В чем разница между командами \ path и \ draw (app1 - stack) и (ohci) - (stack); Я вижу, что изменение \ path на \ draw приводит к «двойной линии». Просто чтобы получить координаты для использования позже? - person Freddie Witherden; 08.08.2010
comment
@Freddie: Команда \path просто создает путь. Команда \draw также создает путь, но дополнительно рисует путь. Команда \path предназначена только для получения координаты, а команда \draw выполняет сразу две вещи. Это взлом. Очень хотелось собрать все в одно дерево, но это не удалось. Так и должно быть, но если я попытаюсь вырастить два узла слева и один справа, левые узлы будут расположены так, как если бы слева было три узла. - person grddev; 09.08.2010