TikZ-decoration: controla la amplitud de la decoración a lo largo de la curva

TikZ-decoration: controla la amplitud de la decoración a lo largo de la curva

Trabajar con decoraciones de camino basadas enesta soluciónproporcionado por marmota. Estoy buscando la posibilidad de cambiar la amplitud de las decoraciones a lo largo del gráfico.

Tener esta trama

ingrese la descripción de la imagen aquí

aplicando la decoración mencionada da

ingrese la descripción de la imagen aquí

que es exactamente lo que se supone que debe hacer la decoración.

De hecho, la curva requerida debería verse así:

ingrese la descripción de la imagen aquí

La última salida se creó buscando manualmente las posiciones correctas para manipular la amplitud, que es un método de "prueba y error". Cambiar las dimensiones del tikzpicturedará un resultado falso, fx

ingrese la descripción de la imagen aquí

Ahora la idea básica es proporcionar un camino separado (que pueda hacerse visible durante el desarrollo) para controlar la amplitud de las decoraciones a lo largo de la curva original (azul). En este caso la ruta de control (roja) sería bastante sencilla:

ingrese la descripción de la imagen aquí

La ruta de control podría interpretarse como un factor de la amplitud de las decoraciones que se puede configurar mediante decoration={amplitude=}.

Suponiendo que este método sería bastante útil, estoy un poco sorprendido de que no esté disponible TikZ, ¿o lo he supervisado? Y si no es así: ¿cómo puedo obtener el valor y de la curva de control dentro de la \state{step}parte de la definición de decoraciones?

El MWE que produce todos los gráficos anteriores (aunque no esté bien codificado en términos de eficiencia y belleza estructural):

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

Respuesta1

Permítanme empezar diciendo que me gusta mucho esa pregunta y estoy realmente impresionado por lo que han logrado. Aquí hay una propuesta para abordar la escalabilidad. Defina una función que gobierne la amplitud,

varyingamp(x) = whatever you like

¿Dónde xestá la fracción del camino decorado (para garantizar la escalabilidad)? (Esta función ya se ha utilizadoaquípara tener anchos de línea variables y variables. No me sorprendería en absoluto que se hubieran utilizado cosas similares antes). Este es el 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}

ingrese la descripción de la imagen aquí

La función se muestra en rojo en el segundo gráfico. El tercer gráfico muestra la escalabilidad. (Por supuesto, también necesita cambiar la escala de las longitudes de los segmentos. Tenga en cuenta también que esta decoración tiene pasos discretos, por lo que si tiene una función que varía mucho pero solo unos pocos pasos, es posible que la función no se "aprecie" completamente ya que solo se evalúa en algunos puntos.)

información relacionada