Команда стекирования/группирования, определенная tikz-изображениями

Команда стекирования/группирования, определенная tikz-изображениями

Я работаю над пакетом, который широко использует команды, необходимые pgfkeysдля создания tikz-картинки. Ниже приведен простой пример:

\documentclass[tikz,border=5pt]{standalone}
\makeatletter
\usetikzlibrary{shapes.geometric, calc}
\newcommand{\example}[2][]{
\tikzset{
 /Example/.cd,
 caption/.store in=\Example@caption,
 caption=X,
 #1,
}
\draw [local bounding box=M] rectangle (1,1);
\node at (0.5,0.5) {\Example@caption};
}
\makeatother
\begin{document}
\begin{tikzpicture}
\example[caption=A];
\end{tikzpicture}
\end{document}

Как и ожидалось, это дает следующий результат:

вывод макроса

(Помните, что это пример, сделанный для упрощения, и он не отражает сложность реальных команд, которые содержат гораздо больше клавиш, выполняющих более сложные действия).

Я хочу создать два новых окружения списков, в которые я могу добавлять одну из команд несколько раз с разными значениями ключей. Полученные изображения затем «группируются» с помощью нарисованной скобки tikz или «складываются» с помощью линии, идущей вниз от юго-западного угла определенного локального ограничивающего прямоугольника в пределах команды на определенную длину, чтобы она соединялась со следующим изображением, если оно есть (все будут иметь одинаковый интервал, и каждое изображение будет иметь одинаковый общий размер):

стек и группа

В идеале мне нужна структура среды списка, подобная этой:

\begin{examplestack}
    \item \example[caption=A] 
    \item \example[caption=B] 
    \item \example[caption=C] 
\end{examplestack}

\begin{examplegroup}
    \item \example[caption=A] 
    \item \example[caption=B] 
    \item \example[caption=C] 
\end{examplegroup}

И стек, и группа должны иметь смещение начала координат в пределах tikzpictureхолста, группа на кончике скобки, стек внизу последней линии (внизу «флагштока»). Это необходимо для того, чтобы их можно было правильно разместить при наложении на другой слой (например, карту).

решение1

Доказательство концепции. Кажется, работает, по крайней мере, для этого простого случая. Длины нужно будет подкорректировать здесь и там, например, вертикальное смещение каждого элемента просто жестко закодировано на 1,2 см. В целом, это не очень гибкий подход, я уверен, что есть и другие, которые могли бы сделать лучше.

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

\documentclass[tikz,border=5pt]{standalone}
\makeatletter
\usetikzlibrary{shapes.geometric, calc}
\newcommand{\example}[2][]{
\tikzset{
 /Example/.cd,
 caption/.store in=\Example@caption,
 caption=X,
 #1,
}
\draw [local bounding box=M] rectangle (1,1);
\node at (0.5,0.5) {\Example@caption};
}
\makeatother

\newcounter{exitem}

\newenvironment{examplestack}{
\setcounter{exitem}{0}
\renewcommand\item{
% if you only want to draw a line between items
%\ifnum \value{exitem}>0
%  \draw ([xshift=0.5\pgflinewidth]current bounding box.south west) -- ++(0,-0.2cm);
%\fi
%
% if you also want the line below the last item -- not very elegant
\draw (0,{-(1.2cm+\theexitem*1.2cm)}) -- ++(0,-2mm);
%
\stepcounter{exitem}\scoped[yshift=-\theexitem*1.2cm]}
\tikzpicture
}{
%\draw (current bounding box.north west) -- ([yshift=-3pt]current bounding box.south west);
\node [above right] at (current bounding box.north west) {``Stack''};
\endtikzpicture
}

\newenvironment{examplegroup}{
\setcounter{exitem}{0}
\renewcommand\item{\stepcounter{exitem}\scoped[yshift=-\theexitem*1.2cm]}
\tikzpicture
}{
\draw ([shift={(5pt,3pt)}]current bounding box.north west) -| ([shift={(-3pt,-3pt)}]current bounding box.south west) -- ++(8pt,0)
 (current bounding box.west) -- ++(-5pt,0);

\node [above right] at (current bounding box.north west) {``Group''};
\endtikzpicture
}


\begin{document}
\begin{examplegroup}
\item\example[caption=A];
\item\example[caption=B];
\item\example[caption=C];
\end{examplegroup}

\begin{examplestack}
\item\example[caption=A];
\item\example[caption=B];
\item\example[caption=C];
\end{examplestack}
\end{document}

решение2

Я чувствую, что должен добавить ответ на это, так как мне удалось придумать лучшее и более гибкое решение, чем ответ Торбьёрна Т. на эту проблему. Их решение не позволяло картинкам разной высоты иметь одинаковый интервал между ними. С помощью макроса длины я смог сохранить длину предыдущей картинки и использовать ее для смещения следующей, а с помощью набора координат я смог объединить их в «Стек».

Важная заметка: \itemбыл переопределен для приема одного аргумента, поэтому в средах следует использовать \item{<picture>}вместо \item <picture>.

Это решение использует xparseболее чистый синтаксис команд и окружения, но можно было бы с таким же успехом использовать и простое решение LaTeX.

Преамбула (плюс остальное из MWE):

\newcounter{exitem}
\newlength{\itemlength}

Синтаксис «Стек»:

\NewDocumentEnvironment{examplestack}{}{
\setlength{\itemlength}{0}
\begin{scope}
\setcounter{exitem}{0}
\RenewDocumentCommand\item{m}{
\scoped[yshift=-\itemlength, local bounding box=T]
##1;
\ifnum \value{exitem}>0
\pgfmathtruncatemacro\result{\value{exitem}-1}
\draw ($(M.south west) + (0, -0.25)$) -- (F\result);
\fi
\coordinate (F\arabic{exitem}) at (M.north west);
\pgfpointdiff{\pgfpointanchor{T}{north west}}{\pgfpointanchor{T}{south west}}
\addtolength{\itemlength}{\pgf@y-5pt} % 5pt is the spacing between pictures.
\stepcounter{exitem}}
}{\end{scope}}

Синтаксис «Группа»:

\NewDocumentEnvironment{examplegroup}{}{
\setlength{\itemlength}{0}
\begin{scope}[local bounding box=G]
\RenewDocumentCommand\item{m}{
\scoped[yshift=-\itemlength, local bounding box=T]
##1;
\pgfpointdiff{\pgfpointanchor{T}{north west}}{\pgfpointanchor{T}{south west}}
\addtolength{\itemlength}{\pgf@y-5pt}} % 5pt is the spacing between pictures.
}{
\draw ([shift={(5pt,3pt)}]G.north west) -| ([shift={(-3pt,-3pt)}]G.south west) -- ++(8pt,0)
 (G.west) -- ++(-5pt,0);
\end{scope}}

Примеры:

\begin{examplegroup}
\item{\example[caption=A]}
\item{\example[caption=B]}
\item{\example[caption=C]}
\end{examplegroup}

\begin{examplestack}
\item{\example[caption=A]}
\item{\example[caption=B]}
\item{\example[caption=C]}
\end{examplestack}

Связанный контент