Obtenha a saída do foreach em vez do próprio foreach

Obtenha a saída do foreach em vez do próprio foreach

Quero obter a saída da seguinte macro armazenada em uma variável:

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

Eu tentei fazer:

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

Não funciona porque armazena a macro em si, não a saída que ela produz.

Alguém poderia me ajudar a descobrir como fazer com que a saída dele seja armazenada dentro de uma variável?


Explicação do que estou tentando realizar

1 Exemplo de trabalho mínimo

\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 Comentário

Eu tenho um estilo tikz chamado "mark pos", que é usado para colocar coordenadas através de linhas criadas com "plot".

Há casos específicos em que uso "plot[smooth]" ou "plot[smooth cycle]" para criar formas que possuem formas semicirculares específicas que precisam ser gerenciadas/fechadas suavemente em uma variedade de padrões.

Tenho então que definir uma série de coordenadas para que ela vá para um determinado caminho que eu quero, neste caso usar uma equação que forme formas circulares/elípticas e usar a "marca pos" para definir as coordenadas.

Em alguns casos tenho que definir uma quantidade considerável de coordenadas para que ela forme uma curva suficientemente homogênea, então quis criar um loop com "foreach" para fazer isso rapidamente sem precisar definir cada uma manualmente.

Preciso colocar a saída da macro foreach dentro de um "\draw[x]", não consigo fazer isso com a própria macro bruta.


Obrigado.


Exemplificação que comentei com Qrrbrbirlbel

1 Caso um: O que posso conseguir agora com a ajuda de 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);

Produz: insira a descrição da imagem aqui

2 Caso dois: O que pretendo obter, mas sem precisar digitar todos esses pontos (z1, z2, z3...) nas coordenadas do gráfico.

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

Produz: insira a descrição da imagem aqui

Responder1

Eu abordaria isso de forma diferente.

Múltiplas marcações em uma separação fixa podem ser colocadas com a mark=between positions … and … step … with …sintaxe. O manual explica tudoos detalhes. O valor da /pgf/decoration/mark info/sequence numberchave fornece um contador incremental.


Além disso, fornecerei um arccalestilo que você pode usar em um caminho TikZ que usa apenas dois argumentos: o centro e os raios no formato TikZ <x> and <y>.

A terceira imagem TikZ desenha o arco elíptico como um arco elíptico em vez de um gráfico.

A última imagem não utiliza a markingsbiblioteca, apenas desenha dois arcos, o segundo com ângulos diferentes. Se você realmente precisa que os arcos sejam encurtados por uma quantidade parcial do comprimento total do arco, a abordagem é um pouco mais complicada (o comprimento total é fornecido apenas pelo módulo de decoração do PGF/TikZ e não é facilmente extraível), mas ainda é melhor do que colocar dezenas de marcações e traçar uma linha através delas.


Há tambémmaneiras mais legaisdesenhar arcos em torno de um centro, mas isso não é relevante para sua pergunta.

Código

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

Saída

insira a descrição da imagem aqui


A meu ver, você deseja combinar arcos entre as interseções.

Aqui estão três abordagens, todas usam a intersectionsbiblioteca para encontrar a interseção entre os dois caminhos que compõem os arcos/semielipses.

O primeiro usa a sintaxe calcda biblioteca let … inpara calcular o ângulo das interseções com os centros da elipse para outro conjunto de arcs. As coordenadas m1e m2são usadas para obter oxraio das elipses no sistema de coordenadas da tela sem ter que fazer as transformações nós mesmos.

O segundo usa a ext.paths.arctobiblioteca do meutikz-extpacoteque permite desenhar um arcoparaum ponto, os ângulos serão calculados por PGF/TikZ.

A terceira solução utiliza a spath3biblioteca que permite dividir caminhos em interseções com outros caminhos. Precisamos apenas especificar quais componentes dos caminhos divididos serão desenhados.


Como as avaliações matemáticas das soluções 1 e 2 não são muito precisas, você obteria artefatos irritantes ao fechar os caminhos:
insira a descrição da imagem aqui

Isso pode ser corrigido usando spath3a adjust and closechave ou ocultado usando line join=round.

No geral, prefiro as arc toabordagens porque

  • a calcabordagem usa muitos cálculos manuais, mas também porque a acosfunção não é inequívoca (dois ângulos para um valor) e isso precisará de ajustes e
  • a spath3solução precisa que você especifique os componentes que podem ser complicados porque os arcos são construídos a partir de até quatro curvas de Bézier (cada uma correspondendo a um componente).

De qualquer forma, no código abaixo, todas as soluções são apresentadas. Eu também estou usandominha respostaé arc starts=after movetopara facilitar o desenho de arcos em torno de um centro.

Código

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

Saída

insira a descrição da imagem aqui

informação relacionada