![当我用 tikz 编写包时出现一个奇怪的错误](https://linux22.com/image/404482/%E5%BD%93%E6%88%91%E7%94%A8%20tikz%20%E7%BC%96%E5%86%99%E5%8C%85%E6%97%B6%E5%87%BA%E7%8E%B0%E4%B8%80%E4%B8%AA%E5%A5%87%E6%80%AA%E7%9A%84%E9%94%99%E8%AF%AF.png)
这是 mwe。似乎当将块在左右对齐时,它在 z 轴上会稍微移动一点,因此它没有对齐。但在 y 轴上移动是正常的。在我的包代码中,两种对齐方式的实现方式类似。我试图注释一些可能导致问题的代码,但没有付出任何努力。
\documentclass[tikz, border=1cm]{standalone}
\usetikzlibrary{calc, positioning}
\usepackage{dnnplot}
\begin{document}
\begin{tikzpicture}
\tikzset{
test/.style={
fill=green, right=4cm of a,
block={scale=1, width=20mm, height=20mm, channel=10mm, pre=a, align=#1}
}
}
\node[fill=red, block={scale=1.5, width=50mm, height=50mm, channel=10mm,
back plot}](a){};
{center};
\node[test=center] (b) {};
\draw[red, line width=1pt, ->] (a.east) -- (b.east);
\foreach \t in {left, right, up, down, upperright, upperleft, lowerleft,
lowerright}{
\node[test=\t] (\t) {};
}
\draw[dashed] (a.north east) -- (up.north west);
\draw[dashed] (a.south east) -- (down.south west);
\draw[dashed] ($(a.front north east)!.5!(a.front south east)$) -- ($(left.front
north west)!.5!(left.front south west)$);
\draw[dashed] ($(a.back north east)!.5!(a.back south east)$) -- ($(right.back
north west)!.5!(right.back south west)$);
\draw[red] (a.north east) -- +(1cm, 0);
\draw[red] (a.south east) -- +(1cm, 0);
\end{tikzpicture}
\end{document}
以下是包代码。
\ProvidesPackage{dnnplot}
\RequirePackage{pdftexcmds}
\usetikzlibrary{math, calc}
\makeatletter
\let\pdfstrcmp=\pdf@strcmp
\pgfkeys{/block plot/.cd,
width/.store in=\block@width, width=1cm,
height/.store in=\block@height, height=1cm,
channel/.store in=\block@channel, channel=1cm,
scale/.store in=\block@scale, scale=.5,
pre/.store in=\block@pre, pre=,
back plot/.store in=\block@back@plot, back plot=,
back plot/.default=true,
zshift/.store in=\block@zshift, zshift=0,
front/.store in=\block@front, front=,
align axis/.store in=\block@align@axis, align axis=x,
hfactor/.store in=\block@hfactor, hfactor=.5,
vfactor/.store in=\block@vfactor, vfactor=.5,
align/.store in=\block@align, align=center,
}
\pgfdeclareshape{base block}
{
\inheritsavedanchors[from=rectangle]
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{north east}
\inheritanchor[from=rectangle]{south west}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{south east}
\saveddimen{\offset}{
\pgfmathsetlength\pgf@x{
sqrt(2)/8*\block@scale*\block@width
}
}
\anchor{front}{
\pgf@process{\southwest}
\pgf@xa=.5\pgf@x
\pgf@ya=.5\pgf@y
\pgf@process{\northeast}
\pgf@x=.5\pgf@x
\pgf@y=.5\pgf@y
\advance \pgf@x by \pgf@xa
\advance \pgf@y by \pgf@ya
\advance \pgf@x by -\offset
\advance \pgf@y by -\offset
}
\anchor{front south west}{
\pgf@process{\southwest}
\advance \pgf@x by -\offset
\advance \pgf@y by -\offset
}
\anchor{back south west}{
\pgf@process{\southwest}
\advance \pgf@x by \offset
\advance \pgf@y by \offset
}
\anchor{front north east}{
\pgf@process{\northeast}
\advance \pgf@x by -\offset
\advance \pgf@y by -\offset
}
\anchor{back north east}{
\pgf@process{\northeast}
\advance \pgf@x by \offset
\advance \pgf@y by \offset
}
\anchor{front south east}{
\pgf@process{\northeast}
\pgf@xa=\pgf@x
\advance \pgf@xa by -\offset
\pgf@process{\southwest}
\advance \pgf@y by -\offset
\pgf@x=\pgf@xa
}
\anchor{back south east}{
\pgf@process{\northeast}
\pgf@xa=\pgf@x
\advance \pgf@xa by \offset
\pgf@process{\southwest}
\advance \pgf@y by \offset
\pgf@x=\pgf@xa
}
\anchor{front north west}{
\pgf@process{\southwest}
\pgf@xa=\pgf@x
\advance \pgf@xa by -\offset
\pgf@process{\northeast}
\advance \pgf@y by -\offset
\pgf@x=\pgf@xa
}
\anchor{back north west}{
\pgf@process{\southwest}
\pgf@xa=\pgf@x
\advance \pgf@xa by \offset
\pgf@process{\northeast}
\advance \pgf@y by \offset
\pgf@x=\pgf@xa
}
\backgroundpath{
\pgf@process{\southwest}
\pgf@xa=\pgf@x \pgf@ya=\pgf@y
\pgf@process{\northeast}
\pgf@xb=\pgf@x \pgf@yb=\pgf@y
\def\block@add@offset##1{
\pgfpointadd{##1}{\pgfqpoint{\offset}{\offset}}
}
\def\block@sub@offset##1{
\pgfpointadd{##1}{\pgfqpoint{-\offset}{-\offset}}
}
\def\block@southwest{\pgfqpoint{\pgf@xa}{\pgf@ya}}
\def\block@southeast{\pgfqpoint{\pgf@xb}{\pgf@ya}}
\def\block@northeast{\pgfqpoint{\pgf@xb}{\pgf@yb}}
\def\block@northwest{\pgfqpoint{\pgf@xa}{\pgf@yb}}
% main path
\pgfpathmoveto{\block@sub@offset{\block@southwest}}
\pgfpathlineto{\block@sub@offset{\block@southeast}}
\pgfpathlineto{\block@add@offset{\block@southeast}}
\pgfpathlineto{\block@add@offset{\block@northeast}}
\pgfpathlineto{\block@add@offset{\block@northwest}}
\pgfpathlineto{\block@sub@offset{\block@northwest}}
\pgfpathclose
% other edge
\pgfpathmoveto{\block@sub@offset{\block@northeast}}
\pgfpathlineto{\block@sub@offset{\block@northwest}}
\pgfpathmoveto{\block@sub@offset{\block@northeast}}
\pgfpathlineto{\block@sub@offset{\block@southeast}}
\pgfpathmoveto{\block@sub@offset{\block@northeast}}
\pgfpathlineto{\block@add@offset{\block@northeast}}
}
\foregroundpath{
% back plot
\ifx\block@back@plot\pgfutil@empty
\else
\pgfsetdash{{1mm}{1mm}}{0mm}
\pgfpathmoveto{\block@add@offset{\block@southwest}}
\pgfpathlineto{\block@sub@offset{\block@southwest}}
\pgfpathmoveto{\block@add@offset{\block@southwest}}
\pgfpathlineto{\block@add@offset{\block@northwest}}
\pgfpathmoveto{\block@add@offset{\block@southwest}}
\pgfpathlineto{\block@add@offset{\block@southeast}}
\pgfusepath{stroke}
\fi
}
}
\tikzset{
block/.code={\tikzset{/block plot/.cd, #1}
% scale
\pgfmathsetlengthmacro\scaled@width{\block@scale*\block@width}
\pgfmathsetlengthmacro\scaled@height{\block@scale*\block@height}
\pgfmathsetlengthmacro\scaled@channel{\block@scale*\block@channel}
% shift
% initial shift
\def\block@shift{(0, 0)}
% add to shift
\def\shift@to@coordinate@x##1{(##1, 0)}
\def\shift@to@coordinate@y##1{(0, ##1)}
\def\shift@to@coordinate@z##1{{-sqrt(2)/4}*(##1, ##1)}
% ##1 coordinate
\def\update@block@shift##1{
\edef\block@shift{($\block@shift+##1$)}
}
% ##1 x, y, z
% ##2 shift length
\def\add@to@shift##1##2{
\update@block@shift{\csname shift@to@coordinate@##1\endcsname{##2}}
}
% shift in z axis
\add@to@shift{z}{\block@zshift}
% predefined macros
% ##1 ##2 anchors ##3 factor
\edef\pre@temp##1##2##3{##3*(\block@pre.##1)-##3*(\block@pre.##2)}
% ##1 factor
\def\pre@offset@x##1{\pre@temp{back north east}{back north west}{##1}}
\def\pre@offset@y##1{\pre@temp{back north west}{back south west}{##1}}
\def\pre@offset@z##1{\pre@temp{back north west}{front north west}{##1}}
\def\cur@offset@x{(\scaled@channel, 0)}
\def\cur@offset@y{(0, \scaled@height)}
\pgfmathsetlength\pgfutil@tempdima{sqrt(2)/4*\scaled@width}
\def\cur@offset@z{(\pgfutil@tempdima, \pgfutil@tempdima)}
% total shift (with factor 1)
% ##1 x, y, z ##2 factor
\edef\shift@x##1{\pre@offset@x{{##1}} - {##1}*\cur@offset@x}
\edef\shift@y##1{\pre@offset@y{{##1}} - {##1}*\cur@offset@y}
\edef\shift@z##1{\pre@offset@z{{##1}} - {##1}*\cur@offset@z}
\ifx\block@pre\pgfutil@empty
\else
% front of shift
\ifx\block@front\pgfutil@empty
\else
\update@block@shift{\pre@offset@z{{-0.5}}}
\add@to@shift{z}{\scaled@width}
\add@to@shift{z}{\block@front}
\fi
% align shift
% align option has higher priority
% ##1 shift style ##2 hfactor ##3 vfactor
\def\shift@style##1##2##3{
\expandafter\def\csname block@shift@##1\endcsname{
\def\block@hfactor{##2}
\def\block@vfactor{##3}
}
}
\shift@style{left}{0}{0.5}
\shift@style{right}{1}{0.5}
\shift@style{down}{0.5}{0}
\shift@style{up}{0.5}{1}
\shift@style{upperleft}{0}{1}
\shift@style{upperright}{1}{1}
\shift@style{lowerleft}{0}{0}
\shift@style{lowerright}{1}{0}
\ifcsname block@shift@\block@align\endcsname
\csname block@shift@\block@align\endcsname
\fi
% hshift and vshift in 3 directions
\pgfmathsetmacro\real@hfactor{\[email protected]}
\pgfmathsetmacro\real@vfactor{\[email protected]}
\def\define@hv@shift##1##2##3{
\expandafter\edef\csname hshift@##1\endcsname{
\csname shift@##2\endcsname{\real@hfactor}
}
\expandafter\edef\csname vshift@##1\endcsname{
\csname shift@##3\endcsname{\real@vfactor}
}
}
\define@hv@shift{x}{z}{y}
\define@hv@shift{y}{x}{z}
\define@hv@shift{z}{x}{y}
\ifcsname hshift@\block@align@axis\endcsname
\csname hshift@\block@align@axis\endcsname
\update@block@shift{
\csname hshift@\block@align@axis\endcsname +
\csname vshift@\block@align@axis\endcsname
}
\fi
\fi
% general
\tikzset{
shift={\block@shift},
base block, draw, fill opacity=.2, thick,
minimum height=\scaled@height,
minimum width=\scaled@channel,
}
}
}
\def\block@label@upperleft@a{front north west}
\def\block@label@upperleft@b{back north west}
\def\block@label@upperright@a{front north east}
\def\block@label@upperright@b{back north east}
\def\block@label@lowerleft@a{front south west}
\def\block@label@lowerleft@b{back south west}
\def\block@label@lowerright@a{front south east}
\def\block@label@lowerright@b{back south east}
\def\block@label@frontwest@a{front south west}
\def\block@label@frontwest@b{front north west}
\def\block@label@fronteast@a{front south east}
\def\block@label@fronteast@b{front north east}
\def\block@label@backwest@a{back south west}
\def\block@label@backwest@b{back north west}
\def\block@label@backeast@a{back south east}
\def\block@label@backeast@b{back north east}
\def\block@label@frontsouth@a{front south west}
\def\block@label@frontsouth@b{front south east}
\def\block@label@frontnorth@a{front north west}
\def\block@label@frontnorth@b{front north east}
\def\block@label@backsouth@a{back south west}
\def\block@label@backsouth@b{back south east}
\def\block@label@backnorth@a{back north west}
\def\block@label@backnorth@b{back north east}
% #1 -- label position
% #2 -- node name
% #3 -- passed string
% #4 -- label text
% #5 -- edge specification
\newcommand{\block@label}[4]{
\path (#2.\csname block@label@#3@a\endcsname) --
node[#1] {#4}
(#2.\csname block@label@#3@b\endcsname);
}
\def\block@label@position@upperleft{left}
\def\block@label@position@upperright{right}
\def\block@label@position@lowerleft{left}
\def\block@label@position@lowerright{right}
\def\block@label@position@frontwest{left}
\def\block@label@position@fronteast{right}
\def\block@label@position@backwest{left}
\def\block@label@position@backeast{right}
\def\block@label@position@frontnorth{above}
\def\block@label@position@frontsouth{below}
\def\block@label@position@backnorth{above}
\def\block@label@position@backsouth{above}
% #1 -- label position, optional
% #2 -- node name
% #3 -- passed string
% #4 -- label text
\newcommand{\blocklabel}[4][]{
\ifcsname block@label@position@#3\endcsname
\def\block@label@position{#1}
% use default position
\ifx\block@label@position\pgfutil@empty
\def\block@label@position{\csname block@label@position@#3\endcsname}
\fi
\block@label{\block@label@position}{#2}{#3}{#4}
\fi
}
\makeatother
答案1
正如我之前在回答你问题时提到的,我对你的成就印象深刻。在我看来,这是 Ti 最令人惊奇的发展之一钾一会儿 Z。
至于你的问题:通过替换你的样式文件
\ProvidesPackage{dnnplot}
\RequirePackage{pdftexcmds}
\usetikzlibrary{math, calc}
\makeatletter
%\let\pdfstrcmp=\pdf@strcmp%
% removed, see see https://tex.stackexchange.com/questions/516078/alignment-of-customized-shape-in-3d-space#comment1304939_516078
\pgfkeys{/block plot/.cd,
width/.store in=\block@width, width=1cm,
height/.store in=\block@height, height=1cm,
channel/.store in=\block@channel, channel=1cm,
scale/.store in=\block@scale, scale=.5,
pre/.store in=\block@pre, pre=,
back plot/.store in=\block@back@plot, back plot=,
back plot/.default=true,
zshift/.store in=\block@zshift, zshift=0,
front/.store in=\block@front, front=,
align axis/.store in=\block@align@axis, align axis=x,
hfactor/.store in=\block@hfactor, hfactor=.5,
vfactor/.store in=\block@vfactor, vfactor=.5,
align/.store in=\block@align, align=center,
}
\pgfdeclareshape{base block}
{
\inheritsavedanchors[from=rectangle]
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{north east}
\inheritanchor[from=rectangle]{south west}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{south east}
\saveddimen{\offset}{
\pgfmathsetlength\pgf@x{
sqrt(2)/8*\block@scale*\block@width
}
}
\anchor{front}{
\pgf@process{\southwest}
\pgf@xa=.5\pgf@x
\pgf@ya=.5\pgf@y
\pgf@process{\northeast}
\pgf@x=.5\pgf@x
\pgf@y=.5\pgf@y
\advance \pgf@x by \pgf@xa
\advance \pgf@y by \pgf@ya
\advance \pgf@x by -\offset
\advance \pgf@y by -\offset
}
\anchor{front south west}{
\pgf@process{\southwest}
\advance \pgf@x by -\offset
\advance \pgf@y by -\offset
}
\anchor{back south west}{
\pgf@process{\southwest}
\advance \pgf@x by \offset
\advance \pgf@y by \offset
}
\anchor{front north east}{
\pgf@process{\northeast}
\advance \pgf@x by -\offset
\advance \pgf@y by -\offset
}
\anchor{back north east}{
\pgf@process{\northeast}
\advance \pgf@x by \offset
\advance \pgf@y by \offset
}
\anchor{front south east}{
\pgf@process{\northeast}
\pgf@xa=\pgf@x
\advance \pgf@xa by -\offset
\pgf@process{\southwest}
\advance \pgf@y by -\offset
\pgf@x=\pgf@xa
}
\anchor{back south east}{
\pgf@process{\northeast}
\pgf@xa=\pgf@x
\advance \pgf@xa by \offset
\pgf@process{\southwest}
\advance \pgf@y by \offset
\pgf@x=\pgf@xa
}
\anchor{front north west}{
\pgf@process{\southwest}
\pgf@xa=\pgf@x
\advance \pgf@xa by -\offset
\pgf@process{\northeast}
\advance \pgf@y by -\offset
\pgf@x=\pgf@xa
}
\anchor{back north west}{
\pgf@process{\southwest}
\pgf@xa=\pgf@x
\advance \pgf@xa by \offset
\pgf@process{\northeast}
\advance \pgf@y by \offset
\pgf@x=\pgf@xa
}
\backgroundpath{
\pgf@process{\southwest}
\pgf@xa=\pgf@x \pgf@ya=\pgf@y
\pgf@process{\northeast}
\pgf@xb=\pgf@x \pgf@yb=\pgf@y
\def\block@add@offset##1{
\pgfpointadd{##1}{\pgfqpoint{\offset}{\offset}}
}
\def\block@sub@offset##1{
\pgfpointadd{##1}{\pgfqpoint{-\offset}{-\offset}}
}
\def\block@southwest{\pgfqpoint{\pgf@xa}{\pgf@ya}}
\def\block@southeast{\pgfqpoint{\pgf@xb}{\pgf@ya}}
\def\block@northeast{\pgfqpoint{\pgf@xb}{\pgf@yb}}
\def\block@northwest{\pgfqpoint{\pgf@xa}{\pgf@yb}}
% main path
\pgfpathmoveto{\block@sub@offset{\block@southwest}}
\pgfpathlineto{\block@sub@offset{\block@southeast}}
\pgfpathlineto{\block@add@offset{\block@southeast}}
\pgfpathlineto{\block@add@offset{\block@northeast}}
\pgfpathlineto{\block@add@offset{\block@northwest}}
\pgfpathlineto{\block@sub@offset{\block@northwest}}
\pgfpathclose
% other edge
\pgfpathmoveto{\block@sub@offset{\block@northeast}}
\pgfpathlineto{\block@sub@offset{\block@northwest}}
\pgfpathmoveto{\block@sub@offset{\block@northeast}}
\pgfpathlineto{\block@sub@offset{\block@southeast}}
\pgfpathmoveto{\block@sub@offset{\block@northeast}}
\pgfpathlineto{\block@add@offset{\block@northeast}}
}
\foregroundpath{
% back plot
\ifx\block@back@plot\pgfutil@empty
\else
\pgfsetdash{{1mm}{1mm}}{0mm}
\pgfpathmoveto{\block@add@offset{\block@southwest}}
\pgfpathlineto{\block@sub@offset{\block@southwest}}
\pgfpathmoveto{\block@add@offset{\block@southwest}}
\pgfpathlineto{\block@add@offset{\block@northwest}}
\pgfpathmoveto{\block@add@offset{\block@southwest}}
\pgfpathlineto{\block@add@offset{\block@southeast}}
\pgfusepath{stroke}
\fi
}
}
\tikzset{
block/.code={\tikzset{/block plot/.cd, #1}
% scale
\pgfmathsetlengthmacro\scaled@width{\block@scale*\block@width}
\pgfmathsetlengthmacro\scaled@height{\block@scale*\block@height}
\pgfmathsetlengthmacro\scaled@channel{\block@scale*\block@channel}
% shift
% initial shift
\def\block@shift{(0, 0)}
% add to shift
%\def\tikz@shift@to@coordinate@x{}
\def\shift@to@coordinate@x##1{(##1, 0)}%
\def\shift@to@coordinate@y##1{(0, ##1)}%
\def\shift@to@coordinate@z##1{({-##1*sqrt(2)/2}, {-##1*sqrt(2)/2})}%
% ##1 coordinate
\def\update@block@shift##1{
\edef\block@shift{($\block@shift+##1$)}
}
% ##1 x, y, z
% ##2 shift length
\def\add@to@shift##1##2{
\update@block@shift{\csname shift@to@coordinate@##1\endcsname{##2}}
}
% shift in z axis
\add@to@shift{z}{\block@zshift}
% predefined macros
% ##1 ##2 anchors ##3 factor
\edef\pre@temp##1##2##3{##3*(\block@pre.##1)-##3*(\block@pre.##2)}
% ##1 factor
\def\pre@offset@x##1{\pre@temp{back north east}{back north west}{##1}}
\def\pre@offset@y##1{\pre@temp{back north west}{back south west}{##1}}
\def\pre@offset@z##1{\pre@temp{back north west}{front north west}{##1}}
\def\cur@offset@x{(\scaled@channel, 0)}
\def\cur@offset@y{(0, \scaled@height)}
\pgfmathsetmacro\pgfutil@tempa{sqrt(2)/4*\scaled@width}
\edef\cur@offset@z{(\pgfutil@tempa pt, \pgfutil@tempa pt)}
% total shift (with factor 1)
% ##1 x, y, z ##2 factor
\edef\shift@x##1{\pre@offset@x{{##1}} - {##1}*\cur@offset@x}
\edef\shift@y##1{\pre@offset@y{{##1}} - {##1}*\cur@offset@y}
\edef\shift@z##1{\pre@offset@z{{##1}} - {##1}*\cur@offset@z}
\ifx\block@pre\pgfutil@empty
\else
% front of shift
\ifx\block@front\pgfutil@empty
\else
\update@block@shift{\pre@offset@z{{-0.5}}}
\add@to@shift{z}{\scaled@width}
\add@to@shift{z}{\block@front}
\fi
% align shift
% align option has higher priority
% ##1 shift style ##2 hfactor ##3 vfactor
\def\shift@style##1##2##3{
\expandafter\def\csname block@shift@##1\endcsname{
\def\block@hfactor{##2}
\def\block@vfactor{##3}
}
}
\shift@style{left}{0}{0.5}
\shift@style{right}{1}{0.5}
\shift@style{down}{0.5}{0}
\shift@style{up}{0.5}{1}
\shift@style{upperleft}{0}{1}
\shift@style{upperright}{1}{1}
\shift@style{lowerleft}{0}{0}
\shift@style{lowerright}{1}{0}
\ifcsname block@shift@\block@align\endcsname
\csname block@shift@\block@align\endcsname
\fi
% hshift and vshift in 3 directions
\pgfmathsetmacro\real@hfactor{\[email protected]}
\pgfmathsetmacro\real@vfactor{\[email protected]}
\def\define@hv@shift##1##2##3{
\expandafter\edef\csname hshift@##1\endcsname{
\csname shift@##2\endcsname{\real@hfactor}
}
\expandafter\edef\csname vshift@##1\endcsname{
\csname shift@##3\endcsname{\real@vfactor}
}
}
\define@hv@shift{x}{z}{y}
\define@hv@shift{y}{x}{z}
\define@hv@shift{z}{x}{y}
\ifcsname hshift@\block@align@axis\endcsname
\csname hshift@\block@align@axis\endcsname
\update@block@shift{
\csname hshift@\block@align@axis\endcsname +
\csname vshift@\block@align@axis\endcsname
}
\fi
\fi
% general
\tikzset{
shift/.expanded={\block@shift},
base block, draw, fill opacity=.2, thick,
minimum height=\scaled@height,
minimum width=\scaled@channel,
}
}
}
\def\block@label@upperleft@a{front north west}
\def\block@label@upperleft@b{back north west}
\def\block@label@upperright@a{front north east}
\def\block@label@upperright@b{back north east}
\def\block@label@lowerleft@a{front south west}
\def\block@label@lowerleft@b{back south west}
\def\block@label@lowerright@a{front south east}
\def\block@label@lowerright@b{back south east}
\def\block@label@frontwest@a{front south west}
\def\block@label@frontwest@b{front north west}
\def\block@label@fronteast@a{front south east}
\def\block@label@fronteast@b{front north east}
\def\block@label@backwest@a{back south west}
\def\block@label@backwest@b{back north west}
\def\block@label@backeast@a{back south east}
\def\block@label@backeast@b{back north east}
\def\block@label@frontsouth@a{front south west}
\def\block@label@frontsouth@b{front south east}
\def\block@label@frontnorth@a{front north west}
\def\block@label@frontnorth@b{front north east}
\def\block@label@backsouth@a{back south west}
\def\block@label@backsouth@b{back south east}
\def\block@label@backnorth@a{back north west}
\def\block@label@backnorth@b{back north east}
% #1 -- label position
% #2 -- node name
% #3 -- passed string
% #4 -- label text
% #5 -- edge specification
\newcommand{\block@label}[4]{
\path (#2.\csname block@label@#3@a\endcsname) --
node[#1] {#4}
(#2.\csname block@label@#3@b\endcsname);
}
\def\block@label@position@upperleft{left}
\def\block@label@position@upperright{right}
\def\block@label@position@lowerleft{left}
\def\block@label@position@lowerright{right}
\def\block@label@position@frontwest{left}
\def\block@label@position@fronteast{right}
\def\block@label@position@backwest{left}
\def\block@label@position@backeast{right}
\def\block@label@position@frontnorth{above}
\def\block@label@position@frontsouth{below}
\def\block@label@position@backnorth{above}
\def\block@label@position@backsouth{above}
% #1 -- label position, optional
% #2 -- node name
% #3 -- passed string
% #4 -- label text
\newcommand{\blocklabel}[4][]{
\ifcsname block@label@position@#3\endcsname
\def\block@label@position{#1}
% use default position
\ifx\block@label@position\pgfutil@empty
\def\block@label@position{\csname block@label@position@#3\endcsname}
\fi
\block@label{\block@label@position}{#2}{#3}{#4}
\fi
}
\makeatother
你的 MWE 产生
重要的变化是使用
\pgfmathsetmacro\pgfutil@tempa{sqrt(2)/4*\scaled@width}
\edef\cur@offset@z{(\pgfutil@tempa pt, \pgfutil@tempa pt)}
代替
\pgfmathsetlength\pgfutil@tempdima{sqrt(2)/4*\scaled@width}
\def\cur@offset@z{(\pgfutil@tempdima, \pgfutil@tempdima)}
正如评论中提到的,\pgfutil@tempa
没有扩展。因此,它在使用时会假定不同的值。当然,这种选择并不是唯一的,例如
\pgfmathsetlength\pgfutil@tempdima{sqrt(2)/4*\scaled@width}
\edef\cur@offset@z{(\the\pgfutil@tempdima, \the\pgfutil@tempdima)}%
也可以。这里还有一些题外的建议:每行都以 结尾以%
避免出现虚假空格。在 中这应该无关紧要tikzpicture
,但这可能是一种很好的做法。此外,在包中你不需要\makeatletter
和\makeatother
。因此你可以使用
\ProvidesPackage{dnnplot}
\usetikzlibrary{calc}
\pgfkeys{/block plot/.cd,
width/.store in=\block@width, width=1cm,
height/.store in=\block@height, height=1cm,
channel/.store in=\block@channel, channel=1cm,
scale/.store in=\block@scale, scale=.5,
pre/.store in=\block@pre, pre=,
back plot/.store in=\block@back@plot, back plot=,
back plot/.default=true,
zshift/.store in=\block@zshift, zshift=0,
front/.store in=\block@front, front=,
align axis/.store in=\block@align@axis, align axis=x,
hfactor/.store in=\block@hfactor, hfactor=.5,
vfactor/.store in=\block@vfactor, vfactor=.5,
align/.store in=\block@align, align=center,
}
\pgfdeclareshape{base block}
{%
\inheritsavedanchors[from=rectangle]%
\inheritanchorborder[from=rectangle]%
\inheritanchor[from=rectangle]{center}%
\inheritanchor[from=rectangle]{north}%
\inheritanchor[from=rectangle]{south}%
\inheritanchor[from=rectangle]{east}%
\inheritanchor[from=rectangle]{west}%
\inheritanchor[from=rectangle]{north east}%
\inheritanchor[from=rectangle]{south west}%
\inheritanchor[from=rectangle]{north west}%
\inheritanchor[from=rectangle]{south east}%
\saveddimen{\offset}{%
\pgfmathsetlength\pgf@x{%
sqrt(2)/8*\block@scale*\block@width%
}%
}%
\anchor{front}{%
\pgf@process{\southwest}%
\pgf@xa=.5\pgf@x%
\pgf@ya=.5\pgf@y%
\pgf@process{\northeast}%
\pgf@x=.5\pgf@x%
\pgf@y=.5\pgf@y%
\advance \pgf@x by \pgf@xa%
\advance \pgf@y by \pgf@ya%
\advance \pgf@x by -\offset%
\advance \pgf@y by -\offset%
}%
\anchor{front south west}{%
\pgf@process{\southwest}%
\advance \pgf@x by -\offset%
\advance \pgf@y by -\offset%
}%
\anchor{back south west}{%
\pgf@process{\southwest}%
\advance \pgf@x by \offset%
\advance \pgf@y by \offset%
}%
\anchor{front north east}{%
\pgf@process{\northeast}%
\advance \pgf@x by -\offset%
\advance \pgf@y by -\offset%
}%
\anchor{back north east}{%
\pgf@process{\northeast}%
\advance \pgf@x by \offset%
\advance \pgf@y by \offset%
}%
\anchor{front south east}{%
\pgf@process{\northeast}%
\pgf@xa=\pgf@x%
\advance \pgf@xa by -\offset%
\pgf@process{\southwest}%
\advance \pgf@y by -\offset%
\pgf@x=\pgf@xa%
}%
\anchor{back south east}{%
\pgf@process{\northeast}%
\pgf@xa=\pgf@x%
\advance \pgf@xa by \offset%
\pgf@process{\southwest}%
\advance \pgf@y by \offset%
\pgf@x=\pgf@xa%
}%
\anchor{front north west}{%
\pgf@process{\southwest}%
\pgf@xa=\pgf@x%
\advance \pgf@xa by -\offset%
\pgf@process{\northeast}%
\advance \pgf@y by -\offset%
\pgf@x=\pgf@xa%
}%
\anchor{back north west}{%
\pgf@process{\southwest}%
\pgf@xa=\pgf@x%
\advance \pgf@xa by \offset%
\pgf@process{\northeast}%
\advance \pgf@y by \offset%
\pgf@x=\pgf@xa%
}%
\backgroundpath{%
\pgf@process{\southwest}%
\pgf@xa=\pgf@x \pgf@ya=\pgf@y%
\pgf@process{\northeast}%
\pgf@xb=\pgf@x \pgf@yb=\pgf@y%
\def\block@add@offset##1{%
\pgfpointadd{##1}{\pgfqpoint{\offset}{\offset}}%
}%
\def\block@sub@offset##1{%
\pgfpointadd{##1}{\pgfqpoint{-\offset}{-\offset}}%
}%
\def\block@southwest{\pgfqpoint{\pgf@xa}{\pgf@ya}}%
\def\block@southeast{\pgfqpoint{\pgf@xb}{\pgf@ya}}%
\def\block@northeast{\pgfqpoint{\pgf@xb}{\pgf@yb}}%
\def\block@northwest{\pgfqpoint{\pgf@xa}{\pgf@yb}}%
% main path%
\pgfpathmoveto{\block@sub@offset{\block@southwest}}%
\pgfpathlineto{\block@sub@offset{\block@southeast}}%
\pgfpathlineto{\block@add@offset{\block@southeast}}%
\pgfpathlineto{\block@add@offset{\block@northeast}}%
\pgfpathlineto{\block@add@offset{\block@northwest}}%
\pgfpathlineto{\block@sub@offset{\block@northwest}}%
\pgfpathclose%
% other edge%
\pgfpathmoveto{\block@sub@offset{\block@northeast}}%
\pgfpathlineto{\block@sub@offset{\block@northwest}}%
\pgfpathmoveto{\block@sub@offset{\block@northeast}}%
\pgfpathlineto{\block@sub@offset{\block@southeast}}%
\pgfpathmoveto{\block@sub@offset{\block@northeast}}%
\pgfpathlineto{\block@add@offset{\block@northeast}}%
}%
\foregroundpath{%
% back plot%
\ifx\block@back@plot\pgfutil@empty%
\else%
\pgfsetdash{{1mm}{1mm}}{0mm}%
\pgfpathmoveto{\block@add@offset{\block@southwest}}%
\pgfpathlineto{\block@sub@offset{\block@southwest}}%
\pgfpathmoveto{\block@add@offset{\block@southwest}}%
\pgfpathlineto{\block@add@offset{\block@northwest}}%
\pgfpathmoveto{\block@add@offset{\block@southwest}}%
\pgfpathlineto{\block@add@offset{\block@southeast}}%
\pgfusepath{stroke}%
\fi%
}%
}%
%
\tikzset{%
block/.code={\tikzset{/block plot/.cd, #1}%
% scale%
\pgfmathsetlengthmacro\scaled@width{\block@scale*\block@width}%
\pgfmathsetlengthmacro\scaled@height{\block@scale*\block@height}%
\pgfmathsetlengthmacro\scaled@channel{\block@scale*\block@channel}%
% shift%
% initial shift%
\def\block@shift{(0, 0)}%
% add to shift%
%\def\tikz@shift@to@coordinate@x{}%
\def\shift@to@coordinate@x##1{(##1, 0)}%%
\def\shift@to@coordinate@y##1{(0, ##1)}%%
\def\shift@to@coordinate@z##1{({-##1*sqrt(2)/2}, {-##1*sqrt(2)/2})}%%
% ##1 coordinate%
\def\update@block@shift##1{%
\edef\block@shift{($\block@shift+##1$)}%
}%
% ##1 x, y, z%
% ##2 shift length%
\def\add@to@shift##1##2{%
\update@block@shift{\csname shift@to@coordinate@##1\endcsname{##2}}%
}%
% shift in z axis%
\add@to@shift{z}{\block@zshift}%
% predefined macros%
% ##1 ##2 anchors ##3 factor%
\edef\pre@temp##1##2##3{##3*(\block@pre.##1)-##3*(\block@pre.##2)}%
% ##1 factor%
\def\pre@offset@x##1{\pre@temp{back north east}{back north west}{##1}}%
\def\pre@offset@y##1{\pre@temp{back north west}{back south west}{##1}}%
\def\pre@offset@z##1{\pre@temp{back north west}{front north west}{##1}}%
\def\cur@offset@x{(\scaled@channel, 0)}%
\def\cur@offset@y{(0, \scaled@height)}%
\pgfmathsetmacro\pgfutil@tempa{sqrt(2)/4*\scaled@width}%
\edef\cur@offset@z{(\pgfutil@tempa pt, \pgfutil@tempa pt)}%
% total shift (with factor 1)%
% ##1 x, y, z ##2 factor%
\edef\shift@x##1{\pre@offset@x{{##1}} - {##1}*\cur@offset@x}%
\edef\shift@y##1{\pre@offset@y{{##1}} - {##1}*\cur@offset@y}%
\edef\shift@z##1{\pre@offset@z{{##1}} - {##1}*\cur@offset@z}%
\ifx\block@pre\pgfutil@empty%
\else%
% front of shift%
\ifx\block@front\pgfutil@empty%
\else%
\update@block@shift{\pre@offset@z{{-0.5}}}%
\add@to@shift{z}{\scaled@width}%
\add@to@shift{z}{\block@front}%
\fi%
% align shift%
% align option has higher priority%
% ##1 shift style ##2 hfactor ##3 vfactor%
\def\shift@style##1##2##3{%
\expandafter\def\csname block@shift@##1\endcsname{%
\def\block@hfactor{##2}%
\def\block@vfactor{##3}%
}%
}%
\shift@style{left}{0}{0.5}%
\shift@style{right}{1}{0.5}%
\shift@style{down}{0.5}{0}%
\shift@style{up}{0.5}{1}%
\shift@style{upperleft}{0}{1}%
\shift@style{upperright}{1}{1}%
\shift@style{lowerleft}{0}{0}%
\shift@style{lowerright}{1}{0}%
\ifcsname block@shift@\block@align\endcsname%
\csname block@shift@\block@align\endcsname%
\fi%
% hshift and vshift in 3 directions%
\pgfmathsetmacro\real@hfactor{\[email protected]}%
\pgfmathsetmacro\real@vfactor{\[email protected]}%
\def\define@hv@shift##1##2##3{%
\expandafter\edef\csname hshift@##1\endcsname{%
\csname shift@##2\endcsname{\real@hfactor}%
}%
\expandafter\edef\csname vshift@##1\endcsname{%
\csname shift@##3\endcsname{\real@vfactor}%
}%
}%
\define@hv@shift{x}{z}{y}%
\define@hv@shift{y}{x}{z}%
\define@hv@shift{z}{x}{y}%
\ifcsname hshift@\block@align@axis\endcsname%
\csname hshift@\block@align@axis\endcsname%
\update@block@shift{%
\csname hshift@\block@align@axis\endcsname +%
\csname vshift@\block@align@axis\endcsname%
}%
\fi%
\fi%
% general%
\tikzset{%
shift/.expanded={\block@shift},%
base block, draw, fill opacity=.2, thick,%
minimum height=\scaled@height,%
minimum width=\scaled@channel,%
}%
}%
}%
%
\def\block@label@upperleft@a{front north west}%
\def\block@label@upperleft@b{back north west}%
\def\block@label@upperright@a{front north east}%
\def\block@label@upperright@b{back north east}%
\def\block@label@lowerleft@a{front south west}%
\def\block@label@lowerleft@b{back south west}%
\def\block@label@lowerright@a{front south east}%
\def\block@label@lowerright@b{back south east}%
\def\block@label@frontwest@a{front south west}%
\def\block@label@frontwest@b{front north west}%
\def\block@label@fronteast@a{front south east}%
\def\block@label@fronteast@b{front north east}%
\def\block@label@backwest@a{back south west}%
\def\block@label@backwest@b{back north west}%
\def\block@label@backeast@a{back south east}%
\def\block@label@backeast@b{back north east}%
\def\block@label@frontsouth@a{front south west}%
\def\block@label@frontsouth@b{front south east}%
\def\block@label@frontnorth@a{front north west}%
\def\block@label@frontnorth@b{front north east}%
\def\block@label@backsouth@a{back south west}%
\def\block@label@backsouth@b{back south east}%
\def\block@label@backnorth@a{back north west}%
\def\block@label@backnorth@b{back north east}%
% #1 -- label position%
% #2 -- node name%
% #3 -- passed string%
% #4 -- label text%
% #5 -- edge specification%
\newcommand{\block@label}[4]{%
\path (#2.\csname block@label@#3@a\endcsname) --%
node[#1] {#4}%
(#2.\csname block@label@#3@b\endcsname);%
}%
\def\block@label@position@upperleft{left}%
\def\block@label@position@upperright{right}%
\def\block@label@position@lowerleft{left}%
\def\block@label@position@lowerright{right}%
\def\block@label@position@frontwest{left}%
\def\block@label@position@fronteast{right}%
\def\block@label@position@backwest{left}%
\def\block@label@position@backeast{right}%
\def\block@label@position@frontnorth{above}%
\def\block@label@position@frontsouth{below}%
\def\block@label@position@backnorth{above}%
\def\block@label@position@backsouth{above}%
% #1 -- label position, optional%
% #2 -- node name%
% #3 -- passed string%
% #4 -- label text%
\newcommand{\blocklabel}[4][]{%
\ifcsname block@label@position@#3\endcsname%
\def\block@label@position{#1}%
% use default position%
\ifx\block@label@position\pgfutil@empty%
\def\block@label@position{\csname block@label@position@#3\endcsname}%
\fi%
\block@label{\block@label@position}{#2}{#3}{#4}%
\fi%
}%
最大的改变是重写它,使其能够在 3d 空间的任意投影中工作(适度努力即可实现)并对平面进行 3d 排序。后者是可行的,但需要付出巨大努力,或者如果 Henri Menke 真的决定撤销,则几乎不可能这一改变。只有当能保证这些(非常好的!)变化不会被撤销时,我才会考虑明确说明这一点。