[Tex/LaTex] Accuracy of calculations in TikZ with fixed point arithmetic

fptikz-pgftikz-trees

I want to build a tree which satisfies the following:

  1. It grows to the right.
  2. The first child grows at 0 degrees (subsequent children growing clockwise).
  3. All children nodes are in the same vertical, and the distance between consecutive nodes is always the same.

All in all, what I'd like to achieve is this:

enter image description here

Indeed, an easy way to code that is through

\documentclass{article}
\usepackage{tikz}
\tikzset{bcir/.style={circle,fill=black,
 minimum size=4pt,inner sep=0},every node/.style={bcir}}
\begin{document}
\begin{tikzpicture}[x=3cm,y=2mm]
\node (A) {};
\foreach \i in {0,...,8} \node at (1,-\i) {} edge (A);
\end{tikzpicture}
\end{document}

However, I tried an alternative approach, which I was expecting to produce the same results:

\documentclass{article}
\usepackage{tikz}
\usepackage{fp}
\usetikzlibrary{fixedpointarithmetic}
\tikzset{bcir/.style={circle,fill=black,
minimum size=4pt,inner sep=0},every node/.style={bcir}}

\begin{document}
\begin{tikzpicture}[fixed point arithmetic]  
\node {}
  child[grow=\g,level distance=\l cm] 
  foreach \i [evaluate={
     \k=tan(5)*\i;
     \g=-atan(\k);
     \l=3/cos(\g);
  }] in {0,...,13} {node {}};
\end{tikzpicture}  
\end{document}

Note that in the code above I have assumed that 1) the level distance of the first (horizontal) child is 3cm and 2) the second child grows at -5 degrees. With these two conditions and some basic trigonometry, one can calculate first the sibling distance between consecutive nodes and then the angle g and level distance l for any children node.

I believe my parametrization is correct; however some sibling angles/level distances are slightly off,

enter image description here

even though (following other answers) I used the fixed point arithmetic engine to try to improve the accuracy. Even replacing the trigonometric functions by the first terms of their Taylor series,

\begin{tikzpicture}[fixed point arithmetic]  
\node {}
  child[grow=\g,level distance=\l cm] 
  foreach \i [evaluate={
     \k=tan(5)*\i;
     \grad=\k-\k^3/3+\k^5/5-\k^7/7+\k^9/9;
     \g=-deg(\grad);
     \l=3/(1-\grad^2/2!+\grad^4/4!-\grad^6/6!);
  }] in {0,...,8} {node {}};
\end{tikzpicture}

the same problems are present (note that the number of nodes here has been chosen so as to ensure the series for atan does converge):

enter image description here

Is there something I could do to overcome these inaccuracy issues or is it an intrinsic TikZ problem that cannot be avoided? (assuming there is no flaw in my approach, as I think is the case).

Best Answer

I don't quite know why the maths seems to fail in this case (although I suppose I should), but it seems it is not a problem with the way TikZ/PGF does maths, it is something to do with way trees are constructed.

Unfortunately, I haven't been able work out what the problem is exactly, but the fact that the problem is not the accuracy of mathematical calculations per se, can be demonstrated by using the same calculations outside of a tree:

\documentclass[tikz, border=5]{standalone}
\tikzset{bcir/.style={circle,fill=black,
  minimum size=4pt,inner sep=0}, every node/.style={bcir}}

\begin{document}
\begin{tikzpicture}[every node/.style={bcir, anchor=center}]
\node {} child [grow=\g, level distance=\l cm] foreach \i [evaluate={%
  \k=tan(5)*\i; \g=-atan(\k); \l=3/cos(\g);}]
  in {0,...,13} { node {} };

\foreach \i [evaluate={%
  \k=tan(5)*\i; \g=-atan(\k); \l=3/cos(\g);}]
  in {0,...,13} { \draw [red] (0,0) -- (\g:\l) node [bcir,fill=red]{}; }
\end{tikzpicture}  
\end{document}

enter image description here

So there must be something else going on.

In any event I think you are making a lot of work out of something that could be done much more simply with a custom growth function.

The following shows an example of the grow via three points growth function from the trees library.

\documentclass[tikz, border=5]{standalone}
\usetikzlibrary{trees}
\tikzset{bcir/.style={circle,fill=black,
  minimum size=4pt,inner sep=0}, every node/.style={bcir}}

\begin{document}
\begin{tikzpicture}[grow via three points={%
  one child at (3,0) and two children at (3,0) and (3,-1/4)
}]
\node {} child foreach \i in {0,...,13} { node {} };
\end{tikzpicture}  
\end{document}

enter image description here