TikZ - Desenho de Arco Recursivo

TikZ - Desenho de Arco Recursivo

Estou tentando fazer diagramas de Farey semelhantes aos vistos aqui (clique)ou a captura de tela da seguinte forma,

insira a descrição da imagem aqui

(fonte da imagem:Wikipédia)

Ou seja, eu gostaria de um exemplo daquele visto notopo da página 6. A partir daí, espero descobrir como fazer o resto. De qualquer forma, eu queria fazer isso usando o TikZ e esperava ter algumalgoritmo que poderia gerar essas imagens para n níveis de profundidade.

Aqui está minha tentativa de força bruta:

    \documentclass[tikz]{standalone}
    \begin{document}
    \begin{tikzpicture}[scale=12]
    \draw (0,0) -- (1,0);
    \draw (0,0) -- (0,.618);
    \draw (1,0) -- (1,.618);
    \draw (1,0) arc (0:180:.5);

    \draw [dotted] (0,0) -- (0,-.1) node[below]{$\frac{0}{1}$};
    \draw [dotted] (1,0) -- (1,-.1) node[below]{$\frac{1}{1}$};

    \draw (1,0) arc (0:180:.25);
    \draw [dotted] (.5,0) -- (.5,-.1) node[below]{$\frac{1}{2}$};
    \draw (.5,0) arc (0:180:.25);

    \draw (1,0) arc (0:180:1/6);
    \draw [dotted] (2/3,0) -- (2/3,-.1) node[below]{$\frac{2}{3}$};
    \draw (2/3,0) arc (0:180:1/12);

    \draw (1/3,0) arc (0:180:1/6);
    \draw [dotted] (1/3,0) -- (1/3,-.1) node[below]{$\frac{1}{3}$};
    \draw (1/2,0) arc (0:180:1/12);

    \end{tikzpicture}
    \end{document}

Devo admitir que sou um novato quando se trata de TikZ e de programação em LaTeX. Portanto, qualquer ajuda, por mais básica que seja, será apreciada. Obrigado.

Responder1

Não é diferente dos exemplos dados por outras línguas. Apenas alguns lugares onde a expansão precisa ser cuidada. Eu realmente não optei pelo código de golfe, mas parece funcionar. E fica mais fraco à medida que a profundidade da recursão aumenta.

\documentclass[tikz]{standalone}
\newcount\recurdepth
\begin{document}
\begin{tikzpicture}[scale=2]
\draw[style=help lines] (0,0) grid[step=0.1cm] (1,0.5);

\def\myrecur#1#2#3#4#5{
\recurdepth=#5
\ifnum\the\recurdepth>1\relax
  \advance\recurdepth by-1\relax
  \edef\tempnum{\number\numexpr#1+#3\relax}%a+b
  \edef\tempden{\number\numexpr#2+#4\relax}%c+d
  \pgfmathparse{\tempnum/\tempden}\edef\temp{\pgfmathresult}%(a+b)/(c+d)

  \node[below=\the\recurdepth*1pt,scale=0.1*\the\recurdepth]at({(\temp)*1cm},0){$\frac{\tempnum}{\tempden}$};
  \draw[ultra thin,opacity=\the\recurdepth/10] ({(\temp)*1cm},0) arc (180:0:{((#3/#4)-\temp)*0.5cm});
  \draw[ultra thin,opacity=\the\recurdepth/10] ({(\temp)*1cm},0) arc (0:180:{(\temp-(#1/#2))*0.5cm});
  \begingroup
    \edef\ttempup{\noexpand\myrecur{\tempnum}{\tempden}{#3}{#4}{\the\recurdepth}}
    \edef\ttempdown{\noexpand\myrecur{#1}{#2}{\tempnum}{\tempden}{\the\recurdepth}}
    \ttempup\ttempdown
  \endgroup
\fi
}

\myrecur{0}{1}{1}{1}{6}

\end{tikzpicture}
\end{document}

insira a descrição da imagem aqui

Responder2

Sem números:

\documentclass[tikz]{standalone}
\begin{document}
    \begin{tikzpicture}
        \draw [ultra thick] (-8,0) -- (8,0);
        \draw [ultra thick] (0,0) circle (8);
        \foreach \i in {0,1,2,3} {%
            \draw [ultra thick] (90*\i:8) arc (270+90*\i:180+90*\i:8);}
        \foreach \i in {0,1,...,7} {%
            \draw [very thick] (45*\i:8) arc (270+45*\i:135+45*\i:3.3);}
        \foreach \i in {0,1,...,15} {%
            \draw [thick] (22.5*\i:8) arc (270+22.5*\i:112.5+22.5*\i:1.6);}
        \foreach \i in {0,1,...,31} {%
            \draw [thin] (11.25*\i:8) arc (270+11.25*\i:101.25+11.25*\i:0.8);}
        \foreach \i in {0,1,...,63} {%
            \draw [ultra thin] (5.625*\i:8) arc (270+5.625*\i:95.625+5.625*\i:0.4);}
    \end{tikzpicture}
\end{document}

insira a descrição da imagem aqui

Responder3

Eu estava me perguntando a mesma coisa ontem nos comentários deesta respostasobre um assunto próximo. Para desenhos recursivos como este são (relativamente!) fáceis de fazer com linguagens intimamente relacionadas ao (La)TeX, mas externas a ele, como MetaPost ou Asymptote. Por exemplo, aqui está minha tentativa "rápida e suja" com MetaPost no diagrama Farey ilustrado na postagem original. Isso mostra como é natural com esta linguagem implementar um desenho recursivo:

input latexmp;
setupLaTeXMP(packages="amsmath", options = "12pt", textextlabel = enable, mode = rerun);

numeric u, m; 
u = 20cm; % scale
m = 8; % maximal denominator

% [a/b, c/d]: diameter, n: recursion level
def farey_diagram(expr a, b, c, d, n) = 
  draw halfcircle scaled ((c/d-a/b)*u) shifted (u*0.5[a/b,c/d], 0);
  if (n > 1) and (b+d <= m):
    label.bot("$\dfrac{" & decimal(a+c) & "}{"& decimal(b+d) & "}$", u*((a+c)/(b+d), 0));
    farey_diagram(a, b, a+c, b+d, n-1); farey_diagram(a+c, b+d, c, d, n-1);
  fi;
enddef;

beginfig(1);
  draw origin -- (u, 0);
  label.bot("$0$", origin); label.bot("$1$", (u, 0));
  % starting with 0/1 and 1/1; m levels of recursion needed
  farey_diagram(0, 1, 1, 1, m); 
endfig;
end.

insira a descrição da imagem aqui

Então, isso significa que devemos reverter melhor para programas externos como MetaPost ou Asymptote cada vez que precisarmos desenhar algo recursivamente? Seria uma surpresa, pois sei o quão poderosos são os pacotes (La)TeX como PSTricks, Tikz ou mfpic (aquele entre os três que uso regularmente para meu trabalho pessoal).

EDITARDepois de ler um pouco mais sobre diagramas e séries de Farey, tentei refinar meu código, permitindo apenas frações com denominadores menores ou iguais ao número de níveis de recursão. Assim, farey_diagram(0, 1, 1, 1, m)compõe os números da série Farey Fm (e somente eles) e desenha os semicírculos correspondentes.

Responder4

Uma resposta parcial: acho que isso produz as sequências corretamente. Precisa lualatex.

\documentclass[border=5]{standalone}
\usepackage{pgffor}
{\catcode`\%=11\gdef\pc{%}}
\directlua{
Rational = {}
Rational.__index = Rational

function Rational.new(p, q)
  local a, b, object
  a, b = p, q
  while b > 0 do
    a, b = b, a \pc b
  end
  object = {p=p/a, q=q/a}
  setmetatable(object, Rational)
  return object
end

function Rational:toString()
  return "" .. self.p .. "/" .. self.q
end

function Rational.__eq(P, Q)
  return (P.p == Q.p) and (P.q == Q.q)
end

function Rational.__add(P, Q)
  return Rational.new(P.p*Q.q + Q.p*P.q, P.q*Q.q)
end

function Rational.__sub(P, Q)
  return Rational.new(P.p*Q.q - Q.p*P.q, P.q*Q.q)
end

Sequence = {}
Sequence.__index = Sequence

function Sequence.new()
  local object = {data={}, n=0}
  setmetatable(object, Sequence)
  return object
end

function Sequence:get(i)
  return self.data[i]
end

function Sequence:append(v)
  table.insert(self.data, v)
  self.n = self.n + 1
end

function Sequence:toString()
  local s, i
  s = ""
  if self.n > 0 then
    s = s .. self.data[1]:toString()
    if self.n > 1 then
      for i = 2,self.n do
        s = s .. "," .. self.data[i]:toString()
      end
    end
  end
  return s
end

function farey_sequence(n)
  local f1, f2, t1, t2, i, j
  f1 = Sequence.new()
  f1:append(Rational.new(0,1))
  f1:append(Rational.new(1,1))
  if n > 1 then
    for i = 1,n do
      f2 = f1
      f1 = Sequence.new()
      for j = 1, f2.n-1 do
        t1 = f2:get(j)
        t2 = f2:get(j+1)
        f1:append(t1)
        if (t2-t1 == Rational.new(1, t1.q*t2.q)) and t1.q+t2.q <= n then 
          f1:append(Rational.new(t1.p+t2.p, t1.q+t2.q))
        end
      end
      f1:append(t2)
    end
  end
  return f1
end
}

\def\getfareysequence#1#2{%
  \edef#1{\directlua{tex.print(farey_sequence(#2):toString())}}%
}
\begin{document}
\begin{minipage}{4in}
\foreach \i in {1,...,8}{
 \getfareysequence\A{\i}
 $F_{\i}=\left\{\foreach \n/\d [count=\k] in \A {\ifnum\k>1,\fi\frac{\n}{\d}}\right\}$
\\[.5ex]
}
\end{minipage}
\end{document}

insira a descrição da imagem aqui

informação relacionada