4

I would like to point an arrow at specific digits in a variety of numbers in a variety of number formats in a variety of font sizes and it isn't an option to draw every arrow manually. I've pointed all the arrows at the first number for demonstration purposes, but I would like to be able to point at any digit in each number. Is there a way to position the arrow based on the place value? I generally compile using XeLaTeX.

\documentclass[12pt,twoside]{article}
\usepackage[hmargin=19mm,vmargin=13mm,includeheadfoot,headheight=27.6pt,headsep=4mm]{geometry}
\usepackage[usenames,dvipsnames]{xcolor}
\usepackage{tikz} \usepackage{tkz-euclide} \usetkzobj{all}
\usetikzlibrary{shadings,calc,positioning}
\usepackage{siunitx}
\sisetup{group-separator = {,},output-decimal-marker = {.}}
\usepackage{amsmath}
\usepackage{mathspec} \newfontfamily\myfont{Cambria}
\setallmainfonts{Cambria}
\setlength{\parindent}{0cm}
\usepackage{graphicx} \graphicspath{{Default/}}
\begin{document}
\begin{tikzpicture}[font=\fontsize{18}{18}\selectfont]
\node[left] at (0,0) {\fontsize{12}{12}\selectfont \textcolor{Gray}{1.}}; \node[right] at (0,0) {\num{976867695082.87}}; \draw[ultra thick,->] (0.35,-1) -- (0.35,-0.35); 
\node[left] at (0,-2.1) {\fontsize{12}{12}\selectfont \textcolor{Gray}{2.}}; \node[right] at (0,-2.1) {\num{9772.9216}}; \draw[ultra thick,->] (0.35,-3.1) -- (0.35,-2.45); 
\node[left] at (0,-4.2) {\fontsize{12}{12}\selectfont \textcolor{Gray}{3.}}; \node[right] at (0,-4.2) {\num{115698983.3302}}; \draw[ultra thick,->] (0.35,-5.2) -- (0.35,-4.55); 
\node[left] at (0,-6.3) {\fontsize{12}{12}\selectfont \textcolor{Gray}{4.}}; \node[right] at (0,-6.3) {\num{61074171.8288}}; \draw[ultra thick,->] (0.35,-7.3) -- (0.35,-6.65); 
\node[left] at (0,-8.4) {\fontsize{12}{12}\selectfont \textcolor{Gray}{5.}}; \node[right] at (0,-8.4) {\num{81872.56}}; \draw[ultra thick,->] (0.35,-9.4) -- (0.35,-8.75); 
\node[left] at (0,-10.5) {\fontsize{12}{12}\selectfont \textcolor{Gray}{6.}}; \node[right] at (0,-10.5) {\num{118010166.2449}}; \draw[ultra thick,->] (0.35,-11.5) -- (0.35,-10.85); 
\node[left] at (0,-12.6) {\fontsize{12}{12}\selectfont \textcolor{Gray}{7.}}; \node[right] at (0,-12.6) {\num{1036600250.575}}; \draw[ultra thick,->] (0.35,-13.6) -- (0.35,-12.95); 
\sisetup{group-separator = {.},output-decimal-marker = {,}}
\node[left] at (0,-14.7) {\fontsize{12}{12}\selectfont \textcolor{Gray}{8.}}; \node[right] at (0,-14.7) {\num{271528084.6175}}; \draw[ultra thick,->] (0.35,-15.7) -- (0.35,-15.05); 
\node[left] at (0,-16.8) {\fontsize{12}{12}\selectfont \textcolor{Gray}{9.}}; \node[right] at (0,-16.8) {\num{3591829.37023}}; \draw[ultra thick,->] (0.35,-17.8) -- (0.35,-17.15); 
\node[left] at (0,-18.9) {\fontsize{12}{12}\selectfont \textcolor{Gray}{10.}}; \node[right] at (0,-18.9) {\num{4735855358.70}}; \draw[ultra thick,->] (0.35,-19.9) -- (0.35,-19.25); 
\node[left] at (8.5,0) {\fontsize{12}{12}\selectfont \textcolor{Gray}{11.}}; \node[right] at (8.5,0) {\num{6162795621.24653}}; \draw[ultra thick,->] (8.85,-1) -- (8.85,-0.35); 
\node[left] at (8.5,-2.1) {\fontsize{12}{12}\selectfont \textcolor{Gray}{12.}}; \node[right] at (8.5,-2.1) {\num{95475.63}}; \draw[ultra thick,->] (8.85,-3.1) -- (8.85,-2.45); 
\node[left] at (8.5,-4.2) {\fontsize{12}{12}\selectfont \textcolor{Gray}{13.}}; \node[right] at (8.5,-4.2) {\num{18964906.93874}}; \draw[ultra thick,->] (8.85,-5.2) -- (8.85,-4.55); 
\node[left] at (8.5,-6.3) {\fontsize{12}{12}\selectfont \textcolor{Gray}{14.}}; \node[right] at (8.5,-6.3) {\num{424743070.9}}; \draw[ultra thick,->] (8.85,-7.3) -- (8.85,-6.65); 
\node[left] at (8.5,-8.4) {\fontsize{12}{12}\selectfont \textcolor{Gray}{15.}}; \node[right] at (8.5,-8.4) {\num{6886.7}}; \draw[ultra thick,->] (8.85,-9.4) -- (8.85,-8.75); 
\sisetup{group-separator = {\,},output-decimal-marker = {,}}
\node[left] at (8.5,-10.5) {\fontsize{12}{12}\selectfont \textcolor{Gray}{16.}}; \node[right] at (8.5,-10.5) {\num{7038.187}}; \draw[ultra thick,->] (8.85,-11.5) -- (8.85,-10.85); 
\node[left] at (8.5,-12.6) {\fontsize{12}{12}\selectfont \textcolor{Gray}{17.}}; \node[right] at (8.5,-12.6) {\num{944938652566.421}}; \draw[ultra thick,->] (8.85,-13.6) -- (8.85,-12.95); 
\node[left] at (8.5,-14.7) {\fontsize{12}{12}\selectfont \textcolor{Gray}{18.}}; \node[right] at (8.5,-14.7) {\num{2927184.8}}; \draw[ultra thick,->] (8.85,-15.7) -- (8.85,-15.05); 
\node[left] at (8.5,-16.8) {\fontsize{12}{12}\selectfont \textcolor{Gray}{19.}}; \node[right] at (8.5,-16.8) {\num{8376.65}}; \draw[ultra thick,->] (8.85,-17.8) -- (8.85,-17.15); 
\node[left] at (8.5,-18.9) {\fontsize{12}{12}\selectfont \textcolor{Gray}{20.}}; \node[right] at (8.5,-18.9) {\num{235261584236.51}}; \draw[ultra thick,->] (8.85,-19.9) -- (8.85,-19.25); 
\end{tikzpicture}
\clearpage
\end{document}

Point arrows at digits

8
  • If using a monospaced font was an option, this would be easier I think, but that is probably out of the question? (Completely unrelated: if you're interested in a slightly more concise way of making that, excluding arrows: gist.github.com/TorbjornT/42d57c860a91f60f1db3b2cb2c442e8d) Commented Apr 19, 2020 at 19:54
  • @freemath, just posted an answer, now I see the siunitx stuff, will think about it.
    – BambOo
    Commented Apr 19, 2020 at 20:06
  • Well, it does not work with siunitx in its current form. Probably due to the expansion order. I searched a bit but I think we need a tex guru to solve this.
    – BambOo
    Commented Apr 19, 2020 at 20:58
  • @TorbjørnT, would you have an idea on how to expand a \num{xxx} to use it as an argument ?
    – BambOo
    Commented Apr 19, 2020 at 21:08
  • @BambOo No, sorry. Commented Apr 19, 2020 at 21:09

2 Answers 2

3

I am not overly sure this answers your exact problem, but here is my proposal using the xstring and tikzmark packages.

Basically what the \addbelowarrow does is

  • Take a string str and a character position index
  • Split str in three strings (str(1:index-1), str(index), str(index+1:end), sorry for the matlab notation)
  • Add a tikz mark to the character a position index
  • Print the string character as if nothing had happened
  • Draw a vertical arrow pointing towards the character at index

I believe there should much better alternatives but this is the only solution I could come up with.

Note that it should be compiled twice to work

enter image description here

\documentclass{article}
\usepackage{xstring}
\usepackage{tikz}
\usetikzlibrary{tikzmark}

\newcommand{\addbelowarrow}[2]{%
    \pgfmathtruncatemacro{\charbefore}{#2-1}
    \pgfmathtruncatemacro{\charafter}{#2+1}
    \StrMid{#1}{1}{\charbefore}%
    \tikzmarknode{tempnode}{\StrChar{#1}{#2}}%
    \StrMid{#1}{\charafter}{100}%
    \tikz[overlay,remember picture]{\draw[stealth-] (tempnode) --++ (0,-2em);}
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\begin{itemize}
    \item  123456789
    \item  \addbelowarrow{123456789}{4}
    \item  \addbelowarrow{123456789}{4}
    \item  \addbelowarrow{123456789}{2}
    \item  \addbelowarrow{123456789}{7}
    \item  \addbelowarrow{123456.789}{7}
\end{itemize}

\end{document}
2

This is not a too serious answer. Like BambOo's nice answer it uses xtring. However, it typesets the numbers with siunitx. One can reconstruct the horizontal position of the digits for a specific SI setting. This means that if you change your settings, the stuff below won't most likely work properly unless you change the pgf functions accordingly. You can say

 \path (0,0) node[name=test1,si node={76867695082.87}];

to create a node. The digit positions are then stored in coordinates test1-digit1 and so on.

\documentclass{article}
\usepackage{siunitx}
\usepackage{tikz}
\sisetup{group-separator = {,},output-decimal-marker = {.}}
\usepackage{xstring}
\pgfmathdeclarefunction{punctuationcontribution}{2}{\begingroup
\pgfmathparse{(#2<5 ? 0 : int((#1-Mod(#2,3)+3*(Mod(#2,3)==2))/3)*2.7778)}%
\pgfmathsmuggle\pgfmathresult
\endgroup}
\pgfmathdeclarefunction{simarkpos}{2}{\begingroup
\pgfmathsetmacro{\digitwidth}{width("\num{1}")}%
\pgfmathsetmacro{\dotwidth}{width("\num{1.2}")-2*\digitwidth}%
\StrPosition{#1}{.}[\dotpos]%
\ifnum#2=\dotpos
 \pgfmathparse{punctuationcontribution(#2,\dotpos)+(#2-1)*5+2.7778/2}%
\else
 \ifnum#2<\dotpos
  \pgfmathparse{punctuationcontribution(#2,\dotpos)+(#2-1)*5+5/2}%
 \else
  \pgfmathparse{punctuationcontribution(\dotpos-1,\dotpos)+(#2-1)*5+2.7778+5/2}%
 \fi
\fi
\pgfmathsmuggle\pgfmathresult
\endgroup}
\tikzset{measure si node/.code={%
\StrLen{#1}[\mylen]%
\foreach \XX in {1,...,\mylen}
{\pgfmathsetmacro{\mydist}{simarkpos("#1",\XX)}
\path ([xshift=\mydist pt]\tikzlastnode.south west) coordinate
(\tikzlastnode-digit \XX);
}},
si node/.style={inner sep=0pt,node contents={\num{#1}},
append after command={[measure si node={#1}]}}}
\begin{document}
\begin{tikzpicture}
 \path (0,0) node[name=test1,si node={76867695082.87}];
 \foreach \X in {1,...,13}
 {\draw[thin,stealth-] (test1-digit \X) -- ++ (0,-0.25)
 node[below,font=\tiny\sffamily]{\X};}
 \path (4,0) node[name=test2,si node={976867695082.87}];
 \foreach \X in {1,...,14}
 {\draw[thin,stealth-] (test2-digit \X) -- ++ (0,-0.25)
 node[below,font=\tiny\sffamily]{\X};}
 \path (8,0) node[name=test3,si node={1976867695082.87}];
 \foreach \X in {1,...,15}
 {\draw[thin,stealth-] (test3-digit \X) -- ++ (0,-0.25)
 node[below,font=\tiny\sffamily]{\X};}
\end{tikzpicture}
\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .