Decoração TikZ: controle a amplitude da decoração ao longo da curva

Decoração TikZ: controle a amplitude da decoração ao longo da curva

Trabalhando com decorações de caminho baseadas emesta soluçãofornecido pela marmot, estou procurando uma possibilidade de alterar a amplitude das decorações ao longo do gráfico.

Tendo esse enredo

insira a descrição da imagem aqui

aplicar a decoração mencionada dá

insira a descrição da imagem aqui

que é exatamente o que a decoração deve fazer.

Na verdade, a curva necessária deve ser semelhante a esta:

insira a descrição da imagem aqui

A última saída foi criada pesquisando manualmente as posições corretas para manipular a amplitude, que é um método de “tentativa e erro”. Alterar as dimensões do tikzpicturedará um resultado falso, fx

insira a descrição da imagem aqui

Agora a ideia básica é fornecer um caminho separado (que pode ficar visível durante o desenvolvimento) para controlar a amplitude da decoração ao longo da curva original (azul). Neste caso o caminho de controle (vermelho) seria bastante simples:

insira a descrição da imagem aqui

O caminho de controle pode ser interpretado como um fator para a amplitude da decoração que pode ser definida via decoration={amplitude=}.

Supondo que esse método seria bastante útil, estou um pouco surpreso por ele não estar disponível TikZ- ou eu o supervisionei? E se não for: como posso obter o valor y da curva de controle dentro da \state{step}parte da definição das decorações?

O MWE produzindo todos os gráficos acima (mesmo que não sejam bem codificados em termos de eficiência e beleza estrutural):

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.pathmorphing}

\newcounter{randymark}
\newcommand{\amplitudesetter}{}
\pgfdeclaredecoration{mark random y steps}{start}
{%
  \state{start}[width=+0pt,next state=step,persistent precomputation={\pgfdecoratepathhascornerstrue\setcounter{randymark}{0}}]
    {\stepcounter{randymark}
     \pgfcoordinate{randymark\arabic{randymark}}{\pgfpoint{0pt}{0pt}}
    }%
  \state{step}[auto end on length=1.5\pgfdecorationsegmentlength,
               auto corner on length=1.5\pgfdecorationsegmentlength,
               width=+\pgfdecorationsegmentlength]
    {\stepcounter{randymark}\amplitudesetter
     \pgfcoordinate{randymark\arabic{randymark}}{\pgfpoint{\pgfdecorationsegmentlength}{rand*\pgfdecorationsegmentamplitude}}
    }%
  \state{final}
    {\stepcounter{randymark}
     \pgfcoordinate{randymark\arabic{randymark}}{\pgfpointdecoratedpathlast}%
    }%
}%

\begin{document}
\begin{tikzpicture}[x=5mm,y=5mm,decoration={mark random y steps,segment length=1.5mm,amplitude=0.75mm}]% original curve
  \draw[style=help lines] (0,-4) grid[step=5mm] (25,1);
  \pgfmathsetseed{2}
  \draw[blue!80!black,thick] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
\end{tikzpicture}

\vspace{2ex}

\begin{tikzpicture}[x=5mm,y=5mm,decoration={mark random y steps,segment length=1.5mm,amplitude=0.75mm}]% original curve
  \draw[style=help lines] (0,-4) grid[step=5mm] (25,1);
  \pgfmathsetseed{2}
  \draw[black] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \path[decorate] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \draw[blue!80!black,thick] plot[variable=\x,samples at={1,...,\arabic{randymark}},smooth] (randymark\x);
\end{tikzpicture}

\vspace{2ex}

\begin{tikzpicture}[x=5mm,y=5mm,decoration={mark random y steps,segment length=1.5mm,amplitude=0.75mm}]% original curve
  \draw[style=help lines] (0,-4) grid[step=5mm] (25,1);
  \pgfmathsetseed{2}
  \renewcommand{\amplitudesetter}{%
    \pgfdecorationsegmentamplitude=0.75mm
    \ifnum\value{randymark}<48\pgfdecorationsegmentamplitude=0.7mm\fi%
    \ifnum\value{randymark}<46\pgfdecorationsegmentamplitude=0.6mm\fi%
    \ifnum\value{randymark}<44\pgfdecorationsegmentamplitude=0.5mm\fi%
    \ifnum\value{randymark}<42\pgfdecorationsegmentamplitude=0.4mm\fi%
    \ifnum\value{randymark}<40\pgfdecorationsegmentamplitude=0.3mm\fi%
    \ifnum\value{randymark}<38\pgfdecorationsegmentamplitude=0.2mm\fi%
    \ifnum\value{randymark}<36\pgfdecorationsegmentamplitude=0.1mm\fi%
    \ifnum\value{randymark}<34\pgfdecorationsegmentamplitude=0mm\fi%
    \ifnum\value{randymark}<8\pgfdecorationsegmentamplitude=0.75mm\fi%
    }
  \draw[black] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \path[decorate] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \draw[blue!80!black,thick] plot[variable=\x,samples at={1,...,\arabic{randymark}},smooth] (randymark\x);
\end{tikzpicture}

\vspace{2ex}

\begin{tikzpicture}[x=2.5mm,y=2.5mm,decoration={mark random y steps,segment length=1.5mm,amplitude=0.75mm}]% original curve
  \draw[style=help lines] (0,-4) grid[step=5mm] (25,1);
  \pgfmathsetseed{2}
  \renewcommand{\amplitudesetter}{%
    \pgfdecorationsegmentamplitude=0.75mm
    \ifnum\value{randymark}<48\pgfdecorationsegmentamplitude=0.7mm\fi%
    \ifnum\value{randymark}<46\pgfdecorationsegmentamplitude=0.6mm\fi%
    \ifnum\value{randymark}<44\pgfdecorationsegmentamplitude=0.5mm\fi%
    \ifnum\value{randymark}<42\pgfdecorationsegmentamplitude=0.4mm\fi%
    \ifnum\value{randymark}<40\pgfdecorationsegmentamplitude=0.3mm\fi%
    \ifnum\value{randymark}<38\pgfdecorationsegmentamplitude=0.2mm\fi%
    \ifnum\value{randymark}<36\pgfdecorationsegmentamplitude=0.1mm\fi%
    \ifnum\value{randymark}<34\pgfdecorationsegmentamplitude=0mm\fi%
    \ifnum\value{randymark}<8\pgfdecorationsegmentamplitude=0.75mm\fi%
    }
  \draw[black] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \path[decorate] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \draw[blue!80!black,thick] plot[variable=\x,samples at={1,...,\arabic{randymark}},smooth] (randymark\x);
\end{tikzpicture}

\vspace{2ex}

\begin{tikzpicture}[x=5mm,y=5mm,decoration={mark random y steps,segment length=1.5mm,amplitude=0.75mm}]
  \draw[style=help lines] (0,-4) grid[step=5mm] (25,1);
  \pgfmathsetseed{2}
  \draw [red,thick,name=amplitudecontrol] (0,1) -- (2,1) -- (2,0) -- (7,0) -- (12,1) -- (25,1);
  \draw[blue!80!black,thick] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
\end{tikzpicture}

\end{document}

Responder1

Deixe-me começar dizendo que gosto muito dessa pergunta e estou realmente impressionado com o que você conseguiu. Aqui está uma proposta para abordar a escalabilidade. Defina uma função que governe a amplitude,

varyingamp(x) = whatever you like

onde xé a fração do caminho decorado (para garantir escalabilidade). (Essa função já foi usadaaquipara ter larguras de linha variáveis. Eu não ficaria surpreso se coisas semelhantes tivessem sido usadas antes.) Este é o MWE.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.pathmorphing}

\newcounter{randymark}
%\newcommand{\amplitudesetter}{}
\pgfdeclaredecoration{mark random y steps}{start}
{%
  \state{start}[width=+0pt,next state=step,persistent precomputation={
  \pgfdecoratepathhascornerstrue\setcounter{randymark}{0}}]
    {\stepcounter{randymark}
     \pgfcoordinate{randymark\arabic{randymark}}{\pgfpoint{0pt}{0pt}}
    }%
  \state{step}[auto end on length=1.5\pgfdecorationsegmentlength,
               auto corner on length=1.5\pgfdecorationsegmentlength,
               width=+\pgfdecorationsegmentlength]
    {\stepcounter{randymark}%\amplitudesetter
     \pgfcoordinate{randymark\arabic{randymark}}{\pgfpoint{\pgfdecorationsegmentlength}{rand*\pgfdecorationsegmentamplitude}}
    }%
  \state{final}
    {\stepcounter{randymark}
     \pgfcoordinate{randymark\arabic{randymark}}{\pgfpointdecoratedpathlast}%
    }%
}%

\pgfdeclaredecoration{mark varying random y steps}{start}
{%
  \state{start}[width=+0pt,next state=step,persistent precomputation={
  \pgfdecoratepathhascornerstrue\setcounter{randymark}{0}}]
    {\stepcounter{randymark}
     \pgfcoordinate{randymark\arabic{randymark}}{\pgfpoint{0pt}{0pt}}
    }%
  \state{step}[auto end on length=1.5\pgfdecorationsegmentlength,
               auto corner on length=1.5\pgfdecorationsegmentlength,
               width=+\pgfdecorationsegmentlength]
    {\stepcounter{randymark}
     \pgfmathsetmacro{\myfraction}{\the\pgfdecorationsegmentlength*\value{randymark}/\pgfdecoratedpathlength}
     \pgfmathsetmacro{\myamplitude}{varyingamp(\myfraction)}
     %\typeout{\myfraction,\myamplitude}
     \pgfcoordinate{randymark\arabic{randymark}}{\pgfpoint{\pgfdecorationsegmentlength}{rand*\myamplitude*\pgfdecorationsegmentamplitude}}
    }%
  \state{final}
    {\stepcounter{randymark}
     \pgfcoordinate{randymark\arabic{randymark}}{\pgfpointdecoratedpathlast}%
    }%
}%



\begin{document}
\begin{tikzpicture}[x=5mm,y=5mm,decoration={mark random y steps,segment length=1.5mm,amplitude=0.75mm}]% original curve
  \draw[style=help lines] (0,-4) grid[step=5mm] (25,1);
  \pgfmathsetseed{2}
  \draw[blue!80!black,thick] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
\end{tikzpicture}

\vspace{2ex}

\begin{tikzpicture}[x=5mm,y=5mm,decoration={mark varying random y steps,segment
length=1.5mm,amplitude=0.75mm},declare function={
varyingamp(\x)=ifthenelse(\x<0.08,1,ifthenelse(\x<0.28,0,ifthenelse(\x<0.48,5*(\x-0.28),1)));}]% 
  \draw[style=help lines] (0,-4) grid[step=5mm] (25,1);
  \draw[red,thick] plot[variable=\x,domain=0:25,samples=101] ({\x},{varyingamp(\x/25)});
  \pgfmathsetseed{2}
  \draw[black] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \path[decorate] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \draw[blue!80!black,thick] plot[variable=\x,samples at={1,...,\arabic{randymark}},smooth] (randymark\x);
\end{tikzpicture}

\vspace{2ex}

\begin{tikzpicture}[x=2.5mm,y=2.5mm,decoration={mark varying random y
steps,segment length=0.75mm,amplitude=0.75mm},declare function={
varyingamp(\x)=ifthenelse(\x<0.08,1,ifthenelse(\x<0.28,0,ifthenelse(\x<0.48,5*(\x-0.28),1)));}]
  \draw[style=help lines] (0,-4) grid[step=5mm] (25,1);
  \pgfmathsetseed{2}
  \draw[black] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \path[decorate] (0,0) -- (2,0) to [out=0,in=180](4,-3.5) to [out=0,in=225](6,-1.75) to [out=45,in=180](11,0) -- (24.25,0);
  \draw[blue!80!black,thick] plot[variable=\x,samples at={1,...,\arabic{randymark}},smooth] (randymark\x);
\end{tikzpicture}
\end{document}

insira a descrição da imagem aqui

A função é mostrada em vermelho no segundo gráfico. O terceiro gráfico mostra escalabilidade. (Claro, você também precisa redimensionar os comprimentos dos segmentos. Observe também que esta decoração tem passos discretos, então se você tiver uma função fortemente variável, mas apenas alguns passos, a função pode não ser totalmente "apreciada", uma vez que só é avaliada em alguns pontos.)

informação relacionada