
TL;DR Zusammenfassung:
Gibt es eine Möglichkeit, die Breite eines Blattknotens zu messen und diese Messung an den Baum zurückzugeben, damit sie in der Einstellung verwendet werden kann sibling distance
? (Vielleicht möchte man etwas Ähnliches level distance
auch für tun.)
Beispiel:
Angenommen, ich habe einen einfachen Baum, bei dem die Blattknoten jeweils dasselbe Bild enthalten:
\documentclass{standalone}
\usepackage{tikz}
\pgfdeclareimage{image}{fptp-ballot}
\begin{document}
\begin{tikzpicture}
\node {root} [level/.append style={level distance=4cm}]
child foreach \c in {1,2} {
node [fill=red!10] {\pgfuseimage{image}}};
\end{tikzpicture}
\end{document}
Bei der Standardeinstellung für sibling distance
überlappen sich die Blätter:
Eine Möglichkeit, die Breite des Blattes zu messen, besteht darin, ein unsichtbares temporäres Blatt zu erstellen tmp
und let
seine Breite mit der Operation für Pfade zu berechnen:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\pgfdeclareimage{image}{fptp-ballot}
\begin{document}
\begin{tikzpicture}
\node (tmp) [fill=red!10, transparent, overlay] {\pgfuseimage{image}};
\path let \p{leafwidth} = ($(tmp.east)-(tmp.west)$) in
node {root} [level/.append style={level distance=4cm, sibling distance=\x{leafwidth}}]
child foreach \c in {1,2} {
node [fill=red!10] {\pgfuseimage{image}}};
\end{tikzpicture}
\end{document}
Das Problem bei diesem Ansatz ist: Es erscheint umständlich, ein temporäres Blatt erstellen zu müssen, tmp
wenn die Blätter, die ich wirklich messen möchte, bereits später im Code vorhanden sind. Dadurch wird die Modularität eingeschränkt. Wenn ich die Blätter ändere, muss ich den Knoten entsprechend ändern tmp
(oder den Blattcode mit einem Makro und Stil ausklammern).
Mit anderen Worten, ich hätte gerne eine Lösung, die funktioniertörtlichunabhängig davon, was ich in die Blätter lege – ein einzelnes Bild, eine Matrix mit beliebigem Zellinhalt usw.
Frage:
Gibt es eine Möglichkeit, die Breite einestatsächlichBlattknoten und geben Sie diese Messung zurück an den Baum weiter, um sie in der Einstellung zu verwenden sibling distance
?
Ich würde gerne etwa Folgendes schreiben:
\begin{tikzpicture}
\node {root} [level/.append style={level distance=4cm, sibling distance=\x{leaf1width}}]
child foreach \c in {1,2} {
node (leaf\c)
[fill=red!10] {\pgfuseimage{image}}
let \p{leaf\c width} = ($(leaf\c.east)-(leaf\c.west)$) in};
\end{tikzpicture}
Hier messe ich direkt die Breiten dertatsächlichBlätter und versuche, dies zu verwenden, um sibling distance
den Stammknoten festzulegen. Leider führt dies zu dem Fehler „Undefinierte Steuersequenz. <argument> \x{leaf1width}
“, vermutlich weil \p{leaf\c width}
erst definiert wird, wenn die Blätter erreicht sind. Gibt es eine Möglichkeit, diesen Code zu beheben?
Ich dachte daran, den late options
Schlüssel zu benutzen, aber derTikZ-Handbuchbesagt, dass
Ein bereits vorhandener Knoten wird ermittelt [...] und dann werden die Optionen in einem lokalen Bereich ausgeführt. Die meisten dieser Optionen haben keine Auswirkung, da SieDas Aussehen des Knotens kann nicht geändert werden, das heißt, Sie können einen roten Knoten nicht mithilfe von späten Optionen in einen grünen Knoten ändern.
Tatsächlich wird das Folgende ohne Fehler kompiliert, sibling distance
ist aber nicht betroffen.
\begin{tikzpicture}
\node (root) {root} [level/.append style={level distance=4cm}]
child foreach \c in {1,2} {
node (leaf\c)
[fill=red!10] {\pgfuseimage{image}}
let \p{leaf\c width} = ($(leaf\c.east)-(leaf\c.west)$) in
(root) [late options={level/.append style={sibling distance=\x{leaf1width}}}]};
\end{tikzpicture}
Antwort1
Wie in den Kommentaren verlinkt, ist es sehr einfach, die Größe des Bildes zu messen, wenn Sie Ihre Bilder zuerst in eine Box legen. Ich bin nicht sicher, ob ich die Komplikation verstehe, aber wenn Sie nur wenige Bilder haben, die in den Baum passen, können Sie das Maximum dieser Messungen aus der max(x,y)
Mathematikbibliothek entnehmen. Hier habe ich die Makros reduziert und Yiannis‘ Lösung ohne jegliche Automatisierung verwendet.
\documentclass{standalone}
\usepackage{tikz}
\newsavebox{\Image}
\savebox{\Image}{\includegraphics[scale=0.05]{DSOTM}}
\newlength{\imageh}
\newlength{\imagew}
\settoheight{\imageh}{\usebox{\Image}}
\settowidth{\imagew}{\usebox{\Image}}
\begin{document}
\begin{tikzpicture}
\node {root} [level/.append style={
level distance=1.5\imageh, sibling distance=1.1\imagew
}
]
child foreach \c in {1,2} {
node [fill=red!10,inner sep=1pt] {\includegraphics[scale=0.05]{DSOTM}}};
\end{tikzpicture}
\end{document}