Das ürsprüngliche Problem ist, dass
start: (1, 2), mid: (3, 4), end: (5, 6)
vom .list
-Handler (bzw. der internen \foreach
-Schleife) in folgende Elemente aufgeteilt wird:
start: (1
,
2)
,
mid: (3
,
4)
,
end: (5
und
6)
.
Das geht beim ersten Element noch gut, weil es dem Argumentenformat #1: #2
noch entspricht; 2)
passt aber nicht mehr in #1: #2
rein. Dass \StrBetween
auch keine gescheiten Ergebnisse mehr auswirft, brauche ich glaube ich nicht mehr zu erwähnen.
Also, beschützen wir das doofe Komma eben und schmeißen nochmal ein Paar { }
außenrum:
\pgfkeys{/bonds/bond points={start: {(1, 2)}, mid: {(3, 4)}, end: {(5, 6)}}}
Fast! Die zwei Koordinaten werden nur als eine Einheit betracht (und die y
-Macros gar nicht definiert). Der Haken:
util/@@coord extractor/.list={\coord}
Wieviele Elemente in der Liste siehst du? Ich sehe nur einen: \coord
. Und \foreach
sieht auch nur einen: Es wird nur über ein Element iteriert: \coord
. \startx
wird dann definiert als
\def\startx{\coord}
was zu zwei Problemen führt:
-
\starty
ist selbstverständlich gar nicht definiert, aber theoretisch kannst du dann auch gleich
\draw (\startx) circle [radius=1cm] node {\startx};
schreiben.
-
Wenn mid:
und end:
bearbeitet wurde, expandiert \coord
zu 5, 6
, und da \startx
zu \coords
expandiert, expandiert es auch zu 5, 6
. Es werden also alle Kreise an der gleichen Stelle gezeichnet.
Bezugnehmend auf:
Wo ist das Problem bei der Benutzung von \StrBetween{#2}{(}{)}[\coord]
um mir eine Liste für den .list
handler zu erzeugen - ein Test des so erzeugten Makros \coord
in einem \foreach
Loop hat nämlich funktioniert und ich dachte beim .list
handler werkelt eben ein solcher \foreach
Loop im Hintergrund.
Ja, hinter .list
werkelt eine komplexe \foreach
-Loop, allerdings kennt das offizielle \foreach
eben die zwei Alternativen:
\foreach \var/\iab/\len in {Ele/men/t 1, Ele/men/t 2, …, Ele/men/t n}
und
\foreach \var/\iab/\len in \macroDasNachEinerExpansionEineListeDerElementeLiefert
Der .list
-Handler arbeitet nur mit der ersten Option.
Lösung: \coord
einmal (und da wir ja nur plain Zahlen haben könnten wir es theoretisch auch mehrmals) expandieren:
util/@@coord extractor/.list/.expand once=\coord
Aber: Warum denn so kompliziert?
Benutze doch direkt Keys start
, mid
und end
, um die Koordinaten zu speichern. (Wenn dir der Doppelpunkt als Trenner so wichtig ist, könntest du xstring
vorher auch drüber laufen lassen und alle :
durch =
austauschen, bevor es PGFkeys bearbeitet.
Ich vermeide auch, die etwas altbackenen /.store in
-Keys und verwende den besseren .initial
-Handler. Siehe dazu bitte auch die Fragen
auf TeX.sx.
Ein paar Styles dazu und man kann die Grafik schon beachtlich beeinflussen. (Bitte beachte, dass Kommas in den Koordinaten selbstverständlich immer noch beschützt werden müssen, wie ich das bei der Initialisierung auch gemacht habe.)
Code (original)
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{tikz}
\usepackage{xstring}
\newcounter{coordcounter}
\setcounter{coordcounter}{23}
\pgfkeys{
util/coord extractor/.style={
util/@coord extractor/.list={#1}
},
util/@coord extractor/.code args={#1: #2}{%
\def\tempcoordkey{#1}%
\StrBetween{#2}{(}{)}[\coord]%
\pgfkeys{
util/@@coord extractor/.list/.expand once=\coord,
bonds/counter/set={coordcounter}{23}
}%
},
util/@@coord extractor/.code={%
\pgfkeys{
/bonds/counter/step={coordcounter},
\savedpath/\tempcoordkey/\alph{coordcounter}={#1}
}%
},
bonds/counter/set/.code 2 args={\setcounter{#1}{#2}},
bonds/counter/step/.code={\stepcounter{#1}},
bonds/bond points/start/x/.store in={\startx},
bonds/bond points/start/y/.store in={\starty},
bonds/bond points/mid/x/.store in={\midx},
bonds/bond points/mid/y/.store in={\midy},
bonds/bond points/end/x/.store in={\endx},
bonds/bond points/end/y/.store in={\endy},
bonds/bond points/.code={%
\def\savedpath{/bonds/bond points}%
\pgfkeys{
util/coord extractor={#1}
}%
}
}
\begin{document}
\begin{tikzpicture}
\pgfkeys{/bonds/bond points={start: {(1, 2)}, mid: {(3, 4)}, end: {(5, 6)}}}
\draw (\startx, \starty) circle [radius=1cm] node {\startx, \starty};
\draw (\midx, \midy) circle [radius=2cm] node {\midx, \midy};
\draw (\endx, \endy) circle [radius=.5cm] node {\endx, \endy};
\end{tikzpicture}
\end{document}
Output (original)
Code
\documentclass[tikz]{standalone}
\newcommand*\bondset{\pgfqkeys{/bonds}}
\bondset{
bond points/start/.initial={(0,0)},
bond points/mid/.initial={(1,1)},
bond points/end/.initial={(2,2)}}
\tikzset{bonds/.code={\bondset{#1}}}
\newcommand*{\drawBond}[1][]{%
\begingroup
\bondset{#1}%
\draw[/bonds/every bond/.try, /bonds/start/.try] \pgfkeysvalueof{/bonds/bond points/start} circle [] node {start};
\draw[/bonds/every bond/.try, /bonds/mid/.try] \pgfkeysvalueof{/bonds/bond points/mid} circle [] node {mid};
\draw[/bonds/every bond/.try, /bonds/end/.try] \pgfkeysvalueof{/bonds/bond points/end} circle [] node {end};
\endgroup}
\begin{document}
\begin{tikzpicture}[radius=+1cm]
\drawBond[mid/.style={green, radius=.5cm}]
\end{tikzpicture}
\begin{tikzpicture}[bonds={every bond/.append style={radius=+1cm}}]
\drawBond[
bond points/mid=(45:1),
bond points/end=(45+90:1),
end/.style={red, radius=+.5cm}]
\end{tikzpicture}
\end{document}
Output