3

So I've been researching making own shapes in TikZ. As most things in LaTeX, I've come to learn, it seems to have an extremely deep rabbit hole.

So I was wondering - is there an easy way out?

Is it possible to define a new shape that can be used "between two coordinates" (i.e. \draw (A) open box (B)) in e.g. \path and \draw, which use familiar notation when defining?

For example, one could do something like this; As a minimal example I'm making a rectangle that has no top:

\documentclass[border=10mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,fit}
\tikzset{
  % When open box is called via edge, draw a rectangle with no top:
  open box/.code={%
      \pgfkeysalso{%
        to path={%
            let
            \p{start}=(\tikztostart),
            \p{end}=(\tikztotarget)
            in
            (\tikztostart) -| (\tikztotarget)
            (\x{start},\y{start}) -- (\x{start},\y{end})
            % Make a fitted node to get good anchors
            node[fit={(\tikztostart)(\tikztotarget)}, inner sep=0pt](#1){}
          }
      }
    }
}

\begin{document}
  \begin{tikzpicture}
    \draw (0,0) edge[open box={therect}] (2,2);
    % How can this be switched with e.g:            %<---
    % \draw (0,0) open box[name=therect] (2,2) %<---
    \node at (therect.center){RECT!};
  \end{tikzpicture}
\end{document}

The result is:

I don't find this syntax half bad, actually, but I was wondering if there is something simpler that is made for this kind of thing, but I just haven't stumbled across?

Thanks! :)

4

I do not know how to achieve the syntax you are suggesting without changing the TikZ parser. The latter can be done but it is quite some effort. Explicit examples are given e.g. in Jake's post and in Loopspace's post. However, the latter also contains a very explicit statement:

I still strongly recommend the to path solution. Do not subvert the TikZ code unless you know what you are doing.

I do share the opinion expressed in this statement. Therefore I just suggest to shorten your code (no calc needed, nor \pgfkeysalso, the way the path is drawn here the corners look good, the node text can be the second argument).

\documentclass[border=10mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}
\tikzset{
  % When open box is called via edge, draw a rectangle with no top:
  open box/.style 2 args={%
        to path={%
            (\tikztostart|-\tikztotarget) -- (\tikztostart) -| (\tikztotarget)
            node[fit={(\tikztostart)(\tikztotarget)}, inner sep=0pt](#1){#2}
          }
    }
}

\begin{document}
  \begin{tikzpicture}
    \draw (0,0) to[open box={therect}{RECT!}] (2,2);
  \end{tikzpicture}
\end{document}

enter image description here

You may also make it more TikZy by using pgf keys instead of a style with multiple options.

\documentclass[border=10mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}
\tikzset{
  % When open box is called via edge, draw a rectangle with no top:
  open box/.style={%
        /utils/exec=\tikzset{/tikz/obox/.cd,#1},
        to path={%
            (\tikztostart|-\tikztotarget) -- (\tikztostart) -| (\tikztotarget)
            node[fit={(\tikztostart)(\tikztotarget)},obox/style]
        (\pgfkeysvalueof{/tikz/obox/name})
        {\pgfkeysvalueof{/tikz/obox/contents}}
          }
    },obox/.cd,name/.initial={},contents/.initial={},style/.style={inner sep=0pt}
}

\begin{document}
  \begin{tikzpicture}
    \draw (0,0) to[open box={name=rect,contents={RECT!}}] (2,2);
  \end{tikzpicture}
\end{document}

If the aim is just to create a node shape of this type, you could do e.g.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{shapes.geometric}
\begin{document}
\begin{tikzpicture}[open box/.style={regular polygon,regular polygon sides=4,
name=opbo,append after command={(opbo.north west)|-(opbo.south east)--(opbo.north east)}}]
\draw node[open box]{RECT!};
\end{tikzpicture}
\end{document}

enter image description here

  • Yeah - just did the open rectangle for simplicity. Was thinking that neural network layers with neurons would be just a tad too much :p But style 2 args is better, I agree :) – Andreas Storvik Strauman May 27 '19 at 12:58
  • @AndreasStorvikStrauman Clearly I do not know what you have in mind but I also do not see why it is so cumbersome to write to[open box=...] instead of, say, open box[...]. Of course, if I knew what you really want to do then there may be a way without changing the parser. See e.g. here what changing the parser may mean. You may also use pgf keys instead of many arguments. – user121799 May 27 '19 at 13:02
  • Yeah. Doing to[open box] or edge[open box] is fine, really. Its' mostly out of curiosity :) – Andreas Storvik Strauman May 27 '19 at 13:08
  • @AndreasStorvikStrauman You can look here for an explicit example. Or here. But I share LoopSpace's opinion: I still strongly recommend the to path solution. Do not subvert the TikZ code unless you know what you are doing. – user121799 May 27 '19 at 13:15
  • @marmot I'm now curious as to whether anyone other than me has released a package on CTAN that subverts the TikZ parser. – Loop Space May 27 '19 at 16:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.