取得 foreach 的輸出而非 foreach 本身

取得 foreach 的輸出而非 foreach 本身

我想獲取存儲在變數中的以下巨集的輸出:

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

我嘗試這樣做:

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

它不起作用,因為它存儲巨集本身,而不是它產生的輸出。

有人可以幫我找出如何將其輸出儲存在變數中嗎?


解釋我想要實現的目標

1 最小工作範例

\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 評論

我有一個名為“mark pos”的 tikz 樣式,用於透過用“plot”創建的線放置座標。

在某些特定情況下,我使用“plot[smooth]”或“plot[smooth Cycle]”來製作具有特定半圓形形狀的形狀,需要以各種模式平滑地管理/關閉這些形狀。

然後,我必須定義一系列座標,使其按照我想要的方式運行,在本例中,使用形成圓形/橢圓形的方程式並使用“mark pos”來設定座標。

在某些情況下,我必須定義大量的座標才能形成足夠均勻的曲線,因此我想使用「foreach」建立一個循環來快速完成這些座標,而不必手動定義每個座標。

我需要將 foreach 巨集的輸出放在「\draw[x]」內,我無法使用原始巨集本身來做到這一點。


謝謝。


我用 Qrrbrbirlbel 評論過的例子

1 案例一:在 Qrrbrbirlbel 的幫助下我現在能得到什麼

\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);

生產: 在此輸入影像描述

2 情況二:我想要得到什麼,但不必在繪圖座標中輸入所有這些點(z1、z2、z3...)。

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

生產: 在此輸入影像描述

答案1

我會以不同的方式處理這個問題。

可以使用固定間隔放置多個標記mark=between positions … and … step … with …語法以固定間隔放置多個標記。說明書解釋了一切細節。鍵的值/pgf/decoration/mark info/sequence number提供了一個遞增計數器。


此外,我將提供一種arccal可以在 TikZ 路徑上使用的樣式,該樣式僅使用兩個參數:TikZ 格式的中心和半徑<x> and <y>

第三張 TikZ 圖片將橢圓弧繪製為橢圓弧而不是繪圖。

最後一張圖沒有使用markings函式庫,只是繪製了兩條弧線,第二條弧線有不同的角度。如果確實需要將弧線縮短部分弧線總長度,則方法會稍微複雜一些(總長度僅由 PGF/TikZ 的裝飾模組提供,不易提取),但是仍然比放置數十個標記並通過它們繪製一條線更好。


還有更好的方法圍繞中心繪製弧線,但這與您的問題無關。

程式碼

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

輸出

在此輸入影像描述


在我看來,您想要組合交叉點之間的弧。

這裡有三種方法,都使用intersections函式庫來找出構成圓弧/半橢圓的兩條路徑之間的交點。

第一個使用calc函式庫的let … in語法來計算另一組 s 與橢圓中心的交點角度arcm1m2用於能夠獲得X畫布座標系中橢圓的半徑,而無需我們自己轉換。

第二個使用的是ext.paths.arcto我的庫tikz-ext包裹允許繪製弧線一個點,角度將由 PGF/TikZ 計算。

第三種解決方案使用該spath3函式庫,可以在與其他路徑的交叉點處分割路徑。我們只需要指定要繪​​製分割路徑的哪些元件即可。


由於解決方案 1 和 2 的數學評估不是很精確,因此在關閉路徑時您會得到惱人的偽影:
在此輸入影像描述

spath3這可以透過使用的key來修復adjust and close或使用 來隱藏line join=round

總的來說,我更喜歡這些arc to方法,因為

  • calc方法使用大量手動計算,但也因為acos函數不是明確的(一個值兩個角度),這需要調整和
  • spath3解決方案需要您指定可能會變得棘手的組件,因為弧是由最多四個貝塞爾曲線(每個曲線對應一個組件)建構的。

不管怎樣,在下面的程式碼中,給出了所有的解決方案。我也在用我的答案以便arc starts=after moveto更容易圍繞中心繪製圓弧。

程式碼

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

輸出

在此輸入影像描述

相關內容