TikZ-декор: управление амплитудой декора вдоль кривой

TikZ-декор: управление амплитудой декора вдоль кривой

Работа с украшениями дорожек на основеэто решениепредоставлено marmot Я ищу возможность изменять амплитуду декораций вдоль графика.

Имея этот участок

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

применение указанного украшения дает

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

именно это и должно делать украшение.

На самом деле требуемая кривая должна выглядеть так:

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

Последний вывод был создан путем ручного поиска правильных позиций для управления амплитудой, что является методом "проб и ошибок". Изменение размеров tikzpictureзатем даст ложный результат, fx

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

Теперь основная идея заключается в том, чтобы предоставить отдельный путь (который можно сделать видимым во время разработки) для управления амплитудой декораций вдоль исходной (синей) кривой. В этом случае путь управления (красный) будет довольно простым:

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

Путь управления можно интерпретировать как фактор амплитуды декораций, который можно задать с помощью decoration={amplitude=}.

Предполагая, что этот метод будет весьма удобен, я немного ошеломлен, что его нет в TikZ- или я его проглядел? И если нет: как мне получить значение y контрольной кривой в \state{step}части определения декораций?

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

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

решение1

Позвольте мне начать с того, что мне очень нравится этот вопрос, и я действительно впечатлен тем, чего вы достигли. Вот предложение по решению проблемы масштабируемости. Определите функцию, которая управляет амплитудой,

varyingamp(x) = whatever you like

где x- доля декорированного пути (для обеспечения масштабируемости). (Такая функция уже использоваласьздесь(чтобы иметь переменную ширину линий. Я бы совсем не удивился, если бы подобные вещи использовались раньше.) Это 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}

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

Функция показана красным на втором графике. Третий график показывает масштабируемость. (Конечно, вам также нужно изменить масштаб длин сегментов. Обратите внимание также, что это украшение имеет дискретные шаги, поэтому если у вас есть сильно меняющаяся функция, но только несколько шагов, функция может быть не полностью «оценена», поскольку она оценивается только в нескольких точках.)

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