2

I have some Tikz figures which I use in multiple other figures. Right now I put them in a scope and use xshift/yshift/scale to place them at the position I want them to be. I have one example. I need a figure in a LaTeX document which has a \linewidth of 336pt, thus I want to work on my picture with this width in mind. I start by creating a frame of the desired width and scale. Next I want some boxes in it with some content. One of the boxes contains a stickman which I use in other figures as well. My current solution looks like this:

Here is one example:

\documentclass{standalone} \usepackage{tikz} \usetikzlibrary{positioning} \begin{document} \begin{tikzpicture}[node distance=0pt] % Stickman \begin{scope}[xshift=38pt, yshift=105pt, anchor=sout west, scale=0.45,local bounding box=person] \draw[thin, line cap=round] (0.05,1) -- (-0.05, 1.1); % hair1 \draw[thin, line cap=round] (-0.05,1) -- (-0.2, 1.12); % hair1 \draw[thick] (0,0) circle [radius=1]; % head \draw[thin] plot [smooth,tension=1.5] coordinates{(-0.7,0.45) (-0.5,0.52) (-0.4,0.52)}; % leyebrow \draw[fill=black] (-0.5,0.25) ellipse (0.1 and 0.15); \draw[thin] plot [smooth,tension=1.5] coordinates{(0.3,0.40) (0.1,0.50) (-0.1,0.50)}; % leyebrow \draw[fill=black] (0.1,0.20) ellipse (0.1 and 0.15); \draw[thick] plot [smooth,tension=1.5] coordinates{(-0.75,-0.4) (-0.2,-0.6) (0.3,-0.53)}; % mouth \draw[thick] (-0.15,-1) .. controls (-0.4,-2.5) .. (-0.5,-4); % torso \draw[thick] (-0.2,-1.3) -- (0.35, -2.55) -- (1.5, -2.2); % rarm \draw[thick,rotate around={110:(1.5, -2.2)}] (1.5, -2.4) ellipse (0.1 and 0.2); \draw[thick] (-0.2,-1.3) -- (-1.55, -2.55) -- (-1.75, -4.1); % rarm \draw[thick,rotate around={-5:(-1.75, -4.1)}] (-1.75, -4.3) ellipse (0.1 and 0.2); \draw[thick] (-0.5,-4) -- (0.7, -5.3) -- (1.4,-6.8); % rleg \draw[thick,rotate around={25:(1.4,-6.8)}] (1.65,-6.8) ellipse (0.25 and 0.1); \draw[thick] (-0.5,-4) -- (-0.95,-5.8) -- (-2.3,-7); % rleg \draw[thick,rotate around={-35:(-2.3,-7)}] (-2.05,-7) ellipse (0.25 and 0.1); \end{scope} \tikzstyle{box}=[draw, very thick, minimum height=120pt] % box style % Stickman Box \node[box, anchor=south west, minimum width=60pt] (FrameInput) at (5pt, 5pt) {}; \node[above=of FrameInput] (xy) {Input}; % Second box \node[box, minimum width=120pt, right=of FrameInput, xshift=15pt] (FrameNextStep) {}; \node[above=of FrameNextStep] (xy) {NextStep}; % Box Connections \path[->, very thick] (FrameInput) edge (FrameNextStep); % Picture Frame \draw[thick] (0,0) rectangle (336pt, 150pt); % frame \end{tikzpicture} \end{document} 

This results in the following image: enter image description here

I just wonder if there are better ways to solve this. e.g. by specifying my stickman should have a max width / height which equals to the FrameInput box without manually tuning the scale parameter of the scope. The same applies for the x/y shift, is there a better / more elegant way for positioning it?

2
  • To create multiple copies of an image, one can use a pic or savebox. The savebox would include an entire tikzpicture and is placed into a node using \usebox. Commented Jun 5, 2020 at 15:42
  • Thanks for the hint, I ended up using a pic and, if required, its local bounding box for edges to/from the pic. Commented Jun 10, 2020 at 7:19

1 Answer 1

2
  1. calculate the width and height and lowerleft anchor of original stickman in a pgfinterruptboundingbox environment.
  2. calculate the shift offset and scale value
  3. draw the correct stickman with lowerleft corner at (0, 0)

Here is the code:

\documentclass[border=1cm]{standalone} \usepackage{tikz} \usetikzlibrary{positioning, calc} \makeatletter \tikzset{ stickman height/.store in=\stickman@height, stickman height=2cm, stickman x sep/.store in=\stickman@x@sep, stickman x sep=3pt, stickman y sep/.store in=\stickman@y@sep, stickman y sep=3pt, } \gdef\@stickman{ \draw[thin, line cap=round] (0.05,1) -- (-0.05, 1.1); % hair1 \draw[thin, line cap=round] (-0.05,1) -- (-0.2, 1.12); % hair1 \draw[thick] (0,0) circle [radius=1]; % head \draw[thin] plot [smooth,tension=1.5] coordinates{(-0.7,0.45) (-0.5,0.52) (-0.4,0.52)}; % leyebrow \draw[fill=black] (-0.5,0.25) ellipse (0.1 and 0.15); \draw[thin] plot [smooth,tension=1.5] coordinates{(0.3,0.40) (0.1,0.50) (-0.1,0.50)}; % leyebrow \draw[fill=black] (0.1,0.20) ellipse (0.1 and 0.15); \draw[thick] plot [smooth,tension=1.5] coordinates{(-0.75,-0.4) (-0.2,-0.6) (0.3,-0.53)}; % mouth \draw[thick] (-0.15,-1) .. controls (-0.4,-2.5) .. (-0.5,-4); % torso \draw[thick] (-0.2,-1.3) -- (0.35, -2.55) -- (1.5, -2.2); % rarm \draw[thick,rotate around={110:(1.5, -2.2)}] (1.5, -2.4) ellipse (0.1 and 0.2); \draw[thick] (-0.2,-1.3) -- (-1.55, -2.55) -- (-1.75, -4.1); % rarm \draw[thick,rotate around={-5:(-1.75, -4.1)}] (-1.75, -4.3) ellipse (0.1 and 0.2); \draw[thick] (-0.5,-4) -- (0.7, -5.3) -- (1.4,-6.8); % rleg \draw[thick,rotate around={25:(1.4,-6.8)}] (1.65,-6.8) ellipse (0.25 and 0.1); \draw[thick] (-0.5,-4) -- (-0.95,-5.8) -- (-2.3,-7); % rleg \draw[thick,rotate around={-35:(-2.3,-7)}] (-2.05,-7) ellipse (0.25 and 0.1); } \newlength\pre@y@max \newlength\pre@y@min \newlength\pre@other \tikzset{ stickman/.pic={ \begin{pgfinterruptboundingbox} \begin{scope}[opacity=0, local bounding box=pre] \@stickman \end{scope} \path (pre.north); \pgfgetlastxy{\pre@other}{\pre@y@max} \path (pre.south); \pgfgetlastxy{\pre@other}{\pre@y@min} \pgfmathparse{(\stickman@height - 2*\stickman@y@sep)/(\pre@y@max - \pre@y@min)} \global\let\temp@scale\pgfmathresult \end{pgfinterruptboundingbox} \draw[line width=1pt] let \p1 = (pre.south west), \p2 = (pre.north west), \p3 = (pre.north east) in let \p{anchor} = ($(\stickman@x@sep,\stickman@y@sep)-\temp@scale*(pre.south west)$) in let \p{other} = ($2*(\stickman@x@sep,\stickman@y@sep)+\temp@scale*(\p3)-\temp@scale*(\p1)$) in coordinate (shift) at (\p{anchor}) coordinate (clip) at (\p{other}); \begin{scope}[local bounding box=now] \draw[line width=1pt] (0, 0) rectangle (clip); \begin{scope}[scale=\temp@scale, shift=(shift)] \@stickman \end{scope} \end{scope} \coordinate (-north) at (now.north); \coordinate (-east) at (now.east); \coordinate (-west) at (now.west); \coordinate (-south east) at (now.south east); } } \makeatother \begin{document} \begin{tikzpicture}[node distance=0pt] \pic [stickman height=3cm] (a) at (0, 0) {stickman}; \pic [stickman height=3cm, xshift=1cm, stickman x sep=10pt] (b) at (a-south east) {stickman}; \draw[->, very thick] (a-east) -- (b-west); \node[above] at (a-north) {Input}; \node[above] at (b-north) {NextStep}; \end{tikzpicture} \end{document} 

enter image description here

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.