
Краткое содержание:
Есть ли способ измерить ширину листового узла и передать это измерение обратно вверх по дереву для использования в настройке sibling distance
? (Возможно, кто-то захочет сделать то же самое level distance
.)
Пример:
Предположим, что у меня есть простое дерево, в котором все конечные узлы содержат одно и то же изображение:
\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}
При настройке по умолчанию sibling distance
листья перекрываются:
Один из способов измерения ширины листа — создать невидимый временный лист tmp
и использовать let
операцию для путей для вычисления его ширины:
\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}
Проблема с этим подходом заключается в следующем: кажется неуклюжим необходимость создания временного листа, tmp
когда листья, которые я действительно хочу измерить, уже существуют позже в коде. Это делает вещи менее модульными. Если я изменяю листья, то мне нужно изменить узел tmp
соответствующим образом (или вынести код листа с помощью макроса и стиля).
Другими словами, я хотел бы найти решение, которое работает.локальнонезависимо от того, что я помещаю внутрь листьев — отдельное изображение, матрицу с произвольным содержимым ячеек и т. д.
Вопрос:
Есть ли способ напрямую измерить ширинудействительныйконечный узел и передать это измерение обратно вверх по дереву для использования в настройке sibling distance
?
Я хотел бы написать что-то вроде следующего:
\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}
Здесь я непосредственно измеряю ширинудействительныйleaves и пытаюсь использовать это для установки sibling distance
в корневом узле. К сожалению, это дает ошибку "Undefined control sequence. <argument> \x{leaf1width}
", предположительно потому, \p{leaf\c width}
что не определено, пока не достигнуты листья. Есть ли способ исправить этот код?
Я думал использовать late options
ключ, ноРуководство пользователя TikZговорится, что
Уже существующий узел определяется [...] и затем опции выполняются в локальной области. Большинство этих опций не будут иметь никакого эффекта, так как выневозможно изменить внешний вид узла, то есть вы не можете превратить красный узел в зеленый узел, используя поздние опции.
Действительно, следующий код компилируется без ошибок, но это sibling distance
не влияет на .
\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}
решение1
Как указано в комментариях, помещение изображений в поле сперва значительно упрощает измерение размера изображения. Я не уверен, что понимаю сложность, но если у вас мало изображений, которые можно поместить в дерево, то вы можете взять максимум этих измерений из max(x,y)
математической библиотеки. Здесь я убрал макросы и использовал решение Янниса без какой-либо автоматизации.
\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}