%20%D0%BA%D0%B0%D0%BA%20%D0%B1%D1%83%D0%B4%D1%82%D0%BE%20%D1%8D%D1%82%D0%BE%20%D1%83%D0%B7%D0%B5%D0%BB.png)
Я запутался в картинках tikz. Я могу свободно определять их без проблем и даже добавлять координаты внутри, которые будут доступны по наследованию имени, как, (-A)
например, в \pic (S) at (0,0) {myPic}; \draw (S-A) -- ++(0,0);
. Все это задокументировано на стр. 255 руководства pgf.
Однако я не понимаю, почему нельзя дать имя картинке, как выше, если внутри нее не определены координаты. По умолчанию было бы здорово, если бы она могла вести себя как обычный узел.
МВЭ:
\documentclass{minimal}
\usepackage{tikz}
\tikzset{
myBlock/.pic = {
\node[draw,minimum width=1cm,minimum height=0.5cm] at (0,0) {};
},
myBlockNamed/.pic = {
\node[draw,minimum height=1cm,minimum width=0.5cm] (-m) at (0,0) {};
},
}
\begin{document}
\begin{tikzpicture}
\pic () at (0,0) {myBock}; % can't give it a name
\pic (S) at (3,0) {myBlockNamed}; % can give it a name
\draw (S-A) -- ++(2,0);
\end{tikzpicture}
\end{document}
Суть в том, что я работаю над библиотекой блоков управления (чтобы мы могли прекратить чат ниже с @Alenanno). Например, вот определение математического оператора
\tikzset{
mySum background/.style = {
circle, minimum size=1.5em, fill=white,
},
mySum edge/.style = {
draw=black, circle, minimum size=1.5em, line width=.5pt,
},
pics/bOp/.style = {
code = {
\node [mySum background] {};
\foreach \t [count=\i] in {#1}{
\pgfmathsetmacro{\angle}{\i*90}
\node[anchor=center, font=\tiny] at (\angle:0.45em) {$\t$};
}
\node [mySum edge] {};
},
},
}
решение1
Есть трюк, который можно использовать в некоторых обстоятельствах, который использует тот факт, что a pic
помещается внутрь a scope
, который может быть назван с помощью local bounding box
ключа. Обратите внимание, что это не будет работать в деревьях или графах.
\documentclass[tikz,border=5]{standalone}
\tikzset{pics/.cd,
pic a/.style={code={
\node [fill=red!20, shape=circle] {A};
}}
}
\begin{document}
\begin{tikzpicture}
\pic [local bounding box=A1] at (0,0) {pic a};
\pic [local bounding box=A2] at (3,0) {pic a};
\foreach \i in {0,15,...,345}{
\draw [red, ->] (\i:1) -- (A1);
\draw [blue, ->] (3,0)++(\i:1) -- (A2);
}
\end{tikzpicture}
\end{document}
Также можно использовать имя, присвоенное , pic
определив ключ «обертки», который явно добавляет область действия к коду:
\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{fit}%
\makeatletter
\tikzset{pics/named scope code/.style={code={\tikz@fig@mustbenamed%
\begin{scope}[local bounding box/.expanded=\tikz@fig@name]#1\end{scope}%
}}}
\makeatother
\tikzset{pics/.cd,
pic a/.style={named scope code={
\node [fill=red!20, shape=circle] {A};
}}
}
\begin{document}
\begin{tikzpicture}
\pic (A1) at (0,0) {pic a};
\pic (A2) at (3,0) {pic a};
\foreach \i in {0,15,...,345}{
\draw [red, ->] (\i:1) -- (A1);
\draw [blue, ->] (3,0)++(\i:1) -- (A2);
}
\end{tikzpicture}
\end{document}
Результат тот же, что и прежде.
решение2
ИзРуководство Pgf (версия 3.0.0), страница 252:
В отличие от узлов, на картинки нельзя ссылаться позже. Вы можете ссылаться на узлы, которые находятся внутри картинки, но не на «саму картинку». В частности, вы не можете рисовать линии между картинками так же, как вы рисуете их между узлами. В общем, когда имеет смысл, что какой-то рисунок может быть предположительно связан с другими вещами, подобными узлам, то узел лучше, чем картинка.
Если использовать пики для эмуляции полной мощности узла (что в принципе возможно), они будут создаваться медленнее и занимать больше памяти, чем узел, достигающий того же эффекта.
Итак, если вы делаете что-то, что узел делает хорошо, и нет особой причины использовать pic
, вам лучше использовать узел. Обходной путь есть в ответе на вопрос "Как дать имя \pic", но это именно так, обходной путь.
Однако, если вы хотите иметь возможность размещать узлы вокруг другого узла, вы можете проверить этот вопрос, который я задал некоторое время назад (Как расположить узлы вокруг другого узла в TiKZ?) или вы используете Tikz foreach с обычным узлом.
Обновленный ответ
Теперь, когда я знаю, что вам нужно, вот решение с Tikz. Новая команда \mySumn
(вы можете переименовать ее) принимает два аргумента, например \mySumn{#1}{#2}
, , где #1
— имя узла, а #2
— позиция.
Я пытался добавить необязательный аргумент с помощью , above of
но не получилось. Однако вы можете сделать то же самое с этим кодом, но другим способом. Рассмотрим следующее:
\mySumn{p1}{0,0};
\mySumn{p2}{$(p1.north east)+(1em,1em)$};
Он поместит узел p1
в точке с координатами (0,0)
, а затем поместит еще один узел p2
в точке p1 на северо-востоке +1em по осям x и y (по диагонали справа вверху).
Конечно, вы по-прежнему можете рисовать ребра от одного узла к другому.
Выход
Код
\documentclass[margin=10pt]{standalone}
\usepackage{tikz}
\usepackage{xparse}
\usetikzlibrary{calc,arrows.meta,positioning}
\tikzset{
mySumbk/.style = {
draw, circle, minimum size=1.5em, fill=white,
},
}
\newcommand{\mySumn}[2]{
\node[mySumbk,fill=white] (#1) at (#2) {};
\foreach \angle/\maop in {
90/+,
180/-
}{
\node[anchor=center, font=\tiny] at ($(#1)+(\angle:.45em)$) {$\maop$};
}}
\begin{document}
\begin{tikzpicture}[>=latex]
\mySumn{p1}{0,0};
\mySumn{p2}{$(p1.north east)+(1em,1em)$};
\draw (p1) -- (3,0);
\draw (p1) edge[out=90,in=180] (p2);
\end{tikzpicture}
\end{document}
решение3
Старый вопрос, но я не был доволен решением, local bounding box
так как не смог найти способ лучше его контролировать (например, расстояние до внутреннего содержания).
Моим решением было использовать вложенную картинку в pic
, вместе с remember picture
опцией. Имена передаются в качестве аргументов каскадным образом. При этом вы можете не только ссылаться на pic
как на узел (потому что на самом деле это узел), но и ссылаться на его содержимое.
Еще один момент заключается в том, что при таком решении содержимое a pic
всегда централизовано, что также было тем, чего я искал при работе над этим кодом.
Имейте в виду:
- вам придется компилировать документ дважды из-за
remember picture
. - Вложенные узлы могут быть сложны из-за наследования.
Вот код:
\documentclass[tikz]{standalone}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}[remember picture]
\tikzset{
mine/.pic={
\node[draw](#1){
\begin{tikzpicture}[remember picture]
\node[draw](#1-1){#1-1};
\node[draw, right=of #1-1](#1-2){#1-2};
\end{tikzpicture}
};
},
}
\pic{mine=a};
\pic[right=of a]{mine=b};
\draw[thick, blue, <->](a-1)to[out=90, in=90](b-1);
\draw[thick, blue, <->](a-2)to[out=-90, in=-90](b-2);
\draw[thick, red](a)to(b);
\end{tikzpicture}
\end{document}
решение4
Похоже, что если я определю команду для своего оператора:
\tikzset{
mySum background/.style = {
circle, minimum size=1.5em, fill=white,
},
mySum edge/.style = {
draw=black, circle, minimum size=1.5em, line width=.5pt,
},
}
\newcommand{\bOp}[1]{
\tikz[outer sep=0pt]{
\node [mySum background] {};
\foreach \t [count=\i] in {#1}{
\pgfmathsetmacro{\angle}{\i*90}
\node[anchor=center, font=\tiny] at (\angle:0.45em) {$\t$};
}
\node [mySum edge] {};
}
}
Затем можно создать узел, содержащий поддельную картинку, поскольку то, что указано выше, — это именно то, что можно использовать для определения картинки.
\node (1) at (0,0) {\bOp{+,-,,}};
\draw (4,0) -- (1);