4

I am trying to put some labels at some angles:

\documentclass[14pt]{extarticle}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[label distance=0.5cm]

\node[draw,circle, minimum size=10cm, thick,
      label=1:a, label=2:a, label=3:a, label=4:a, label=5:a,
      label=6:a, label=7:a, label=8:a, label=9:a, label=10:a,
      label=44:a, label=45:a, label=46:a, label=47:a, label=48:a,
      label=91:a, label=92:a, label=93:a, label=94:a, label=95:a,]
    (c1) at (0,0) {};

\end{tikzpicture}
\end{document}

The labels are positioned evenly except for some gaps, that seem to appear only around the angles of 90*n+3 degrees:

Mind the gap

Why is this happening and what can I do about it?

5
  • 2
    The problem also appears at 90*n-3: \documentclass[14pt]{extarticle} \usepackage{tikz} \begin{document} \begin{tikzpicture}[label distance=0.5cm] \foreach \Angle in {1,2,...,360} \node[draw,circle, minimum size=10cm,label=\Angle:a] (c1) at (0,0) {}; \end{tikzpicture} \end{document} – Gonzalo Medina Aug 8 '15 at 15:32
  • Same for pin: \tikz\foreach~in{0,...,359}\node[circle, minimum size=10cm, thick,pin=~:.]{}; – Kpym Aug 8 '15 at 16:14
  • If you check this snippet \tikz\draw[draw=red]foreach~in{0,...,99}{(0,0) node[circle, minimum size=4cm,thick,pin=~:.]{}(~:2)--(~:2.1)}; you can see that the imprecision is everywhere ... – Kpym Aug 8 '15 at 16:34
  • 1
    This is probably the same problem as in this question. – Kpym Aug 8 '15 at 16:43
  • An answer and explanaitions are here : tex.stackexchange.com/questions/163762/… – Tarass Aug 8 '15 at 17:03
3

I clicked Kpym and Tarass's links and in fact Loop Space gives the reason.

Briefly speaking, TikZ invented anchor to help you put nodes at the desired position. In this case, we are putting labels, which are nodes internally, lacking the information of which anchor is used.

Obviously TikZ uses the anchor on the edge if the inout angle is about 90x, and uses the anchor at the corner otherwise. What is not obvious is that TikZ implemented two mechanisms to do so: normally it is \tikz@auto@anchor deciding the anchor; with absolute option it is \tikz@compute@direction. Perhaps the most obscure thing is that they do not always return the same result:

\documentclass[border=9,tikz]{standalone}
\usetikzlibrary{shapes.misc}
\begin{document}
\def\r{100cm}\def\s{10cm}\def\t{1cm}

\tikzset{
  every label/.style={draw=black,inner sep=0,minimum size=\t}
}
\begin{tikzpicture}
\clip(0,\r)+(-\s,-\s)rectangle+(\s,\s);
\draw(0,0)node[draw,circle,minimum size=\r*2,
         label=90:90,label=91:91,label=92:92,label=93:93,label=94:94,label=95:95]{}
     (0,0)edge(90:\r) edge(91:\r) edge(92:\r) edge(93:\r) edge(94:\r) edge(95:\r);
\end{tikzpicture}

\begin{tikzpicture}[absolute]
\clip(0,\r)+(-\s,-\s)rectangle+(\s,\s);
\draw(0,0)node[draw,circle,minimum size=\r*2,
         label=90:90,label=91:91,label=92:92,label=93:93,label=94:94,label=95:95]{}
     (0,0)edge(90:\r) edge(91:\r) edge(92:\r) edge(93:\r) edge(94:\r) edge(95:\r);
\end{tikzpicture}

To create a \tikz@whatever@called which is continuous with respect to the input angle, and hence prevent the gap, the final \tikz@anchor should either

  • be fixed; or
  • vary continuously with respect to the input angle.

Loop Space implement the first possibility, in which the anchor center is the default choice.

\makeatletter
\tikzset{
  reset label anchor/.code={%
    \let\tikz@auto@anchor=\pgfutil@empty
    \def\tikz@anchor{#1}
  },
  reset label anchor/.default=center,
  every label/.append style={reset label anchor}
}
\makeatother
\begin{tikzpicture}
\clip(0,\r)+(-\s,-\s)rectangle+(\s,\s);
\draw(0,0)node[draw,circle,minimum size=\r*2,
         label=90:90,label=91:91,label=92:92,label=93:93,label=94:94,label=95:95]{}
     (0,0)edge(90:\r) edge(91:\r) edge(92:\r) edge(93:\r) edge(94:\r) edge(95:\r);
\end{tikzpicture}

I implemented the second possibility. In case the input angle is, say, 95, the output anchor is 275. In general, I add 180 to the input.

Therefore, if you extend the line connecting the parent and child nodes, it pass through the two centers, regardless its shape. (For circle labels, the distance is unstable because TikZ adds mandatory fix designed for rectangle labels.)

\tikzset{
  every label/.append style={cross out},
  every edge/.append style={shorten >=-1cm}
}
\makeatletter
\def\tikz@compute@direction#1{
  \let\tikz@do@auto@anchor=\relax
  \pgfmathsetcount{\c@pgf@counta}{#1+180}
  \def\tikz@anchor{\the\c@pgf@counta}
}
\begin{tikzpicture}[absolute]
\clip(0,\r)+(-\s,-\s)rectangle+(\s,\s);
\draw(0,0)node[draw,circle,minimum size=\r*2,
         label=90:90,label=91:91,label=92:92,label=93:93,label=94:94,label=95:95]{}
     (0,0)edge(90:\r) edge(91:\r) edge(92:\r) edge(93:\r) edge(94:\r) edge(95:\r);
\end{tikzpicture}
0
2

To understand why these gaps around 0 or 90 appear, you should carefully read section "17.10.2 The Label Option" from pgfmanual. There you can read:

Then, an anchor point for the label node is computed. It is determined in such a way that the label node will “face away” from the border of the main node. The anchor that is chosen depends on the position of the border point that is chosen and its position relative to the center of the main node and on whether the transform shape option is set. In detail, when the computed border point is at 0º, the anchor west will be used. Similarly, when the border point is at 90º, the anchor south will be used, and so on for 180º and 270º.

For angles between these “major” angles, like 30º or 110º, combined anchors, like south west for 30º or south east for 110º, are used. However, for angles close to the major angles, (differing by up to 2º from the major angle), the anchor for the major angle is used. Thus, a label at a border point for 2º will have the anchor west, while a label for 3º will have the anchor south west, resulting in a “jump” of the anchor. You can set the anchor “by hand” using the anchor key or indirect keys like left.

Now you can understand why there's a gap between labels at 2º and 3º. The former is placed according its west anchor, while for the last south west anchor is used. Remember that, by default, nodes are rectangular, then next figure shows the expected (although strange) behaviour

enter image description here

It shows labels at angles 1º, 2º and 3º. You can see how two first labels are closer than the third although red dots keep similar distance. The gap between labels contents is due to explained anchor selection.

In case you decide to use circle labels, results are similar, for similar reasons:

enter image description here

The code for previous results is:

\documentclass[tikz,border=2mm]{standalone}
\begin{document}
\begin{tikzpicture}[label distance=0.5cm, every label/.style={draw}]

\node[draw, circle, minimum size=3cm, thick,
      label={[name=1]1:a}, label={[name=2]2:a}, label={[name=3]3:a}]
    (c1) at (0,0) {};

\foreach \i/\j in {1/west,2/west,3/south west}
\draw (0,0)--(\i.\j) node[circle, fill=red, minimum size=2pt, inner sep=0pt]{};
\end{tikzpicture}

\begin{tikzpicture}[label distance=0.5cm, every label/.style={draw, circle}]

\node[draw, circle, minimum size=3cm, thick,
      label={[name=1]1:a}, label={[name=2]2:a}, label={[name=3]3:a}]
    (c1) at (0,0) {};

\foreach \i/\j in {1/west,2/west,3/south west}
\draw (0,0)--(\i.\j) node[circle, fill=red, minimum size=2pt, inner sep=0pt]{};
\end{tikzpicture}\end{document}

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.