7

I have a tikz picture that looks like this (a simple string diagram)

\begin{tikzpicture}[x=0.5cm, y=0.3cm]
\draw (0,0) -- (1,0);
\draw[rounded corners=0.3cm] (1,0) -- (1,1) -- (2,1);
\draw[rounded corners=0.3cm] (1,0) -- (1,-1) -- (2,-1);
\draw[fill=white] (1,0) circle (1.75pt);
\end{tikzpicture}

enter image description here

I'll be making many more of these, and later on I might change the y scale. If I do that, I want the rounded corners to scale as well. In other words, instead of writing rounded corners=0.3cm, is there a way to specify that the rounding should be "one y unit"?

Of course I could just define a macro for the y length, but I'm wondering if there's a more idiomatic way. I guess the more general question is how to avoid magic numbers in tikz diagrams as much as possible.

N. Virgo
  • 4,289
  • 2
  • 26
  • 41

2 Answers2

5

One solution consists in using this technique from Paul Gaborit:

\documentclass[tikz, border=2mm]{standalone}
\usetikzlibrary{calc}

\newcommand*{\getylength}[1]{
  \path let \p{y}=(0,1), \n{ylen}={veclen(\x{y},\y{y})}
    in \pgfextra{\xdef#1{\n{ylen}}};
}

\begin{document}
\begin{tikzpicture}[x=0.5cm, y=0.3cm]
  \getylength{\myylen}

  \draw (0,0) -- (1,0);
  \begin{scope}[rounded corners=\myylen]
    \draw (1,0) -- (1, 1) -- (2, 1);
    \draw (1,0) -- (1,-1) -- (2,-1);
  \end{scope}
  \draw[fill=white] (1,0) circle[radius=1.75pt];
\end{tikzpicture}
\end{document}

enter image description here

With [x=1.0cm, y=0.6cm], one obtains:

enter image description here

frougon
  • 24,283
  • 1
  • 32
  • 55
5

You could also just define a function, tikzy that tells you what the current y value is. Then you can say things like

\draw[rounded corners=tikzy] (1,0) -- (1,1) -- (2,1);

Note also that if you really want to produce many of those, you may want to use a pic.

\documentclass[tikz,border=3mm]{standalone}
\makeatletter
\pgfmathdeclarefunction{tikzy}{0}{\begingroup
\edef\pgfmathresult{\the\pgf@yy}%
\pgfmathsmuggle\pgfmathresult
\endgroup}
\makeatother
\begin{document}
\begin{tikzpicture}[pics/semiarc/.style={code={ \draw (0,0) -- (1,0);
 \draw[rounded corners=tikzy] (1,0) -- (1,1) -- (2,1);
 \draw[rounded corners=tikzy] (1,0) -- (1,-1) -- (2,-1);
 \draw[fill=white] (1,0) circle[radius=1.75pt];}}]
\begin{scope}[x=0.5cm, y=0.3cm]
 \draw (0,0) -- (1,0);
 \draw[rounded corners=0.3cm] (1,0) -- (1,1) -- (2,1);
 \draw[rounded corners=0.3cm] (1,0) -- (1,-1) -- (2,-1);
 \draw[fill=white] (1,0) circle[radius=1.75pt];
\end{scope}
\begin{scope}[xshift=2cm,x=0.5cm, y=0.3cm]
 \draw (0,0) -- (1,0);
 \draw[rounded corners=tikzy] (1,0) -- (1,1) -- (2,1);
 \draw[rounded corners=tikzy] (1,0) -- (1,-1) -- (2,-1);
 \draw[fill=white] (1,0) circle[radius=1.75pt];
\end{scope}
\begin{scope}[xshift=4cm,x=0.8cm, y=0.6cm]
 \draw (0,0) -- (1,0);
 \draw[rounded corners=tikzy] (1,0) -- (1,1) -- (2,1);
 \draw[rounded corners=tikzy] (1,0) -- (1,-1) -- (2,-1);
 \draw[fill=white] (1,0) circle[radius=1.75pt];
\end{scope}
\begin{scope}[yshift=-2cm]
  \pic[x=0.5cm, y=0.3cm]{semiarc};
 \begin{scope}[xshift=2cm,x=0.5cm, y=0.3cm]
  \pic{semiarc};
 \end{scope}
 \begin{scope}[xshift=4cm,x=0.8cm, y=0.6cm]
  \pic{semiarc};
 \end{scope}
\end{scope}
\end{tikzpicture}
\end{document}

enter image description here