문맥:이 질문은 다음 질문에 대한 후속 질문입니다.중첩된 요소로 TikZ 그림을 만드는 모범 사례.기호 1제공답변이 질문에 대해서는 어디에 \scopenode
정의되어 있습니까?
\scopenode
범위는 노드로 전환됩니다. 즉, 다음을 수행할 수 있습니다. 범위 이름을 name=foo
; 범위를 다음으로 배치합니다 at=(somewhere)
. 로 위치를 조정합니다 anchor=something
. 중첩될 수 있기 때문에 기본적으로 훌륭합니다.
그런 다음tikzexternalize 및 savebox를 호환 가능하게 사용하는 방법은 무엇입니까?,CFR제공답변의 배경과 내용을 \scopenode
모두 표시할 수 있도록 하여 이러한 기능을 개선합니다 . (스코프노드 배경은 실제로 그려질 것입니다.\scopenode
\scopenode
~ 위에내용은 그렇지 않습니다.)
문제:\scopenode
Ti에 포함시키려고 했는데케이지 matrix
. 그러나 몇 가지 문제가 있습니다.
질문:\scopenode
Ti와 호환되게 만드는 방법케이Z matrix
?
MWE
(예제에서는 다음을 사용하여 행렬을 만듭니다.하나행과 두 개의 열. 두 셀(A1 및 B1) 모두 스코프노프가 채워져 그려져 있습니다. A(빨간색-주황색)는 남쪽에 고정되어 있고 B(황록색)는 북쪽에 고정되어 있습니다. 각 범위 노드에서 경로는 (0,0)에서 (1,1))로 그려집니다.
_______
| A | |
|---|---| <-- baseline
|___|_B_|
기호 1의 솔루션을 사용하면 다음과 같습니다.
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usetikzlibrary{backgrounds}
% \usetikzlibrary{external}
% \tikzexternalize
% \tikzset{external/prefix=build/}
\makeatletter
\newbox\tikz@sand@box
\newcount\tikz@scope@depth
\tikz@scope@depth111\relax
\def\scopenode[#1]#2{%
\begin{pgfinterruptboundingbox}%
\advance\tikz@scope@depth111\relax%
% process the user option
\begin{scope}[name=tempscopenodename,at={(0,0)},anchor=center,#1]%
% try to extract positioning information: name, at, anchor
\global\let\tikz@fig@name\tikz@fig@name%
\global\let\tikz@node@at\tikz@node@at%
\global\let\tikz@anchor\tikz@anchor%
\end{scope}%
\let\tikz@scopenode@name\tikz@fig@name%
\let\tikz@scopenode@at\tikz@node@at%
\let\tikz@scopenode@anchor\tikz@anchor%
% try to typeset this scope
% we only need bounding box information
% the box itself will be discard
\setbox\tikz@sand@box=\hbox{%
\begin{scope}[local bounding box=tikz@sand@box\the\tikz@scope@depth,#1]%
#2%
\end{scope}%
}%
% goodbye. haha
\setbox\tikz@sand@box=\hbox{}%
% now typeset again
\begin{scope}[local bounding box=\tikz@scopenode@name]%
% use the bounding box information to reposition the scope
\pgftransformshift{\pgfpointanchor{tikz@sand@box\the\tikz@scope@depth}{\tikz@scopenode@anchor}%
\pgf@x-\pgf@x\pgf@y-\pgf@y}%
\pgftransformshift{\tikz@scopenode@at}%
\begin{scope}[#1]%
#2
\end{scope}%
\end{scope}%
\pgfkeys{/pgf/freeze local bounding box=\tikz@scopenode@name}%
\global\let\tikz@scopenode@name@smuggle\tikz@scopenode@name%
\end{pgfinterruptboundingbox}%
% make up the bounding box
\path(\tikz@scopenode@[email protected] west)(\tikz@scopenode@[email protected] east);%
% draw something, not necessary
\draw[#1](\tikz@scopenode@[email protected] west)rectangle(\tikz@scopenode@[email protected] east);%
}
\makeatother
\begin{document}
\begin{tikzpicture}[
remember picture,
inner sep=0pt,
outer sep=0pt,
]
\draw [help lines](-2,-2) grid (2,2);
\matrix[
column sep=2em,
row sep = 1em,
nodes in empty cells,
anchor=center,
nodes={anchor=center},
]
{
\scopenode[draw = red, fill = orange, anchor=south] {
\draw [blue] (0,0) -- (1,1);
};
&
\scopenode[draw = yellow, fill = green, anchor=north] {
\draw [black] (0,1) -- (1,0);
};
\\
};
\end{tikzpicture}
\end{document}
cfr의 솔루션을 사용하면 다음과 같습니다.
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usetikzlibrary{backgrounds}
% \usetikzlibrary{external}
% \tikzexternalize
% \tikzset{external/prefix=build/}
\makeatletter
\pgfdeclarelayer{scopenode}
\pgfsetlayers{background,scopenode,main}
\tikzset{%
% adapted from tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarybackgrounds.code.tex
on scopenode layer/.style={%
execute at begin scope={%
\pgfonlayer{scopenode}%
\let\tikz@options=\pgfutil@empty%
\tikzset{every on scopenode layer/.try,#1}%
\tikz@options%
},
execute at end scope={\endpgfonlayer}
},
}
% ateb Symbol 1: tex.stackexchange.com/a/…
\newbox\tikz@sand@box
\newcount\tikz@scope@depth
\tikz@scope@depth111\relax
\def\scopenode[#1]#2{% name=<enw>, at=<man>, anchor=<angor>
\begin{pgfinterruptboundingbox}%
\advance\tikz@scope@depth111\relax%
% process the user option
\begin{scope}[name=tempscopenodename,at={(0,0)},anchor=center,#1]%
% try to extract positioning information: name, at, anchor
\global\let\tikz@fig@name\tikz@fig@name%
\global\let\tikz@node@at\tikz@node@at%
\global\let\tikz@anchor\tikz@anchor%
\end{scope}%
\let\tikz@scopenode@name\tikz@fig@name%
\let\tikz@scopenode@at\tikz@node@at%
\let\tikz@scopenode@anchor\tikz@anchor%
% try to typeset this scope
% we only need bounding box information
% the box itself will be discard
\setbox\tikz@sand@box=\hbox{%
\begin{scope}[local bounding box=tikz@sand@box\the\tikz@scope@depth,#1]%
#2%
\end{scope}%
}%
% goodbye. haha
\setbox\tikz@sand@box=\hbox{}%
% now typeset again
\begin{scope}[local bounding box=\tikz@scopenode@name]%
% use the bounding box information to reposition the scope
\pgftransformshift{\pgfpointanchor{tikz@sand@box\the\tikz@scope@depth}{\tikz@scopenode@anchor}%
\pgf@x-\pgf@x\pgf@y-\pgf@y}%
\pgftransformshift{\tikz@scopenode@at}%
\begin{scope}[#1]%
#2
\end{scope}%
\end{scope}%
\pgfkeys{/pgf/freeze local bounding box=\tikz@scopenode@name}%
\global\let\tikz@scopenode@name@smuggle\tikz@scopenode@name%
\end{pgfinterruptboundingbox}%
% make up the bounding box
\path(\tikz@scopenode@[email protected] west)(\tikz@scopenode@[email protected] east);%
% draw something, not necessary
\begin{scope}[on scopenode layer]%
\draw[#1](\tikz@scopenode@[email protected] west)rectangle(\tikz@scopenode@[email protected] east);%
\end{scope}%
}
\makeatother
\begin{document}
\begin{tikzpicture}[
remember picture,
inner sep=0pt,
outer sep=0pt,
]
\draw [help lines](-2,-2) grid (2,2);
\matrix[
column sep=2em,
row sep = 1em,
nodes in empty cells,
anchor=center,
nodes={anchor=center},
]
{
\scopenode[draw = red, fill = orange, anchor=south] {
\draw [blue] (0,0) -- (1,1);
};
&
\scopenode[draw = yellow, fill = green, anchor=north] {
\draw [black] (0,1) -- (1,0);
};
\\
};
\end{tikzpicture}
\end{document}
답변1
이것은 내가 얻을 수 있는 최고의 것입니다:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usetikzlibrary{backgrounds}
% \usetikzlibrary{external}
% \tikzexternalize
% \tikzset{external/prefix=build/}
\makeatletter
\newbox\tikz@sand@box
\newcount\tikz@scope@depth
\newdimen\tikz@scope@shiftx
\newdimen\tikz@scope@shifty
\newdimen\tikz@scope@swx
\newdimen\tikz@scope@swy
\newdimen\tikz@scope@nex
\newdimen\tikz@scope@ney
\tikz@scope@depth111\relax
\def\scopenode[#1]#2{%
\begin{pgfinterruptboundingbox}%
\advance\tikz@scope@depth111\relax%
% process the user option
\begin{scope}[name=tempscopenodename,at={(0,0)},anchor=center,#1]%
% try to extract positioning information: name, at, anchor
\global\let\tikz@fig@name@\tikz@fig@name%
\global\let\tikz@node@at@\tikz@node@at%
\global\let\tikz@anchor@\tikz@anchor%
\end{scope}%
\let\tikz@scopenode@name\tikz@fig@name@%
\let\tikz@scopenode@at\tikz@node@at@%
\let\tikz@scopenode@anchor\tikz@anchor@%
% try to typeset this scope
% we only need bounding box information
% the box itself will be discard
\setbox\tikz@sand@box=\hbox{%
\begin{scope}[local bounding box=tikz@sand@box\the\tikz@scope@depth,#1]%
#2%
\end{scope}%
}%
% goodbye. haha
\setbox\tikz@sand@box=\hbox{}%
% now typeset again
\begin{scope}[local bounding box=\tikz@scopenode@name]%
% use the bounding box information to reposition the scope
\pgfpointanchor{tikz@sand@box\the\tikz@scope@depth}{\tikz@scopenode@anchor}%
\tikz@scope@shiftx-\pgf@x%
\tikz@scope@shifty-\pgf@y%
\tikz@scopenode@at%
\advance\tikz@scope@shiftx\pgf@x%
\advance\tikz@scope@shifty\pgf@y%
\pgftransformshift{\pgfpoint{\tikz@scope@shiftx}{\tikz@scope@shifty}}
% the background path
% lengthy, tedious calculation
% someone please improve this
\pgfpointanchor{tikz@sand@box\the\tikz@scope@depth}{south west}
\tikz@scope@swx\pgf@x\advance\tikz@scope@swx\tikz@scope@shiftx
\tikz@scope@swy\pgf@y\advance\tikz@scope@swy\tikz@scope@shifty
\pgfpointanchor{tikz@sand@box\the\tikz@scope@depth}{north east}
\tikz@scope@nex\pgf@x\advance\tikz@scope@nex\tikz@scope@shiftx
\tikz@scope@ney\pgf@y\advance\tikz@scope@ney\tikz@scope@shifty
\path(\tikz@scope@swx,\tikz@scope@swy)coordinate(tempsw)
(\tikz@scope@nex,\tikz@scope@ney)coordinate(tempne);
\path[#1](tempsw)rectangle(tempne);
% typeset the content for real
\begin{scope}[#1]%
#2%
\end{scope}%
\end{scope}%
\pgfkeys{/pgf/freeze local bounding box=\tikz@scopenode@name}%
\global\let\tikz@scopenode@name@smuggle\tikz@scopenode@name%
\end{pgfinterruptboundingbox}%
% make up the bounding box
\path(\tikz@scopenode@[email protected] west)(\tikz@scopenode@[email protected] east);%
% compatible code for matrix
\expandafter\pgf@nodecallback\expandafter{\tikz@scopenode@name@smuggle}%
}
\makeatother
\begin{document}
\begin{tikzpicture}[remember picture,inner sep=0pt,outer sep=0pt]
\draw[help lines](-2,-2)grid(2,2);
\matrix()
[
column sep=2em,
row sep=1em,
nodes in empty cells,
anchor=center,
nodes={anchor=center},
]
{
\scopenode[draw=red,fill=orange,name=aaa,anchor=south] {
\draw[blue](0,0)--(1,1)circle(.2);
};
&
\scopenode[draw=yellow,fill=green,name=bbb,anchor=north] {
\draw[black](0,1)--(1,0)circle(.1);
};
&
\scopenode[fill=cyan,name=ccc,anchor=east,scale=.8] {
\draw(0,0)--(1,1)circle(.3)--(2,0);
};
\\
\node(aaaa){};
&
\node(bbbb){};
&
\node(cccc){};
\\
};
\draw[->](2,2)node[above]{this is the orange scopenode}to[bend left](aaa.east);
\draw[->](-2,-2)node[below]{this is the green scopenode}to[bend left](bbb.west);
\draw[->](3,-1)node[right]{this is the cyan scopenode}to[bend left](ccc.south);
\end{tikzpicture}
\end{document}
수입정보
미래의 나에게:
참고로, 행렬의 내용은 hbox에서 한 번만 조판됩니다. 그런 다음 해당 셀로 이동됩니다. 그런 다음 전체 행렬이 원하는 위치로 이동됩니다. 첫 번째 동작은 에 의해 수행 \pgf@matrix@shift@nodes@initial
되고 두 번째 동작은 에 의해 수행됩니다 \pgf@matrix@shift@nodes@secondary
. 그들은 단지 \pgf@shift@node
노드 목록에만 적용됩니다. 스코프노드를 등록하기 위해 다음 줄을 추가했습니다.
\expandafter\pgf@nodecallback\expandafter{\tikz@scopenode@name@smuggle}%
따라서 스코프노드도 이동됩니다.
현재 스코프노드의 모든 것은 두 번 조판됩니다. 중첩된 스코프노드의 경우 사물은 2 깊이 배로 조판됩니다. 정말 실망스럽습니다. 어쩌면 누군가가 Ti를 통해 이것을 개선할 수 있을지도 모릅니다.케이Z는 행렬을 다룹니다.
(그러나 행렬은 중첩될 수 없습니다. 당신이 승리합니다!)
게다가 너도 변했지
\global\let\tikz@fig@name\tikz@fig@name
에게
\global\let\tikz@fig@name@\tikz@fig@name
범위 노드의 이름은 다른 곳에서 액세스할 수 없습니다.
특히, 티케이\pgf@shift@node
Z는 행렬 자체에 적용됩니다 . 행렬의 이름이 지정되지 않은 경우 마지막 스코프 노드가 이동되어 원하지 않습니다. 이 멍청한 버그를 발견하는데만 2시간이 걸렸습니다. 교훈을 배우십시오.
또한 이제 범위 콘텐츠 앞에 채워지거나 그려지도록 범위 노드의 배경 경로를 하드코딩했습니다. (그래서 이름이배경경로) 그러나 계산이 길고 중복되는 것처럼 보입니다. 누군가가 그것을 개선할 수 있기를 바랍니다.
그럼에도 불구하고 pgfonlayer
. 그거 좋네.