![TikZ-декор: управление амплитудой декора вдоль кривой](https://rvso.com/image/392325/TikZ-%D0%B4%D0%B5%D0%BA%D0%BE%D1%80%3A%20%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%B0%D0%BC%D0%BF%D0%BB%D0%B8%D1%82%D1%83%D0%B4%D0%BE%D0%B9%20%D0%B4%D0%B5%D0%BA%D0%BE%D1%80%D0%B0%20%D0%B2%D0%B4%D0%BE%D0%BB%D1%8C%20%D0%BA%D1%80%D0%B8%D0%B2%D0%BE%D0%B9.png)
Работа с украшениями дорожек на основеэто решениепредоставлено 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}
Функция показана красным на втором графике. Третий график показывает масштабируемость. (Конечно, вам также нужно изменить масштаб длин сегментов. Обратите внимание также, что это украшение имеет дискретные шаги, поэтому если у вас есть сильно меняющаяся функция, но только несколько шагов, функция может быть не полностью «оценена», поскольку она оценивается только в нескольких точках.)