1

I have a document with multiple variations on what is essentially the same image, and using this question and answer, I was able to simplify things a lot.

When I draw pictures, I usually use many coodinates to aid in connecting various parts together. I've just noticed that coordinates specified within a node seem to be accessible outside it, which is really helpful for my drawing style, but I'm left wondering if this is an expected feature of TikZ, or a useful trick that is asking for difficult-to-debug troubles. I'm really hoping for the former, as this technique makes drawing really simple.

Here's an MWE to illustrate what I mean. I've removed all the packages and code that aren't required though the drawing itself is still fairly complex as I wanted to illustrate the number of named nodes and coordinates within the pic that are accessible wherever it is placed (provided there isn't a name clash).

\RequirePackage{luatex85}
\documentclass[tikz]{standalone}

\usepackage{tikz}

\usetikzlibrary{calc}
\usetikzlibrary{positioning}
\usepgflibrary{arrows.meta}

\usepackage{siunitx}
\sisetup{detect-all, per-mode=symbol}
\DeclareSIPostPower\fourth{4}


\tikzset{%
  % End view, "real" x-axis points directly out of page. Projects end view of
  % view top left/right systems
  view end yz/.style={ 
    x={(0cm,1cm)},     % Simulated y-axis (actually x-axis)
    y={(1cm,0cm)},    % Simulated z-axis (actually y-axis)
  },
  dim edge/.style={densely dashed, line width=0.5pt, shorten >= -2.5mm, color=black!75!white},
  dim length/.style={draw, line width=0.5pt, arrows={Stealth-Stealth}, every node/.style={anchor=mid, midway, fill=white, node font=\footnotesize, inner sep=1pt},
  },
}

\begin{document}

\pgfkeys{/tikz/.cd,
  cross section/.pic={
    \path
      (0.1, 0) coordinate (bottom-left)
      -- ++(0, 1.5) coordinate (bottom-right)
      -- ++(1.5, 0) coordinate (top-right)
      -- ++(0, -1.5) coordinate (top-left)
      -- cycle;

    \fill[draw]
      (top-left)
      -- (top-right)
      -- ++(0.1, 0) coordinate (flange-top-right)
      -- ($(top-left) + (0.1, 0)$) coordinate (flange-top-left)
      -- (top-left)
      -- cycle
      (bottom-left)
      -- ++(-0.1, 0) coordinate (flange-bottom-left)
      -- ++(0, 0.5) coordinate (flange-bottom-inner-left)
      -- ++(0.1, 0) coordinate (flange-top-inner-left)
      -- cycle
      (bottom-right)
      -- ++(-0.1, 0) coordinate (flange-bottom-right)
      -- ++(0, -0.5) coordinate (flange-bottom-inner-right)
      -- ++(0.1, 0) coordinate (flange-top-inner-right)
      -- cycle;

    \fill[draw]
      ($(bottom-left)!0.5!(flange-top-inner-left) - (0, 0.03)$) coordinate (left-web-bottom-left)
      -- ($(bottom-left)!0.5!(flange-top-inner-left) + (1.5, -0.03)$) coordinate (left-web-top-left)
      -- ($(bottom-left)!0.5!(flange-top-inner-left) + (1.5, 0.03)$) coordinate (left-web-top-right)
      -- ($(bottom-left)!0.5!(flange-top-inner-left) + (0, 0.03)$) coordinate (left-web-bottom-right)
      -- cycle
      ($(bottom-right)!0.5!(flange-top-inner-right) - (0, 0.03)$) coordinate (right-web-bottom-left)
      -- ($(bottom-right)!0.5!(flange-top-inner-right) + (1.5, -0.03)$) coordinate (right-web-top-left)
      -- ($(bottom-right)!0.5!(flange-top-inner-right) + (1.5, 0.03)$) coordinate (right-web-top-right)
      -- ($(bottom-right)!0.5!(flange-top-inner-right) + (0, 0.03)$) coordinate (right-web-bottom-right)
      -- cycle;

  }
}

\begin{tikzpicture}

  \begin{scope}[view end yz, name prefix=end-]
    \fill[blue!60!white, draw=blue]
      (0.1, 0) coordinate (bottom-left)
      -- ++(0, 1.5) coordinate (bottom-right)
      -- ++(1.5, 0) coordinate (top-right)
      -- ++(0, -1.5) coordinate (top-left)
      -- cycle;

    \pic[fill=blue!40!white, draw=blue] at (0, 0){cross section};

    \draw[dim edge] (flange-bottom-left) -- ++(-0.25, 0) coordinate (dim-left-flange-left);
    \draw[dim edge] (flange-bottom-inner-left) -- ++(-0.25, 0) coordinate (dim-left-flange-inner);
    \draw[dim edge] (flange-bottom-inner-right) -- ++(-0.25, 0) coordinate (dim-right-flange-inner);
    \draw[dim edge] (flange-bottom-right) -- ++(-0.25, 0) coordinate (dim-right-flange-right);

    \draw[dim edge] (flange-top-left) -- ++(0.25, 0) coordinate (dim-top-flange-left);
    \draw[dim edge] (flange-top-right) -- ++(0.25, 0) coordinate (dim-top-flange-right);

    \draw[dim length] (dim-left-flange-left) -- (dim-left-flange-inner) node[below=0.1] {\SI{25}{\mm}};
    \draw[dim length] (dim-right-flange-right) -- (dim-right-flange-inner) node[below=0.1] {\SI{25}{\mm}};

    \draw[dim length] (dim-top-flange-left) -- (dim-top-flange-right) node[above=0.1] {\SI{75}{\mm}};

  \end{scope}

  \begin{scope}[xshift=2cm, view end yz, name prefix=centre-]

    \pic[fill=blue!40!white, draw=blue] at (0, 0){cross section};

    \draw[dim edge] ($(left-web-bottom-left) - (0.1, 0)$) -- ++(-0.5, 0) coordinate (dim-left-web-left);
    \draw[dim edge] ($(left-web-bottom-right) - (0.1, 0)$) -- ++(-0.5, 0) coordinate (dim-left-web-right);
    \draw[dim edge] ($(right-web-bottom-left) - (0.1, 0)$) -- ++(-0.5, 0) coordinate (dim-right-web-left);
    \draw[dim edge] ($(right-web-bottom-right) - (0.1, 0)$) -- ++(-0.5, 0) coordinate (dim-right-web-right);

    \draw[dim length, arrows={Stealth-}] (dim-left-web-left) -- ++(0, -0.25);
    \draw[dim length, arrows={Stealth-}] (dim-right-web-right) -- ++(0, 0.25);
    \draw[dim length] (dim-left-web-right) -- (dim-right-web-left) node[above=0.1] {\SI{47}{\mm}};
    \draw[dim length, draw=none] (dim-left-web-left) -- (dim-left-web-right) node[below=0.1] {\SI{3}{\mm}};
    \draw[dim length, draw=none] (dim-right-web-left) -- (dim-right-web-right) node[below=0.1] {\SI{3}{\mm}};

  \end{scope}

  \begin{scope}[yshift=3cm, view end yz, transform shape, scale=2, name prefix=big-]
    \fill[red!60!white, draw=red]
      (0.1, 0) coordinate (bottom-left)
      -- ++(0, 1.5) coordinate (bottom-right)
      -- ++(1.5, 0) coordinate (top-right)
      -- ++(0, -1.5) coordinate (top-left)
      -- cycle;

    \pic[fill=red!40!white, draw=red] at (0, 0){cross section};

  \end{scope}

  \draw[dim edge] (big-flange-bottom-left) -- ++(-0.25, 0) coordinate (dim-flange-bottom-left);
  \draw[dim edge] (big-bottom-left) -- ++(-0.25, 0) coordinate (dim-web-bottom);
  \draw[dim edge] (big-top-left) -- ++(-0.25, 0) coordinate (dim-web-top);
  \draw[dim edge] (big-flange-top-left) -- ++(-0.25, 0) coordinate (dim-flange-top-left);

  \draw[dim length] (dim-web-bottom) -- (dim-web-top) node[left=0.1] {\SI{75}{\mm}};
  \draw[dim length, arrows={Stealth-}] (dim-flange-bottom-left) -- ++(0, -0.25);
  \draw[dim length, arrows={Stealth-}] (dim-flange-top-left) -- ++(0, 0.25);
  \draw[dim length, draw=none] (dim-flange-bottom-left) -- (dim-web-bottom) node[left=0.1] {\SI{5}{\mm}};
  \draw[dim length, draw=none] (dim-web-top) -- (dim-flange-top-left) node[left=0.1] {\SI{5}{\mm}};

\end{tikzpicture}

\end{document}
Robbie
  • 2,893
  • This also works if I define the repeated picture as a pic, and I think that method is more "correct". Using pics also allows me to set colours and styles to the resulting object, but as far as I can tell, only if the object contains a single fill and colour. – Robbie Oct 31 '16 at 07:05
  • 5
    You know that the M in MWE stands for minimal? – Ulrike Fischer Oct 31 '16 at 07:56
  • Yes, but I was illustrating the point with a complex example, and it's much quicker to copy and paste a part of the document I'm working on than to come up with a much simpler example. It still works, and it's mostly a matter of copying and pasting the code; I stripped out everything I didn't think it needed to work. – Robbie Oct 31 '16 at 08:03
  • 6
    Well it may be much quicker for you. But it is obvious that it will take to much of my time to wade through your code only to understand your question. So I will leave and answer something else. – Ulrike Fischer Oct 31 '16 at 08:18
  • 1
    I'm with @UlrikeFischer. Life's too short to figure out what you mean. Which coordinate? Which node? And does the trick really depend on fontspec and physics? If so, then I'd say that it is not at all safe to rely on it, no. – cfr Oct 31 '16 at 13:02
  • How minimal a MWE should I provide? I used an example with lots of coordinates to illustrate that all the coordinates specified within the pic are accessible outside of it, which is unexpected but (if it's a bug) actually a really useful feature. – Robbie Oct 31 '16 at 13:27
  • 3
    It is not a bug and it is not unexpected. Read the paragraph »Name scopes.« in section »The Pic Syntax« on page 254 of the current documentation (version 3.0.1a). – esdd Oct 31 '16 at 13:56
  • Where are the problem to solve and the question? – Enlico Oct 31 '16 at 19:37
  • @esdd Ah thanks. I should really thoroughly read manuals rather than just skim through to find out whatever I'm looking for at the time. – Robbie Nov 01 '16 at 01:17
  • @esdd That part of the manual is indirectly relevant. However, referring to it without mentioning that the behaviour described there is currently completely broken is rather misleading. I wouldn't count on anything to do with referring to nodes or coordinates in pics continuing to work indefinitely because I have no idea what the fix for this is going to look like if it ever comes. pics are buggy as currently implemented. Period. They mostly work. They sometimes fail spectacularly. Try, for example, the seagull example from the manual. – cfr Nov 02 '16 at 01:12
  • Referencing points within the pic from outside is one part which is currently especially broken. It used to work. It hasn't worked for ages. – cfr Nov 02 '16 at 01:14

0 Answers0