Расчеты соединительной линии с помощью подгоночного узла в 3D tikz?

Расчеты соединительной линии с помощью подгоночного узла в 3D tikz?

Рассмотрим следующий MWE:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{positioning}
\usetikzlibrary{fit}
\usetikzlibrary{3d}

\makeatletter
\tikzset{
  fitting node/.style={
    inner sep=0pt,
    fill=none,
    draw=none,
    reset transform,
    fit={(\pgf@pathminx,\pgf@pathminy) (\pgf@pathmaxx,\pgf@pathmaxy)}
  },
  reset transform/.code={\pgftransformreset},
}
\makeatother
\tikzstyle{dr} = [draw, rectangle, line width=1pt, font=\Huge, align=left]
\tikzstyle{cl} = [>=latex,->,line width=1pt]

\begin{document}
\begin{tikzpicture}[
%   x={(0.5cm,0.5cm)}, y={(1cm,0cm)}, z={(0cm,1cm)},
%   every node/.append style={transform shape},
]

\draw[very thick] (0,0) rectangle (18,8) node[fitting node] (starter) {};

\begin{scope}[
  shift={(1,1)},
%   canvas is yx plane at z=0.25,
]
\node[dr] (NodeA) at (1,5) {Node A};
\draw[dr] (4.5,2.5) rectangle (11,6.5) node [fitting node] (NodeB) {Node B\\Slightly bigger};
\node[dr] (NodeC) [above=10pt of NodeB.south, anchor=south] {Node C};

\draw[cl] (NodeA) -- (NodeB);
\draw[cl] (NodeA) |- ($(NodeB.north west)-(10pt,10pt)$) -- ($(NodeB.south west)-(10pt,7.5pt)$) -| ($(NodeC.south west)+(10pt,0)$);

\end{scope}
\end{tikzpicture}
\end{document}

Если я скомпилирую его как есть, то получу ожидаемое расположение узлов и соединительных линий:

test41.png

Но если я включу 3D, раскомментировав закомментированные строки в MWE, я получу следующее:

test42.png

То, что текст NodeB не находится в перспективе, меня не сильно беспокоит; меня беспокоит то, что координаты, основанные на прямоугольнике, подходящем к узлу NodeB, не работают должным образом при 3D-преобразованиях (обратите внимание, что между «правильными» узлами все в порядке, например, между частью линии, идущей прямо в NodeC).

(Я знаю, что этот пример, в частности, можно было бы сделать без прямоугольника подгоночного узла — и тогда проблема будет решена; дело в том, что они весьма полезны для редактирования графического интерфейса в TikzEdt, и поэтому у меня есть код с кучей таких повсюду; поэтому я бы предпочел иметь решение вроде исправления стиля «подгоночного узла».)

решение1

Я не знаю, где проблема, может быть, transform shapeэто не применяется к fitузлам. Вот вам обходной путь, если никто не предоставит лучшее решение.

Использовать label={center:{node text}}как вариант для fittingузлов:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{positioning}
\usetikzlibrary{fit}
\usetikzlibrary{3d}

\makeatletter
\tikzset{
  fitting node/.style={
    inner sep=0pt,
    fill=none,
    draw=none,
    reset transform,
    fit={(\pgf@pathminx,\pgf@pathminy) (\pgf@pathmaxx,\pgf@pathmaxy)}
  },
  reset transform/.code={\pgftransformreset},
}
\makeatother
\tikzstyle{dr} = [draw, rectangle, line width=1pt, font=\Huge, align=left]
\tikzstyle{cl} = [>=latex,->,line width=1pt]

\begin{document}
\begin{tikzpicture}[
   x={(0.5cm,0.5cm)}, y={(1cm,0cm)}, z={(0cm,1cm)},
   every node/.append style={transform shape},
]

\draw[very thick] (0,0) rectangle (18,8) node[fitting node] (starter) {};

\begin{scope}[
  shift={(1,1)},
   canvas is yx plane at z=0.25,
]
\node[dr] (NodeA) at (1,5) {Node A};
\draw[dr] (4.5,2.5) rectangle (11,6.5) node [fitting node, label={center:{Node B\\Slightly bigger}}] (NodeB) {};
\node[dr] (NodeC) [above=10pt of NodeB.south, anchor=south] {Node C};

\draw[cl] (NodeA) -- (NodeB);
\draw[cl] (NodeA) |- ($(NodeB.north west)-(10pt,10pt)$) -- ($(NodeB.south west)-(10pt,7.5pt)$) -| ($(NodeC.south west)+(10pt,0)$);

\end{scope}
\end{tikzpicture}
\end{document}

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

решение2

EDIT: Обратите внимание, что этот ответ был сломан в Texlive 2014 из-за зависания:

Ладно, я думаю, я понял, но пока не совсем понимаю, почему.

Во-первых, проблема в том, что он fitделает ровно то, что ему говорят — мы говорим ему подгонять последние PGF min и max x и y, и он делает ровно это (можно увидеть, изменив на draw=redof fitting node):

test43.png

Проблема, по-видимому, в том, что прямоугольник уже преобразован к моменту достижения fit, но еще fitне знает о трехмерном преобразовании.

Поэтому я пытался остановить преобразование, затем выполнить подгонку прямоугольника, а затем восстановить преобразование — не сработало; пытался найти способ сгруппировать команды рисования pgf, а затем применить преобразование ко всем ним — не смог найти.

Потом я нашел#47797 Как установить точки, подобные якорям узлов, на прямоугольном пути (tikz) (есть ли метод лучше описанного)?, и использовал это так, чтобы координатные якоря добавлялись к прямоугольнику - и среди прочего, пытался fitс якорями прямоугольника... И вдруг это работает?? И я не вижу, как это может нарушить преобразование координат, как это было в моей теории для проблемы выше??

Тем не менее, на данный момент результат таков:

test44.png

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

\usetikzlibrary{calc}
\usetikzlibrary{positioning}
\usetikzlibrary{fit}
\usetikzlibrary{3d}

\makeatletter
%https://tex.stackexchange.com/a/47797/2595
\tikzset{add reference/.style={insert path={%
    coordinate [pos=0,xshift=-0.5\pgflinewidth,yshift=-0.5\pgflinewidth] (#1 south west)
    coordinate [pos=1,xshift=0.5\pgflinewidth,yshift=0.5\pgflinewidth]   (#1 north east)
    coordinate [pos=.5] (#1 center)
    (#1 south west |- #1 north east)     coordinate (#1 north west)
    (#1 center     |- #1 north east)     coordinate (#1 north)
    (#1 center     |- #1 south west)     coordinate (#1 south)
    (#1 south west -| #1 north east)     coordinate (#1 south east)
    (#1 center     -| #1 south west)     coordinate (#1 west)
    (#1 center     -| #1 north east)     coordinate (#1 east)
}}}
\tikzset{
  fitting node/.style={
    inner sep=0pt,
    fill=none,
    draw=red,
    fit={(#1 south west) (#1 north east)},
  },
}
\makeatother
\tikzstyle{dr} = [draw, rectangle, line width=1pt, font=\Huge, align=left]
\tikzstyle{cl} = [>=latex,->,line width=1pt]


\begin{tikzpicture}[
  x={(0.5cm,0.5cm)}, y={(1cm,0cm)}, z={(0cm,1cm)},
  every node/.append style={transform shape},
]

\draw[very thick] (0,0) rectangle (18,8) [add reference=R1] node[fitting node=R1] (starter) {};

\begin{scope}[
  shift={(1,1)},
  canvas is yx plane at z=0.25,
]
\node[dr] (NodeA) at (1,5) {Node A};

\draw[dr] (4.5,2.5) rectangle (11,6.5) [add reference=R2] node [fitting node=R2] (NodeB) {Node B\\Slightly bigger};

\node[dr] (NodeC) [above=10pt of NodeB.south, anchor=south] {Node C};

\draw[cl] (NodeA) -- (NodeB);
\draw[cl] (NodeA) |- ($(NodeB.north west)-(10pt,10pt)$) -- ($(NodeB.south west)-(10pt,7.5pt)$) -| ($(NodeC.south west)+(10pt,0)$);

\end{scope}
\end{tikzpicture}

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