tikz 形状,不太正确(锚点和键)

tikz 形状,不太正确(锚点和键)

因此,我尝试定义一个 tikz/pgf 形状。基本上这些节点不会包含任何文本,这只是一种不复制大量代码来绘制这些框的方法。

我有几个问题

  1. 在形状中是否有访问已定义锚点的官方方法?我为其创建了一个宏 ( \pgfutil@useanchor),但我认为可能有更好的方法。

  2. 形状本身,有没有更好的方法来绘制这两个额外的区域?(我可能没有得到正确的边距,只是想支持较粗的外线宽度)

  3. 键,尤其是dbox strib width,为什么更改初始值不会改变节点上的额外锚点?参见下图改变\beforebackgroundpath,显然这里做错了什么。

有任何想法吗?

\documentclass[a4paper]{memoir}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{shapes}

\makeatletter
% access to anchor coordinates, got to be a better way
\def\pgfutil@useanchor#1#2{\csname pgf@anchor@#1@#2\endcsname}

\pgfkeys{/pgf/.cd,
  dbox strib width/.initial=5mm,
  % dbox strib width/.code={%
  %   \def\pgf@lib@temp{#1}%
  %   \pgfkeyslet{/pgf/dbox strib width}{\pgf@lib@temp}%
  % },
  dbox strib color/.initial=blue,
}


\pgfdeclareshape{dbox}
{
  % this is just a rectangle with extra colored areas
  \inheritsavedanchors[from=rectangle] 
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{mid}
  \inheritanchor[from=rectangle]{mid west}
  \inheritanchor[from=rectangle]{mid east}
  \inheritanchor[from=rectangle]{base}
  \inheritanchor[from=rectangle]{base west}
  \inheritanchor[from=rectangle]{base east}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchor[from=rectangle]{south east}
  \anchor{center left}{
    \pgf@process{\pgfutil@useanchor{dbox}{west}}
    \advance\pgf@x by \pgfkeysvalueof{/pgf/dbox strib width}
    \advance\pgf@x by \pgflinewidth
  }
  \anchor{center left above}{
    \pgf@process{\pgfutil@useanchor{dbox}{north west}}
    \advance\pgf@x by \pgfkeysvalueof{/pgf/dbox strib width}
    \advance\pgf@x by \pgflinewidth
  }
  \anchor{center left below}{
    \pgf@process{\pgfutil@useanchor{dbox}{south west}}
    \advance\pgf@x by \pgfkeysvalueof{/pgf/dbox strib width}
    \advance\pgf@x by \pgflinewidth
  }
  \anchor{center right}{
    \pgf@process{\pgfutil@useanchor{dbox}{east}}
    \advance\pgf@x by -\pgfkeysvalueof{/pgf/dbox strib width}
    \advance\pgf@x by -\pgflinewidth
  }
  \anchor{center right above}{
    \pgf@process{\pgfutil@useanchor{dbox}{north east}}
    \advance\pgf@x by -\pgfkeysvalueof{/pgf/dbox strib width}
    \advance\pgf@x by -\pgflinewidth
  }
  \anchor{center right below}{
    \pgf@process{\pgfutil@useanchor{dbox}{south east}}
    \advance\pgf@x by -\pgfkeysvalueof{/pgf/dbox strib width}
    \advance\pgf@x by -\pgflinewidth
  }
  \beforebackgroundpath{
    \pgfsetfillcolor{\pgfkeysvalueof{/pgf/dbox strib color}}
    \pgfpathrectanglecorners{
      \pgfpointadd{\southwest}{
        \pgfpoint{\pgflinewidth}{\pgflinewidth}
      }
    }{
      \pgfpointadd{\pgf@process{\pgfutil@useanchor{dbox}{north  west}}}%
      {\pgfpoint{\pgflinewidth+\pgfkeysvalueof{/pgf/dbox strib width}}{-\pgflinewidth}}
    }
    \pgfusepath{fill}
    \pgfpathrectanglecorners{
      \pgfpointadd{\northeast}{
        \pgfpoint{-\pgflinewidth}{-\pgflinewidth}
      }
    }{
      \pgfpointadd{\pgf@process{\pgfutil@useanchor{dbox}{south  east}}}%
      {\pgfpoint{-\pgflinewidth-\pgfkeysvalueof{/pgf/dbox strib width}}{\pgflinewidth}}
    }
    \pgfusepath{fill}
  }
  %
  % Background path
  %
  \inheritbackgroundpath[from=rectangle]
}

\makeatother


\begin{document}

  \begin{tikzpicture}

  \begin{scope}[
    ms/.style = {minimum height=17mm,minimum
      width=6cm,draw,fill=cyan,shape=dbox,
      dbox strib color=red!50!white,
    },
    ]
     \node[ms,
     %dbox strib width=1cm,
     ] (BBb) at (0,2) {};
     \node[ms,
     dbox strib width=1cm,
    ] (BBa) at (0,0) {};
  \end{scope}

  \fill[green] (BBa.center left) circle (1mm);
  \fill[green] (BBa.center left above) circle (1mm);
  \fill[green] (BBa.center left below) circle (1mm);
  \fill[green] (BBa.center right) circle (1mm);
  \fill[green] (BBa.center right above) circle (1mm);
  \fill[green] (BBa.center right below) circle (1mm);

  \end{tikzpicture}
\end{document}

现在的情况如下

在此处输入图片描述

答案1

以下是根据第一原理(即没有继承)得出的所需形状的完整示例(我理解为)。我利用了(未记录的)命令,\addtosavedmacro该命令可以在“已保存的宏”(请参阅\savedmacro​​手册)内使用,在宏内一次定义多个宏\getdboxparameters

所有“常见”锚点都已定义,但图像根据节点是否具有某些文本内容排除了锚点。

为了添加填充颜色,必须添加一个dbox inner color键。

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{plotmarks}
\makeatletter
\pgfkeys{/pgf/.cd,
  dbox strib width/.initial=5mm,
  dbox strib color/.initial=red!50,
  dbox inner color/.initial=blue!20
}
\pgfdeclareshape{dbox}{%
  \savedmacro\getdboxparameters{%
    \pgfmathsetlength\pgf@xa{\wd\pgfnodeparttextbox}%
    \pgfmathsetlength\pgf@ya{\ht\pgfnodeparttextbox+\dp\pgfnodeparttextbox}%
    \pgfextract@process\centerpoint{%
      \pgfqpoint{.5\pgf@xa}{.5\pgf@ya}%
    }%
    \addtosavedmacro\centerpoint%
    %
    \pgfmathsetlengthmacro\dstrib{\pgfkeysvalueof{/pgf/dbox strib width}}%
    \pgfmathsetlengthmacro\innerxsep{\pgfkeysvalueof{/pgf/inner xsep}}%
    \pgfmathsetlengthmacro\innerysep{\pgfkeysvalueof{/pgf/inner ysep}}%
    \pgfmathsetlengthmacro\outerxsep{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlengthmacro\outerysep{\pgfkeysvalueof{/pgf/outer ysep}}%
    \pgfmathsetlengthmacro\minimumwidth{\pgfkeysvalueof{/pgf/minimum width}}%
    \pgfmathsetlengthmacro\minimumheight{\pgfkeysvalueof{/pgf/minimum height}}%
    %
    \pgfmathsetlengthmacro\halfwidth{max(\minimumwidth,%
      \pgf@xa+2*(\innerxsep+\dstrib))/2}%
    \pgfmathsetlengthmacro\halfheight{max(\minimumheight,%
      \pgf@ya+2*(\innerysep))/2}%    
    \pgfextract@process\southwest{%
      \pgfpointadd{\centerpoint}{%
        \pgfpointadd{\pgfqpoint{-\halfwidth}{-\halfheight}}%
          {\pgfqpoint{-\outerxsep}{-\outerysep}}}%
    }%
    \pgfextract@process\northeast{%
      \pgfpointadd{\centerpoint}{%
        \pgfpointadd{\pgfqpoint{\halfwidth}{\halfheight}}%
          {\pgfqpoint{\outerxsep}{\outerysep}}}%
    }%
    \edef\linewidth{\the\pgflinewidth}%
    \addtosavedmacro{\linewidth}%
    \addtosavedmacro\dstrib%
    \addtosavedmacro\outerxsep%
    \addtosavedmacro\outerysep%
    \addtosavedmacro\southwest%
    \addtosavedmacro\northeast%
    \addtosavedmacro\halfwidth%
  }
  \backgroundpath{%
    \getdboxparameters%
    \pgfpathrectanglecorners%
      {\pgfpointadd{\southwest}{\pgfqpoint{\outerxsep}{\outerysep}}}%
      {\pgfpointadd{\northeast}{\pgfqpoint{-\outerxsep}{-\outerysep}}}%
  }
  \behindbackgroundpath{%
    \getdboxparameters%
    \pgfpathrectanglecorners%
      {\pgfpointadd%
         {\southwest\pgf@xa=\pgf@x\northeast\pgf@x=\pgf@xa%
           \advance\pgf@x by\dstrib}%
         {\pgfqpoint{\outerxsep}{-\outerysep}}}%
      {\pgfpointadd%
         {\northeast\pgf@xa=\pgf@x\southwest\pgf@x=\pgf@xa%
           \advance\pgf@x by-\dstrib}%
         {\pgfqpoint{-\outerxsep}{\outerysep}}}%
    \pgfsetfillcolor{\pgfkeysvalueof{/pgf/dbox inner color}}%
    \pgfusepath{fill}%
    \pgfpathrectanglecorners%
      {\pgfpointadd{\southwest}{\pgfqpoint{\outerxsep}{\outerysep}}}%
      {\pgfpointadd%
         {\southwest\pgf@xa=\pgf@x\northeast\pgf@x=\pgf@xa%
           \advance\pgf@x by\dstrib}%
         {\pgfqpoint{\outerxsep}{-\outerysep}}%
    }%
    \pgfpathrectanglecorners%
      {\pgfpointadd{\northeast}{\pgfqpoint{-\outerxsep}{-\outerysep}}}%
      {\pgfpointadd%
         {\northeast\pgf@xa=\pgf@x\southwest\pgf@x=\pgf@xa%
           \advance\pgf@x by-\dstrib}%
         {\pgfqpoint{-\outerxsep}{\outerysep}}%
    }%
    \pgfsetfillcolor{\pgfkeysvalueof{/pgf/dbox strib color}}%
    \pgfusepath{fill}%
  }
  \anchorborder{%
    \getdboxparameters%
    \pgf@xb=\pgf@x% 
    \pgf@yb=\pgf@y%
    \southwest%
    \pgf@xa=\pgf@x% xa/ya is se
    \pgf@ya=\pgf@y%
    \northeast%
    \advance\pgf@x by-\pgf@xa%
    \advance\pgf@y by-\pgf@ya%
    \pgf@xc=.5\pgf@x% x/y is half width/height
    \pgf@yc=.5\pgf@y%
    \advance\pgf@xa by\pgf@xc% xa/ya becomes center
    \advance\pgf@ya by\pgf@yc%
    \edef\pgf@marshal{%
      \noexpand\pgfpointborderrectangle
      {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}
      {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
    }%
    \pgf@process{\pgf@marshal}%
    \advance\pgf@x by\pgf@xa%
    \advance\pgf@y by\pgf@ya%
  }
  \anchor{center}{\getdboxparameters\centerpoint}
  \anchor{north}{\getdboxparameters\centerpoint%
    \pgf@xa=\pgf@x\northeast\pgf@x=\pgf@xa}
  \anchor{south}{\getdboxparameters\centerpoint%
    \pgf@xa=\pgf@x\southwest\pgf@x=\pgf@xa}
  \anchor{east}{\getdboxparameters\centerpoint%
    \pgf@ya=\pgf@y\northeast\pgf@y=\pgf@ya}
  \anchor{west}{\getdboxparameters\centerpoint%
    \pgf@ya=\pgf@y\southwest\pgf@y=\pgf@ya}
  \anchor{north west}{\getdboxparameters\southwest%
    \pgf@xa=\pgf@x\northeast\pgf@x=\pgf@xa}
  \anchor{south east}{\getdboxparameters\northeast%
    \pgf@xa=\pgf@x\southwest\pgf@x=\pgf@xa}
  \anchor{north east}{\getdboxparameters\northeast}
  \anchor{south west}{\getdboxparameters\southwest}
  \anchor{base}{\getdboxparameters\centerpoint\pgf@y=0pt\relax}
  \anchor{base west}{\getdboxparameters\southwest\pgf@y=0pt\relax}
  \anchor{base east}{\getdboxparameters\northeast\pgf@y=0pt\relax}
  \anchor{mid}{\getdboxparameters\centerpoint%
    \pgfmathsetlength\pgf@y{0.5ex}}
  \anchor{mid west}{\getdboxparameters\southwest%
    \pgfmathsetlength\pgf@y{0.5ex}}
  \anchor{mid east}{\getdboxparameters\northeast%
    \pgfmathsetlength\pgf@y{0.5ex}}
  \anchor{center left}{\getdboxparameters%
    \pgfpointadd{\southwest\pgf@xa=\pgf@x\centerpoint\pgf@x=\pgf@xa}%
    {\pgfpoint{\dstrib+\outerxsep}{+0pt}}}
  \anchor{center left above}{\getdboxparameters%
    \pgfpointadd{\southwest\pgf@xa=\pgf@x\northeast\pgf@x=\pgf@xa}%
    {\pgfpoint{\dstrib+\outerxsep}{+0pt}}}
  \anchor{center left below}{\getdboxparameters%
    \pgfpointadd{\southwest}%
    {\pgfpoint{\dstrib+\outerxsep}{+0pt}}}
  \anchor{center right}{\getdboxparameters%
    \pgfpointadd{\northeast\pgf@xa=\pgf@x\centerpoint\pgf@x=\pgf@xa}%
    {\pgfpoint{-\dstrib-\outerxsep}{+0pt}}}
  \anchor{center right above}{\getdboxparameters%
    \pgfpointadd{\northeast}%
    {\pgfpoint{-\dstrib-\outerxsep}{+0pt}}}
  \anchor{center right below}{\getdboxparameters%
    \pgfpointadd{\southwest\pgf@ya=\pgf@y\northeast\pgf@y=\pgf@ya}%
    {\pgfpoint{-\dstrib-\outerxsep}{+0pt}}}
}
\begin{document}
\begin{tikzpicture}
\fill [red] circle [radius=.1pt];
\node [draw=gray!50, line width=0.125in, dbox, dbox strib width=0.5in,
   inner xsep=0.75in, inner ysep=0.5in] (s) {};
\foreach \anchor/\placement in
{north west/left, north/below, north east/right,
west/left, center/above, east/right,
south west/left, south/above, south east/right,
10/right, 190/below,
center left/above, center left above/above, center left below/below,
center right/above, center right above/above, center right below/below}
\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)}
node[\placement] {\scriptsize\texttt{(s.\anchor)}};
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

这不是对您的问题的直接回答,而只是一个例子,说明您可以使用pic带锚点的绘制形状,作为一种不复制大量代码即可绘制这些框的方法。

\documentclass[tikz,border=5,convert={density=2100}]{standalone}
\tikzset{
  dbox width/.store in=\dboxwidth,dbox width=10mm,
  dbox height/.store in=\dboxheight,dbox height=5mm,
  dbox color/.store in=\dboxcolor,dbox color=blue!50,
  strip width/.store in=\stripwidth,strip width=2mm,
  strip color/.store in=\stripcolor,strip color=red!50,
  set box size/.style = {inner sep=0,minimum width=#1,minimum height=\dboxheight},
  dbox/.pic = {
    \node[pic actions,fill=\dboxcolor,set box size=\dboxwidth] (-main) at (0,0){};
    \node[pic actions,fill=\stripcolor,below right,set box size=\stripwidth] (-left) at (-main.north west){};
    \node[pic actions,fill=\stripcolor,below left,set box size=\stripwidth] (-right) at (-main.north east){};
  }
}
\begin{document}
  \begin{tikzpicture}
    \pic[dbox color=green!70] (A) at (0,1) {dbox};
    \pic[strip color=yellow!70, strip width=1mm] (B) at (0,0) {dbox};
    \foreach \a in {center,north,south}
      \fill[green] (A-left.\a) circle(.4pt);
    \draw[-latex] (A-left.center) -- (B-right.center);
  \end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容