Назовите TikZ Pics (\pic) как будто это узел

Назовите TikZ Pics (\pic) как будто это узел

Я запутался в картинках 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:

  1. В отличие от узлов, на картинки нельзя ссылаться позже. Вы можете ссылаться на узлы, которые находятся внутри картинки, но не на «саму картинку». В частности, вы не можете рисовать линии между картинками так же, как вы рисуете их между узлами. В общем, когда имеет смысл, что какой-то рисунок может быть предположительно связан с другими вещами, подобными узлам, то узел лучше, чем картинка.

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

Итак, если вы делаете что-то, что узел делает хорошо, и нет особой причины использовать 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 (по диагонали справа вверху).

Конечно, вы по-прежнему можете рисовать ребра от одного узла к другому.

Выход

Рисунок 1

Код

\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);

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