Получите вывод 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 Комментарий

У меня есть стиль tikz под названием «mark pos», который используется для размещения координат по линиям, созданным с помощью «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для вычисления угла пересечений с центрами эллипса для другого набора arcs. Координаты m1и m2используются для того, чтобы иметь возможность получитьИксрадиус эллипсов в системе координат холста без необходимости выполнять преобразования самостоятельно.

Второй использует ext.paths.arctoбиблиотеку моегоtikz-extупаковкачто позволяет рисовать дугукточка, углы будут рассчитаны PGF/TikZ.

Третье решение использует библиотеку spath3, которая позволяет разделять пути на пересечениях с другими путями. Нам просто нужно указать, какие компоненты разделенных путей должны быть нарисованы.


Поскольку математические оценки решений 1 и 2 не очень точны, при закрытии путей возникнут раздражающие артефакты:
введите описание изображения здесь

Это можно исправить с помощью spath3ключа 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}

Выход

введите описание изображения здесь

Связанный контент