![TikZ - Rekursives Bogenzeichnen](https://rvso.com/image/286351/TikZ%20-%20Rekursives%20Bogenzeichnen.png)
Ich versuche, Farey-Diagramme zu erstellen, die denen ähneln, die ich sehe hier (klick)oder den Screenshot wie folgt,
(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}
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}
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.
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}