当我用 tikz 编写包时出现一个奇怪的错误

当我用 tikz 编写包时出现一个奇怪的错误

这是 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 真的决定撤销,则几乎不可能这一改变。只有当能保证这些(非常好的!)变化不会被撤销时,我才会考虑明确说明这一点。

相关内容