15

Consider this code in the TikZ - PGF manual, which uses a macro

% Main code from
% The TikZ - PGF manual
%   Author: Till Tantau et al
%   Version 3.1.3, released May 9, 2019
%   Page 40
\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
    \def\rectanglepath{-- ++(1cm,0cm) -- ++(0cm,1cm) -- ++(-1cm,0cm) -- cycle}
    \draw (0,0) \rectanglepath;
    \draw (1.5,0) \rectanglepath;
\end{tikzpicture}
\end{document}

and this one written by me, which uses pic

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
[rectanglepath/.pic={\draw (0,0)--++(1cm,0cm)--++(0cm,1cm)--++(-1cm,0cm)--cycle;}]
    \pic at (0,0) {rectanglepath};
    \pic at (1.5,0) {rectanglepath};
\end{tikzpicture}
\end{document}

Both give us the same output

enter image description here

Observation

Both give the same output. I prefer the latter one, as it is more "TikZ-ish". However, we can always change a code from pic to macro and vice versa, as above (am I wrong – is there a case in which we can't convert?), or draw the same figure using two different codes (this and this for example).

Also, I can't see any aspects in which macros are better than pic. Even arguments: we can also have pic with up to nine arguments with any pattern using /.style args.

In the PGF manual, sometimes I see pic is used, but sometimes a macro is used (it is even used in the title page!). From those examples, I can't figure out in what case I should use a macro and in what case I should use a pic.

Question

It may be quite clear by now.

If I have to draw the same "sub-"picture many times in a TikZ picture, should I use a pic or a macro? And why? Is there any cases in which I must use this one and not the other?

Thanks in advance.


Edit

As for @marmot's nice codes, I have written myself some code (against it) which uses macros

\documentclass{article}
\usepackage{tikz}
\begin{document}
\subsection*{Macros can have more complicated constructions}

\begin{tikzpicture}%[rectanglepath/.pic={\draw (-0.5,-0.5) rectangle ++(1,1);
%\draw[red] (-0.5,0.5) -- (0.5,-0.5);}]
\newcommand\rectanglepath[2][]{\scope[shift={(#2)},#1]\draw (-0.5,-0.5) rectangle ++(1,1);
                                \draw[red] (-0.5,0.5) -- (0.5,-0.5);\endscope}
%\path (0,0) pic{rectanglepath} (2,0) pic[dashed]{rectanglepath};
\rectanglepath{0,0}
\rectanglepath[dashed]{2,0}
\end{tikzpicture}

\subsection*{Macros can have names}

\begin{tikzpicture}%[rectanglepath/.pic={\draw (-0.5,-0.5) rectangle ++(1,1);
%\draw[red] (-0.5,0.5) coordinate(-tl)  -- (0.5,-0.5) coordinate(-br) ;}]
\newcommand\rectanglepath[3][]{\scope[shift={(#2)},#1]\draw (-0.5,-0.5) rectangle ++(1,1);
                                \draw[red] (-0.5,0.5) coordinate (#3-tl) 
                                    -- (0.5,-0.5) coordinate (#3-br);\endscope}
%\path (0,0) pic (A) {rectanglepath} (2,0) pic[dashed] (B) {rectanglepath};
\rectanglepath{0,0}{A}
\rectanglepath[dashed]{2,0}{B}
\draw (A-tl) to[out=30,in=150] (B-tl) (A-br) to[out=-30,in=-150] (B-br);
\end{tikzpicture}

\subsection*{Transformations are much more intuitive on macros}

\begin{tikzpicture}[rectanglepath/.pic={\draw (-0.5,-0.5) rectangle ++(1,1);}]
\newcommand\rectanglepath[2][]
    {\scope[shift={(#2)},#1]\draw (-0.5,-0.5) rectangle ++(1,1);\endscope}
%\path (0,0) pic[rotate=45]{rectanglepath} (2,0) pic[dashed,rotate=-30]{rectanglepath}
%(4,0) pic[thick,xscale=0.5]{rectanglepath};
\rectanglepath[rotate=45]{0,0}
\rectanglepath[rotate=-30,dashed]{2,0}
\rectanglepath[thick,xscale=0.5]{4,0}
\end{tikzpicture}
\end{document}

enter image description here

  • My experience is that pics are faster. For example, the threads on a screw. – John Kormylo May 25 at 13:45
  • @JohnKormylo If yes, probably it is faster on very long documents. On reports I usually write, they are equal in time taken – user156344 May 25 at 15:16
10

Here are threefour examples of things that are much harder to achieve in the macro approach. The first three examples have been translated to macros in the revised question.

\documentclass{article}
\usepackage{tikz}
\begin{document}
\subsection*{Pics can have more complicated constructions}
\tikzset{rectanglepath/.pic={\draw (-0.5,-0.5) rectangle ++(1,1);
\draw[red] (-0.5,0.5) coordinate(-tl)  -- (0.5,-0.5) coordinate(-br) ;}}

\begin{tikzpicture}
\path (0,0) pic{rectanglepath} (2,0) pic[dashed]{rectanglepath};
\end{tikzpicture}

\subsection*{Pics can have names}

\begin{tikzpicture}
\path (0,0) pic (A) {rectanglepath} (2,0) pic[dashed] (B) {rectanglepath};
\draw (A-tl) to[out=30,in=150] (B-tl) (A-br) to[out=-30,in=-150] (B-br);
\end{tikzpicture}

\subsection*{Transformations are much more intuitive on pics}

\begin{tikzpicture}
\path (0,0) pic[rotate=45]{rectanglepath} (2,0) pic[dashed,rotate=-30]{rectanglepath}
(4,0) pic[thick,xscale=0.5]{rectanglepath};
\end{tikzpicture}

\subsection*{You can insert pics in paths}

\begin{tikzpicture}[xboard/.style={insert path={
(0,0) grid (#1,#1)
foreach \X in {1,...,#1}
{(\X-0.5,\X-0.5) pic{rectanglepath} (\X-0.5,#1-\X+0.5) pic[rotate=90]{rectanglepath}}}}]
\draw[xboard=1,xshift=2cm,xboard=3,xshift=4cm,xboard=5];
\end{tikzpicture}

\end{document}

enter image description here

My personal take: pics win, at least in the above-described scenarios. IMHO the translated macros in the revised question substantiate this.

Notice that "behind the scenes" pics are macros at some level. So you will always be able to reproduce the outcome of a pic with a macro. However, the effort will be more substantial. And yes, if you are in the mood to do some unnecessary extra work, you can use macros instead of pics. So, yes, the choice can depend on the mood of the day.

Let me also stress that there are scenarios in which pics perform worse. An example of this type may be a life wheel.

BTW, there is also the insert path option that is sometimes preferable over pics IMO.

  • 1
    +1: Perfect answer! – Dr. Manuel Kuehner May 25 at 13:42
  • 2
    @JouleV Well, at some level a pic is a macro. My point is simply that things are harder to achieve with macros, and your macros substantiate this. I never claimed that you cannot achieve things done with a pic also with a macro, it is just harder and also less elegant IMHO. – user121799 May 25 at 15:42
  • 2
    @JouleV You also misinterpreted "The first thingy has \newcommand\rectanglepath[2][]{...}, the next \newcommand\rectanglepath[3][]{...}, they are not the same. ". The point is that you have to write different macros for different situations, and if you want to have the combined functionality, things become even more complicated. BTW, \foreach \X in {1,2,3} {\begin{tikzpicture}[rectanglepath/.pic={\draw (-0.5,-0.5) rectangle ++(1,1); \draw[red] (-0.5,0.5) -- (0.5,-0.5);}] \path (0,0) pic{rectanglepath} (2,0) pic[dashed]{rectanglepath}; \end{tikzpicture}} works ... – user121799 May 25 at 15:55
  • 1
    but \foreach \X in {1,2,3} {\begin{tikzpicture} \newcommand\rectanglepath[2][]{\scope[shift={(#2)},#1]\draw (-0.5,-0.5) rectangle ++(1,1); \draw[red] (-0.5,0.5) -- (0.5,-0.5);\endscope} \rectanglepath{0,0} \rectanglepath[dashed]{2,0} \end{tikzpicture}} doesn't. (Yes, I know how to fix it but it is, again, more complicated.) – user121799 May 25 at 15:55
  • 1
    @JouleV I tried to answer the question If I have to draw the same "sub-"picture many times in a TikZ picture, should I use a pic or a macro? And why?. My answer is that in most situations pics are less complicated, which is why they are arguably preferable. – user121799 May 25 at 16:48

Your Answer

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