TikZ - Rekursives Bogenzeichnen

TikZ - Rekursives Bogenzeichnen

Ich versuche, Farey-Diagramme zu erstellen, die denen ähneln, die ich sehe hier (klick)oder den Screenshot wie folgt,

Bildbeschreibung hier eingeben

(Bildquelle:Wikipedia)

Ich hätte nämlich gern ein Beispiel von dem auf derzum Seitenanfang 6. Von dort aus hoffe ich, dass ich herausfinden kann, wie ich den Rest mache. Wie auch immer, ich wollte dies mit TikZ machen und hoffte, einigeAlgorithmus, der diese Bilder für n Ebenen tief erzeugen könnte.

Hier ist mein Brute-Force-Versuch:

    \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}

Ich muss zugeben, dass ich ein Neuling bin, wenn es um TikZ und die Programmierung in LaTeX geht. Daher wäre ich für jede Hilfe dankbar, egal wie einfach sie ist. Danke.

Antwort1

Es unterscheidet sich nicht von den Beispielen anderer Sprachen. Nur an einigen Stellen muss auf Erweiterungen geachtet werden. Ich habe mich nicht wirklich auf Code-Golf konzentriert, aber es scheint zu funktionieren. Und es wird schwächer, wenn die Rekursionstiefe zunimmt.

\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}

Bildbeschreibung hier eingeben

Antwort2

Ohne Zahlen:

\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}

Bildbeschreibung hier eingeben

Antwort3

Das Gleiche habe ich mich gestern gefragt in den Kommentaren vondiese Antwortzu einem nahen Thema. Denn rekursive Zeichnungen wie diese sind (relativ!) einfach mit Sprachen zu erstellen, die eng mit (La)TeX verwandt, aber außerhalb davon liegen, wie MetaPost oder Asymptote. Hier ist beispielsweise mein „schneller und schmutziger“ Versuch mit MetaPost auf dem im Originalbeitrag dargestellten Farey-Diagramm. Er zeigt, wie selbstverständlich es mit dieser Sprache ist, eine rekursive Zeichnung zu implementieren:

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.

Bildbeschreibung hier eingeben

Heißt das nun, dass wir jedes Mal, wenn wir etwas rekursiv zeichnen müssen, besser auf externe Programme wie MetaPost oder Asymptote zurückgreifen sollten? Das wäre eine kleine Überraschung, da ich weiß, wie leistungsfähig (La)TeX-Pakete wie PSTricks, Tikz oder mfpic (eines der drei Pakete, das ich regelmäßig für meine persönliche Arbeit verwende) sind.

BEARBEITENNachdem ich etwas mehr über Farey-Diagramme und -Reihen gelesen hatte, versuchte ich, meinen Code zu verfeinern, indem ich nur Brüche mit Nennern kleiner oder gleich der Anzahl der Rekursionsebenen zuließ. So farey_diagram(0, 1, 1, 1, m)setzte ich die Zahlen der Farey-Reihe Fm (und nur diese) und zeichnete die entsprechenden Halbkreise.

Antwort4

Eine Teilantwort: Ich denke, dies erzeugt die Sequenzen korrekt. Es braucht 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}

Bildbeschreibung hier eingeben

verwandte Informationen