1

I'm trying to improve my xfrm shape to fix two things (diagonal slash protruding beyond corners; not using line style of rectangle boundary) by using \pgfdeclareshape as in using linestyle and color of \tikzlastnode in append after command.

My question is: How can I reuse a \pgfpointadd command?

The part of the rectangle definition that draws its outline is (ref: https://svn.ssec.wisc.edu/repos/geoffc/LaTeX/beamerposter_UW-SSEC/pgfmoduleshapes.code.tex) is

    \pgfpathrectanglecorners
    {\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}
    {\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}}

and I want to add

    \pgfmoveto{\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}
    \pgflineto{{\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}}

but that's repeating the same coordinates and I'd like to know how to reuse a computed coordinate in pgf.

I tried using

  \def\swofs{\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}
  \def\neofs{\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}
  \backgroundpath{
    \pgfpathrectanglecorners{\swofs}{\neofs}
    \pgfmoveto{\swofs}\pgflineto{\neofs}    
  }

but that doesn't work. (I don't get an error, but it doesn't seem to define any shape.)

full example:

enter image description here

\documentclass[border=1mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,shadows,arrows,positioning,fit,backgrounds,calc}
\pgfdeclareshape{xfrmshape}{
  \inheritsavedanchors[from={rectangle}]
  \inheritbackgroundpath[from={rectangle}]
  \inheritanchorborder[from={rectangle}]
  \foreach \x in {center,north east,north west,north,south,south east,south west,east,west}{
    \inheritanchor[from={rectangle}]{\x}
  }
  \backgroundpath{
    \pgfpathrectanglecorners
    {\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}
    {\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}}
    \pgfmoveto{\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}
    \pgflineto{{\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}}
  }
}
\begin{document}
\begin{tikzpicture}[node distance=5mm, 
       blockcolors/.style={
        % The rest
        thick,draw=black,
        top color=white,
        bottom color=black!10,
        font=\sffamily\small
    },
    block/.style={
        % The shape:
        rectangle, minimum size=6mm, minimum height=10mm, minimum width=12mm,
        node distance=5mm,
        blockcolors,
        drop shadow
    },
    xfrm/.style={block,
      append after command={
             \pgfextra{\let\lastnode\tikzlastnode} 
            (\lastnode.south west) edge [-, thick, line join=round] (\lastnode.north east)
          }
    },      
    every node/.style={
        font=\sffamily\small
    }
    ]

\node (xfrm1) [xfrm, label={below:xfrm}] {};
\node (xfrm2) [block, xfrmshape, label={below:xfrmshape}] at (1.6, 0) {};
\end{tikzpicture}
\end{document}
Jason S
  • 2,838
  • Why not simply xfrm/.style={block, path picture={\draw (path picture bounding box.south west) -- (path picture bounding box.north east);} }? –  Apr 03 '20 at 18:35
  • uh... because I don't know any of this stuff and it's hard to figure out? :-) – Jason S Apr 03 '20 at 18:40

1 Answers1

1

One of the simplest ways to achieve what you want might be to use

xfrm/.style={block, path picture={
\draw (path picture bounding box.south west) -- (path picture bounding box.north east);} }

However, to answer your question, let me first mention that TikZ internally works with auxiliary dimensions like \pgf@xa and so on. However, since it is usually quite some effort to find out which of them are already used, you may just define some (local) macros:

  \backgroundpath{
    \southwest
    \pgfmathsetmacro{\myxa}{\pgf@x+\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetmacro{\myya}{\pgf@y+\pgfkeysvalueof{/pgf/outer xsep}}%
    \northeast
    \pgfmathsetmacro{\myxb}{\pgf@x-\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetmacro{\myyb}{\pgf@y-\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfpathrectanglecorners{\pgfpoint{\myxa pt}{\myya pt}}%
        {\pgfpoint{\myxb pt}{\myyb pt}}%
    \pgfmoveto{\pgfpoint{\myxa pt}{\myya pt}}%
    \pgflineto{\pgfpoint{\myxb pt}{\myyb pt}}%
  }

As you see, these macros get used twice. Doing it this way is somewhat slower than playing with the dimensions, but I do not think the difference in performance is measurable unless you produce zillions of these nodes.

\documentclass[border=1mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shadows}
\makeatletter
\pgfdeclareshape{xfrmshape}{
  \inheritsavedanchors[from={rectangle}]
  \inheritbackgroundpath[from={rectangle}]
  \inheritanchorborder[from={rectangle}]
  \foreach \x in {center,north east,north west,north,south,south east,south west,east,west}{
    \inheritanchor[from={rectangle}]{\x}
  }
  \backgroundpath{
    \southwest
    \pgfmathsetmacro{\myxa}{\pgf@x+\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetmacro{\myya}{\pgf@y+\pgfkeysvalueof{/pgf/outer xsep}}%
    \northeast
    \pgfmathsetmacro{\myxb}{\pgf@x-\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetmacro{\myyb}{\pgf@y-\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfpathrectanglecorners{\pgfpoint{\myxa pt}{\myya pt}}%
        {\pgfpoint{\myxb pt}{\myyb pt}}%
    \pgfmoveto{\pgfpoint{\myxa pt}{\myya pt}}%
    \pgflineto{\pgfpoint{\myxb pt}{\myyb pt}}%
  }
}
\makeatother
\begin{document}
\begin{tikzpicture}[node distance=5mm, 
       blockcolors/.style={
        % The rest
        thick,draw=black,
        top color=white,
        bottom color=black!10,
        font=\sffamily\small
    },
    block/.style={
        % The shape:
        rectangle, minimum size=6mm, minimum height=10mm, minimum width=12mm,
        node distance=5mm,
        blockcolors,
        drop shadow
    },
    xfrm/.style={block,
      path picture={\draw (path picture bounding box.south west)
       -- (path picture bounding box.north east);}
    },      
    every node/.style={
        font=\sffamily\small
    }
    ]

\node (xfrm1) [xfrm, label={below:xfrm}] {};
\node (xfrm2) [block, xfrmshape, label={below:xfrmshape}] at (1.6, 0) {};
\end{tikzpicture}
\end{document}

enter image description here