Holen Sie sich die Ausgabe von foreach statt foreach selbst

Holen Sie sich die Ausgabe von foreach statt foreach selbst

Ich möchte die Ausgabe des folgenden Makros in einer Variablen speichern:

\foreach \m in {1,...,9}{\csname h\m \endcsname};

Ich habe versucht:

\def\lkj{
  \foreach \m in {1,...,9}{\csname h\m \endcsname};
}

Dies funktioniert nicht, da das Makro selbst gespeichert wird und nicht die Ausgabe, die es erzeugt.

Kann mir jemand helfen, herauszufinden, wie ich die Ausgabe in einer Variablen speichern kann?


Erklärung dessen, was ich erreichen möchte

1 Minimales Arbeitsbeispiel

\documentclass{standalone}
\usepackage{xargs,tikz}
\usetikzlibrary{decorations.markings,hobby}

\tikzset{
  mark pos/.style args={#1(#2)}{
    postaction={
      decorate,
      decoration={
        markings,
        mark=at position #1 with \coordinate (#2);
      }
    }
  }
}

\newcommandx*\arccal[6][6]{%
  \draw[#6,domain=#5] plot ({#1+#3*cos(\x)}, {#2+#4*sin(\x)});
}

\foreach \m in {1,...,9}{
  \expandafter\xdef\csname h\m \endcsname{mark pos=0.\m(m\m),}
}

\def\lkj{
  \foreach \m in {1,...,9}{\csname h\m \endcsname};
}

\begin{document}
\begin{tikzpicture}

\arccal{-2.8}{0}{0.6}{1.2}{270:90}[samples=50,ultra thick,
  mark pos=0.05(w1),
  mark pos=0.1(w2),
  mark pos=0.15(w3),
  mark pos=0.2(w4),
  mark pos=0.25(w5),
  mark pos=0.3(w6),
  mark pos=0.35(w7),
  mark pos=0.4(w8),
  mark pos=0.45(w9),
  mark pos=0.5(w10),
  mark pos=0.55(w11),
  mark pos=0.6(w12),
  mark pos=0.65(w13),
  mark pos=0.7(w14),
  mark pos=0.75(w15),
  mark pos=0.8(w16),
  mark pos=0.85(w17),
  mark pos=0.9(w18),
  mark pos=0.95(w19),
];
\draw[ultra thick] plot[smooth] coordinates {(w19)(w18)(w17)(w16)(w15)(w14)(w13)(w12)(w11)(w10)(w9)(w8)(w7)(w6)(w5)(w4)(w3)(w2)(w1)};

\end{tikzpicture}
\end{document}

2 Kommentar

Ich habe einen Tikz-Stil namens „Mark Pos“, der verwendet wird, um Koordinaten durch mit „Plot“ erstellte Linien zu platzieren.

Es gibt bestimmte Fälle, in denen ich „plot[smooth]“ oder „plot[smooth cycle]“ verwende, um Formen zu erstellen, die bestimmte halbkreisförmige Formen haben, die in verschiedenen Mustern reibungslos verwaltet/geschlossen werden müssen.

Dann muss ich eine Reihe von Koordinaten definieren, damit es in die von mir gewünschte Richtung geht. In diesem Fall verwende ich eine Gleichung, die kreisförmige/elliptische Formen bildet und verwende „Position markieren“, um die Koordinaten festzulegen.

In manchen Fällen muss ich eine beträchtliche Anzahl an Koordinaten definieren, um eine ausreichend homogene Kurve zu bilden. Deshalb wollte ich eine Schleife mit „foreach“ erstellen, um diese schnell zu erstellen, ohne jede einzelne Koordinaten manuell definieren zu müssen.

Ich muss die Ausgabe des foreach-Makros in ein „\draw[x]“ einfügen, mit dem Rohmakro selbst geht das nicht.


Danke.


Beispiel, das ich mit Qrrbrbirlbel kommentiert habe

1 Fall eins: Was ich jetzt mit Qrrbrbirlbels Hilfe erreichen kann

\newcommandx*\arccalpath[6][6]{%
  \path[#6,domain=#5] plot ({#1+#3*cos(\x)}, {#2+#4*sin(\x)});
}

\arccalpath{-3}{0}{0.9}{1.2}{90:-90}[samples=50,ultra thick,
  mark positions={0.05}{z}];
\arccalpath{-2.8}{0}{0.6}{1.2}{270:90}[samples=50,ultra thick,
  mark positions={0.05}{w}]

\draw[ultra thick] plot[smooth,samples at={19,...,1}] (z\x);
\draw[ultra thick] plot[smooth,samples at={19,...,1}] (w\x);

Produziert: Bildbeschreibung hier eingeben

2 Fall zwei: Was ich erreichen möchte, ohne jedoch alle diese Punkte (z1, z2, z3...) in die Plot-Koordinaten eingeben zu müssen.

\newcommandx*\arccalpath[6][6]{%
  \path[#6,domain=#5] plot ({#1+#3*cos(\x)}, {#2+#4*sin(\x)});
}

\arccalpath{-3}{0}{0.9}{1.2}{90:-90}[samples=50,ultra thick,
  mark positions={0.05}{z}];
\arccalpath{-2.8}{0}{0.6}{1.2}{270:90}[samples=50,ultra thick,
  mark positions={0.05}{w}]

\draw[ultra thick] plot[smooth cycle,samples at={19,...,1}] coordinates
{(w19)(w18)(w17)(w16)(w15)(w14)(w13)(w12)(w11)(w10)(w9)(w8)(w7)(w6)(w5)(w4)(w3)(w2)(w1)(z19)(z18)(z17)(z16)(z15)(z14)(z13)(z12)(z11)(z10)(z9)(z8)(z7)(z6)(z5)(z4)(z3)(z2)(z1)};

Produziert: Bildbeschreibung hier eingeben

Antwort1

Ich würde das anders angehen.

Mehrere Markierungen in einem festen Abstand können mit der Syntax platziert werden mark=between positions … and … step … with …. Das Handbuch erklärt alledie DetailsDer Wert des /pgf/decoration/mark info/sequence numberSchlüssels stellt einen inkrementierenden Zähler dar.


Darüber hinaus stelle ich einen arccalStil bereit, den Sie auf einem TikZ-Pfad verwenden können, der nur zwei Argumente verwendet: den Mittelpunkt und die Radien im TikZ-Format <x> and <y>.

Das dritte TikZ-Bild zeichnet den elliptischen Bogen als elliptischen Bogen statt als Diagramm.

Das letzte Bild verwendet die markingsBibliothek nicht, sondern zeichnet nur zwei Bögen, den zweiten mit unterschiedlichen Winkeln. Wenn Sie die Bögen wirklich um einen Teil der Gesamtlänge des Bogens kürzen müssen, ist der Ansatz etwas komplizierter (die Gesamtlänge wird nur vom Dekorationsmodul von PGF/TikZ bereitgestellt und ist nicht einfach extrahierbar), aber immer noch besser, als Dutzende von Markierungen zu platzieren und eine Linie durch sie zu ziehen.


es gibt auchschönere Wegeum Bögen um einen Mittelpunkt zu zeichnen, aber das ist für Ihre Frage nicht relevant.

Code

\documentclass{standalone}
\usepackage{xargs,tikz}
\usetikzlibrary{decorations.markings}
\tikzset{
  mark positions/.style 2 args={
    postaction=decorate,
    decoration={
      name=markings, % PGFMath isn't precise, cheat with 1-0.001
      mark=between positions #1 and 1-0.001 step #1 with \coordinate
           (#2\pgfkeysvalueof{/pgf/decoration/mark info/sequence number});}}}
\newcommandx*\arccal[6][6]{%
  \draw[#6,domain=#5] plot ({#1+#3*cos(\x)}, {#2+#4*sin(\x)});
}
\tikzset{arccal/.style n args=2{insert path={plot([shift={(#1)}]\x:#2)}}}
\begin{document}
\begin{tikzpicture}
\arccal{-2.8}{0}{0.6}{1.2}{270:90}[
  samples=50, ultra thick,
  mark positions={0.05}{w}
];
\draw[thick, green] plot[smooth, samples at={19, ..., 1}] (w\x);
\end{tikzpicture}

\begin{tikzpicture}
\draw[
  ultra thick, samples=50, domain=270:90,
  mark positions={0.05}{w}, arccal={-2.8, 0}{.6 and 1.2}];
\draw[thick, green] plot[smooth, samples at={19, ..., 1}] (w\x);
\end{tikzpicture}

\begin{tikzpicture}
\draw[ultra thick, shift={(-2.8, 0)}, mark positions={0.05}{w}]
  (270:.6 and 1.2) arc[start angle=270, end angle=90, x radius=.6, y radius=1.2];
\draw[thick, green] plot[smooth, samples at={19, ..., 1}] (w\x);
\end{tikzpicture}

\begin{tikzpicture}
\draw[ultra thick, shift={(-2.8, 0)}]
  (270:.6 and 1.2) arc[start angle=270, end angle= 90, x radius=.6, y radius=1.2];
\draw[thick, green, shift={(-2.8, 0)}]
  (255:.6 and 1.2) arc[start angle=255, end angle=105, x radius=.6, y radius=1.2];
\end{tikzpicture}
\end{document}

Ausgabe

Bildbeschreibung hier eingeben


So wie ich das sehe, möchten Sie Bögen zwischen den Schnittpunkten kombinieren.

Hier sind drei Ansätze, die alle die intersectionsBibliothek verwenden, um den Schnittpunkt zwischen den beiden Pfaden zu finden, die die Bögen/Halbellipsen bilden.

Die erste verwendet die Syntax calcder Bibliothek, let … inum den Winkel der Schnittpunkte zu den Mittelpunkten der Ellipsen für einen anderen Satz von arcs zu berechnen. Die Koordinaten m1und m2werden verwendet, um dieXRadius der Ellipsen im Canvas-Koordinatensystem, ohne die Transformationen selbst durchführen zu müssen.

Der zweite verwendet die ext.paths.arctoBibliothek meinestikz-extPaketdas es erlaubt, einen Bogen zu zeichnenZuein Punkt, die Winkel werden von PGF/TikZ berechnet.

Die dritte Lösung verwendet die spath3Bibliothek, die es ermöglicht, Pfade an Kreuzungen mit anderen Pfaden aufzuteilen. Wir müssen nur angeben, welche Komponenten der aufgeteilten Pfade gezeichnet werden sollen.


Da die mathematischen Auswertungen der Lösungen 1 und 2 nicht sehr präzise sind, würden beim Schließen der Pfade störende Artefakte auftreten:
Bildbeschreibung hier eingeben

Dies kann durch die Verwendung spath3des adjust and closeSchlüssels behoben oder durch die Verwendung ausgeblendet werden line join=round.

Insgesamt bevorzuge ich diese arc toAnsätze, weil

  • Der calcAnsatz verwendet viele manuelle Berechnungen, aber auch, weil die acosFunktion nicht eindeutig ist (zwei Winkel für einen Wert) und dies Anpassungen erfordert und
  • Für die spath3Lösung müssen Sie die Komponenten angeben, was schwierig werden kann, da Bögen aus bis zu vier Bézierkurven (die jeweils einer Komponente entsprechen) konstruiert werden.

So oder so, im folgenden Code werden alle Lösungen präsentiert. Ich verwende auchmeine Antwortsoll arc starts=after movetodas Zeichnen von Bögen um einen Mittelpunkt erleichtern.

Code

\documentclass[border=5pt]{standalone}
\usepackage{tikz}
%% https://tex.stackexchange.com/a/123189
\usepackage{etoolbox}
\makeatletter
\patchcmd{\tikz@arc@opt}{\xdef}{\tikz@arc@do\xdef}{}{}\let\tikz@arc@do\relax
\tikzset{arc starts/.cd,.is choice, at last point/.code=\let\tikz@arc@do\relax,after moveto/.code=\tikz@arc@do@\pgfpathmoveto,after lineto/.code=\tikz@arc@do@\pgfpathlineto}
\def\tikz@arc@do@#1{\def\tikz@arc@do{\tikz@@@parse@polar{\tikz@arc@do@@#1}(\tikz@s:\pgfkeysvalueof{/tikz/x radius} and \pgfkeysvalueof{/tikz/y radius})}}
\def\tikz@arc@do@@#1#2{#1{\pgfpointadd{#2}{\tikz@last@position@saved}}}
\makeatother

\usetikzlibrary{intersections} % solutions 1, 2, 3
\usetikzlibrary{
  calc,            % solution 1
  ext.paths.arcto, % solution 2
  spath3           % solutions (1, 2b,) 3
}
\tikzset{cycle/.style=/tikz/spath/adjust and close}
\begin{document}

%%% 1. calc (doing our own math)
\begin{tikzpicture}[
  arc starts=after moveto,
  e1/.style={x radius=.6, y radius=1.2},
  e2/.style={x radius=.9, y radius=1.2},
  label position=center, line join=round,
]
% the coordinate m1 and m2 are used to find the x radius in the canvas (w/ units)
\path[name path=e1] (-2.8, 0) coordinate (c1)
  arc[start angle=90, delta angle= 180, e1] coordinate[midway] (m1);
\path[name path=e2] (-3.0, 0) coordinate(c2)
  arc[start angle=90, delta angle=-180, e2] coordinate[midway] (m2);

\draw[
  ultra thick, arc starts=at last point,
  name intersections={of=e1 and e2}]
  % work in the coordinate system of the first ellipse:
  [shift=(c1), e1]
  let \p0=(intersection-1), \p1=(m1), \n0={180-acos(\x0/\x1)} in
   (intersection-1) arc[start angle=\n0, end angle=360-\n0]
  % work in the coordinate system of the second ellipse:
  [shift=(c2), e2]
  let \p0=(intersection-2), \p1=(m2), \n0={-acos(\x0/\x1)} in
   arc[start angle=\n0, end angle=-\n0]
   [cycle];
\end{tikzpicture}

%%% 2a. arc to + round line join
\begin{tikzpicture}[
  arc starts=after moveto, line join=round,
  e1/.style={x radius=.6, y radius=1.2},
  e2/.style={x radius=.9, y radius=1.2},
]
\path[name path=e1] (-2.8, 0) arc[start angle=90, delta angle= 180, e1];
\path[name path=e2] (-3.0, 0) arc[start angle=90, delta angle=-180, e2];

\draw[name intersections={of=e1 and e2}, ultra thick]
   (intersection-1) arc to[/tikz/e1] (intersection-2)
                    arc to[/tikz/e2] (intersection-1) -- cycle;
\end{tikzpicture}

%%% 2b. arc to + spath3
\begin{tikzpicture}[
  arc starts=after moveto,
  e1/.style={x radius=.6, y radius=1.2},
  e2/.style={x radius=.9, y radius=1.2},
]
\path[name path=e1] (-2.8, 0) arc[start angle=90, delta angle= 180, e1];
\path[name path=e2] (-3.0, 0) arc[start angle=90, delta angle=-180, e2];

\draw[name intersections={of=e1 and e2}, ultra thick]
   (intersection-1) arc to[/tikz/e1] (intersection-2)
                    arc to[/tikz/e2] (intersection-1) [cycle];
\end{tikzpicture}

% 3. spath
\begin{tikzpicture}[
  arc starts=after moveto,
  e1/.style={x radius=.6, y radius=1.2},
  e2/.style={x radius=.9, y radius=1.2},
  label position=center,
]
\path[name path=e1] (-2.8, 0) coordinate (c1)
  arc[start angle=90, delta angle= 180, e1];
\path[name path=e2] (-3.0, 0) coordinate(c2)
  arc[start angle=90, delta angle=-180, e2];

\draw[ultra thick, spath/.cd,
  split at intersections={e1}{e2},
  remove components={e1}{2,4},
  remove components={e2}{1,2,4},
  use=e1, append reverse=e2,
 ] -- cycle;
\end{tikzpicture}
\end{document}

Ausgabe

Bildbeschreibung hier eingeben

verwandte Informationen