# `arc`
Der `arc`-Path-Operator von TikZ ist bekanntermaßen etwas unflexibel, da er – abgesehen von den Radien – nur mit Start-, End- und Delta-Winkeln etwas anfangen kann.
# `\pgfpatharcto`
PGF selbst bietet da noch etwas mehr, hier passt das Macro `\pgfpatharcto`, das im [PGF manual](http://texdoc.net/texmf-dist/doc/generic/pgf/pgfmanual.pdf) auf Seite 892 geklärt wird.
Neben den Radien (`#1`, `#2`) benötigt man noch die Rotation `#3` sowie zwei Flags (`#4`, `#5`) und den Zielpunkt `#6`. Die Rotation ist nur relevant, falls man unterschiedliche Radien verwendet (nicht am Rad drehen ;)).
## Flags und Rotation
Die Flags sind aber selbst im einfachen Fall relevant, da man für einen gegeben Radius vier Kreisbögen konstruieren kann, die an einem Punkt starten und an einem anderen Punkt enden, nämlich linksrum/rechtsrum (das ist der `counterclockwise flag`, `#5`) und innenrum/außenrum (`large arc flac`, `#4`). Da TikZ mathematisch positiv immer gegen den Uhrzeigersinn rechnet, habe ich dementsprechend auch den Key `arc ccw` mit `1` initialisiert; da man vermutlich eher an den inneren Kreisbogen denkt, wird `arc large` mit `0` initialisiert.
## Ungenauigkeit
Eine kleine *Warnung*, die ich aus dem Manual zitieren möchte, vorweg (Überstzung von mir):
> *Warning:* The internal computations necessary for this command are numerically very unstable. In
particular, the arc will not always really end at the `<target coordinate>`, but may be off by up to several points. A more precise positioning is currently infeasible due to TeX’s numerical weaknesses. The only case it works quite nicely is when the resulting angle is a multiple of 90°.
> ----
> *Achtung:* Die internen Berechnungen, die für diesen Befehl nötig sind, sind numerisch instabil.
> Im Besonderen wird der Bogen nicht immer wirklich am spezifierten Endpunkt enden, sondern um einige Punkte daneben liegen. Eine präzisere Positionierung ist derzeit aufgrund TeX’s numerischer Schwäche nicht erreichbar. Der einzige Fall, bei dem das sehr gut funktioniert, ist, wenn der Winkel ein Vielfaches von 90 Grad ist.
## Implementation
Beachte auch bitte meine Implementierung eher als Proof-of-Concept.
Die Syntax ist relativ fest vorgegeben (die `[ ]` sind im Gegensatz zur üblichen LaTeX-Konvention Pflicht).
Ich habe mich dazu entschlossen, nicht den bereits vorhandenen `arc`-Path-Operator neu zu definieren, weil der Code dann auch noch unterscheiden muss zwischen dem klassichen Bogen mit den `* angle` angle`-Optionen und dem hier benutzten.
benutzten. (Ja, theoretisch sind natürlich Kombination wie „der Startwinkel, der Radius und der Endpunkt”, aber das kann eben keiner von beiden ausrechnen.)
Es ist quasi ein komplett unabhängiger Path-Operator, der statt `arc` eben `arc*` heißt, auch `arc to` heißt (`arcto` ginge auch); er verwendet eben falls die Keys `radius`, `x radius` und `y radius` verwendet sowie den eventuell definierten `every arc`-Style ausführt.
Die Zeilen
\iftikz@shapeborder
\edef\tikz@moveto@waiting{\tikz@shapeborder@name}%
\fi
sind dafür da, den Pfad nach dem Endpunkt fortzusetzen, falls es arc`-Style.
### Nodes als Ziel
Falls man eine Node ist. als Endpunkt auswählt und von dort eine Linie weiter zeichnen will, also zum Beispiel
\node (B) {Bogen-Ziel};
\draw (a) arc to[] (B) -- (a);
startet die Linie nicht am Zentrum von B (wo der Bogen endet), sondern dort wo er auch bei `(B) -- (a)` starten würde. Dies ist durch die Zeilen
\iftikz@shapeborder
\edef\tikz@moveto@waiting{\tikz@shapeborder@name}%
\fi
sichergestellt.
(Das ist in meinem Beispiel im Prinzip auch der Fall, aber da es eh eine `coordinate` ist, ist das nicht von Relevanz.)
Es fehlt außerdem ein ordentlicher „Timer”, sprich eine Funktion, die eine `pos`-Angabe von Nodes in eine Platzierung entlang des Pfades umrechnet. Dies ist beim originalen `arc`-Path-Operator in der stabilen PGF/TikZ-Version allerdings auch nicht der Fall (und ### Timer
In allen Version bis auf der `2.10-cvs`-Version wird mir bei Bögen auch etwas zu viel zum Darüber-Nachdenken). Als als Ersatz der Timer der Linie `--` verwendet. Bei der CVS-Version wird der Timer der Linie (`--`) verwendet, die Nodes und Coordinates werden also entlang der direkten Verbindung der beiden Punkte platziert.
Die [CVS-Version](http://texwelt.de/wissen/fragen/1184/wo-kann-ich-die-neueste-version-von-pgftikz-herunterladen) von TikZ beinhaltet bereits einen (doch nicht so simplen) Timer für den `arc`-Path-Operator; da `\pgfpatharcto` intern aber auch ein `\pgfpath*`-Macro verwendet, das eben auch von `arc` verwendet wird, wäre es theoretisch nicht so kompliziert, auf den Timer des `arc`s zurückgegriffen, wobei ich hier aber ordentlich geschummelt habe und die notwendigen Werte aus dem Scratch-Macro `\pgf@marshal` herausgeholt, die zu meinem Glück auch zu verwenden, wenn man noch an die Daten käme, die es berechnet hat.
Das lässt sich nicht so einfach reinpfriemeln ohne `\pgfpatharcto` auseinander zu nehmen oder irgendwelche Tricks anzuwenden.
die richtigen sind. :D
### Koordinaten-Systeme
Des Weiteren wird in PGF/TikZ zwischen Canvas-Koordinaten (mit Einheiten) und `xy`-Koordinaten (ohne Einheiten) unterschieden. Wenn ich das richtig sehe, versteht `\pgfpatharcto` nur Canvas-Koordinaten. Canvas-Koordinaten.
Ich habe mir erlaubt, einheitslose Radiusangaben ins `xy`-System zu schmeißen und die Längen der Basisvektoren als Radien für `\pgfpatharcto` zu verwenden. Das wird so oder so ähnlich auch an anderen Stellen verwendet, wobei dann aber direkt auf passendere PGF-Macros zurückgegriffen wird. Solange du allerdings das `xy`-System nicht in Relation zum Canvas-System drehst, sollten keine allzu überraschende Ergebnisse herauskommen. (Ich garantiere aber sicherheitshalber für nichts.)
## Download
Der Code ist in die [`tikzlibrary.qrr.arc.code.tex`](https://github.com/Qrrbrbirlbel/pgf/blob/master/tikzlibraryqrr.arc.code.tex)-Library ausgelagert, die entsprechend mit
\usetikzlibrary{qrr.arc}
geladen werden muss.
## Code
\documentclass[tikz,convert=false]{standalone}
\tikzset{
arc/ccw/.initial=1,
arc/large/.initial=0,
arc ccw/.style={/tikz/arc/ccw=1},
arc cw/.style={/tikz/arc/ccw=0},
arc large/.style={/tikz/arc/large=1},
arc small/.style={/tikz/arc/large=0},
arc rotation/.initial=0
}
\makeatletter
\def\tikz@arcA rc{\pgfutil@ifnextchar*%
{\expandafter\tikz@flush@moveto\expandafter\tikz@arcB@opt\pgfutil@gobble}
{\tikz@flush@moveto\tikz@arc@cont}}
\def\tikz@arcB@opt[#1]{%
\def\tikz@arcB@options{#1}
\tikz@do@@arcB}
\def\tikz@do@@arcB{%
\pgfutil@ifnextchar n{\tikz@collect@label@onpath\tikz@do@@arcB}
{\pgfutil@ifnextchar c{\tikz@collect@coordinate@onpath\tikz@do@@arcB}
{\tikz@scan@one@point\tikz@do@arcB}}}
\def\tikz@do@arcB#1{%
\edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}
\tikz@make@last@position{#1}%
\edef\tikz@timer@end{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
\iftikz@shapeborder
\edef\tikz@moveto@waiting{\tikz@shapeborder@name}%
\fi
\begingroup
\tikzset{every arc/.try}%
\expandafter\tikzset\expandafter{\tikz@arcB@options}%
\pgfmathparse{\pgfkeysvalueof{/tikz/x radius}}%
\let\tikz@arc@x\pgfmathresult
\ifpgfmathunitsdeclared
\edef\tikz@arc@x{\tikz@arc@x pt}%
\else
\pgf@process{\pgfpointxy{\tikz@arc@x}{0}}%
\pgfmathveclen@{\pgf@x}{\pgf@y}%
\edef\tikz@arc@x{\pgfmathresult pt}%
\fi
\pgfmathparse{\pgfkeysvalueof{/tikz/y radius}}%
\let\tikz@arc@y\pgfmathresult
\ifpgfmathunitsdeclared
\edef\tikz@arc@y{\tikz@arc@y pt}%
\else
\pgf@process{\pgfpointxy{0}{\tikz@arc@y}}%
\pgfmathveclen@{\pgf@x}{\pgf@y}%
\edef\tikz@arc@y{\pgfmathresult pt}%
\fi
\pgfpatharcto{\tikz@arc@x}{\tikz@arc@y}
{\pgfkeysvalueof{/tikz/arc rotation}}{\pgfkeysvalueof{/tikz/arc/large}}
{\pgfkeysvalueof{/tikz/arc/ccw}}{#1}%
\endgroup
\let\tikz@timer=\tikz@timer@line
\tikz@scan@next@command
}
\makeatother
\documentclass[tikz,convert,png={size=600}]{standalone}
\usetikzlibrary{qrr.arc}
\begin{document}
\begin{tikzpicture}[ultra thick,dot/.style={label={#1}}]
\coordinate[dot=below left:$a$] (a) at (0,0);
\coordinate[dot=above right:$b$] (b) at (2,3);
\tikzset{nodes={circle,fill=white, fill opacity=.9, text opacity=1, inner sep=+0pt, sloped, allow upside down}}
\draw[blue] (a) arc*[radius arc to[radius = 3cm] node[near start] {.25} node {.5} node[near end] {.75} (b);
\draw[red] (a) arc*[radius arc to[radius = 3cm, arc cw] node[near start] {.25} node {.5} node[near end] {.75} (b);
\draw[blue!50] (a) arc*[radius arc to[radius = 3cm, arc large] node[near end, black] start] {.25} node {.5} node[near end] {.75} (b);
\draw[red!50] (a) arc*[radius arc to[radius = 3cm, arc large, arc cw] node[near start] {.25} node {.5} node[near end] {.75} (b);
\fill[radius=2pt] (a) circle[] (b) circle[];
\end{tikzpicture}
\begin{tikzpicture}
\path[fill=blue!50!black] (0,0) arc*[radius=1cm] (1,2) arc*[radius=2.5cm, arc cw] (0,0);
\end{tikzpicture}
\end{document}
## Resultat
![alt text][1]
![alt text][2]
[1]: http://texwelt.de/wissen/upfiles/de1490-0_1.png
[2]: http://texwelt.de/wissen/upfiles/de1490-1.pnghttp://texwelt.de/wissen/upfiles/de1490-0_4.png