两点之间指定长度的曲线

两点之间指定长度的曲线

我想在两点之间绘制一条指定长度的随机曲线。例如,以点(0,0)和为例(10,10)。如何用长度为 20 的随机曲线将它们连接起来?

根据这个回答,有一种方法可以找到已绘制曲线的长度,但我不知道从哪里开始预先指定长度。任何帮助都非常感谢。

答案1

0

这是一条长度约为 30 的随机平滑曲线,范围从 (1, 0) 到 (10, 9)。它是通过递归修饰获得的。random curve of given length此修饰有四个参数:“随机点”的缩放因子、随机点处切向量的缩放因子、第一个因子的步长变化以及所需长度。

有关施工的一些说明

  1. 它基于for random smooth curves通过引入的样式scope。此样式采用一个参数,即随机点的数量。它执行一些计算(主要引入后续操作中所需的随机数和一些单独的常量,\cst{\i}这些常量允许出于美观原因对随机切向量进行一些控制(参见 2.)。

  2. 曲线是使用random curve test仅接受两个参数(递归修饰的前两个参数)的修饰来构造的(如果需要)。见下图。

2

假设我们不喜欢点 1 和 3 周围的曲线。我们改变各个常数的符号并得出下一个数字。

3

  1. 我们使用递归修饰来构建所需的曲线。

在此处输入图片描述

  1. 我正在使用@Gonzalo Medina 的想法来决定曲线的长度。

  2. 种子通过 固定\pgfmathsetseed{19}。您可能想要注释掉该行;请注意,测试阶段没有意义。但是有一个问题;我决定采用一个简单的解决方案来处理random curve of given length调用时第三个参数的符号;它基于测试步骤!如果需要,我可以修改代码……

代码(它生成了最后一张图纸。)

\documentclass[11pt, margin=.5cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{math, calc}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{decorations.pathreplacing} % for show control points

\usepackage{pgfplots}

\makeatletter
\tikzset{%
  measureme/.style={%
    decoration={%
      markings,
      mark=at position 1 with {%
        \tikzmath{
          \lrc = \pgfdecoratedpathlength*1pt/1cm;
        }
        \pgfextra{\xdef\lrcG{\lrc}}
      }
    },
    postaction=decorate
  },
  for smooth random curve/.style={%
    evaluate={%
      int \N@glc, \M@glc, \i, \j;
      real \lrc; 
      \N@glc = #1;
      \M@glc = #1 +1;
      for \i in {1, ..., \N@glc}{%
        \rndPx{\i} = .5 +1.5*rand;
        \rndPy{\i} = .5 -1.5*rand;
      };      
      for \i in {0, ..., \M@glc}{%
        \cst{\i} = 1;
        \rndVm{\i} = .2 +abs(rand);
        \rndVa{\i} = 180*rand;
      };
    }
  },
  random curve test/.style 2 args={  % p scale / q scale
    decoration={
      show path construction,
      lineto code={
        \path (\tikzinputsegmentfirst) coordinate (P-0);
        \path (\tikzinputsegmentlast) coordinate (P-\M@glc);
        \path ($($(P-0)!1/\M@glc!(P-\M@glc)$) -(P-0)$) coordinate (v);
        \foreach \i in {1, ..., \N@glc}{%
          \path ($(P-0)!\i/\M@glc!(P-\M@glc)$)
          let
          \p1 = (v)
          in ++({#1*\rndPx{\i}*\x1}, {#1*\rndPy{\i}*\y1})
          coordinate (P-\i);
        }
        \foreach \i in {0, ..., \M@glc}{%
          \path ($(0, 0)!{#2*\cst{\i}*\rndVm{\i}}!\rndVa{\i}: (v)$)
          coordinate (v-\i);
        }
        \foreach \i in {0, ..., \M@glc}{%
          \draw[green!70!black] (P-\i) circle (2pt) -- ++(v-\i)
          node[pos=1.03, text=red] {\i};
        }
        \draw[measureme] (P-0)
        \foreach \i [evaluate=\i as \j using {int(\i +1)}]
        in {0, ..., \N@glc}{%
          .. controls ++(v-\i) and ++([scale=-1] v-\j) .. (P-\j)
        };
      }
    },
    decorate
  },
  random curve of given length/.style n args={4}{%
    % p scale / q scale / step / length
    decoration={
      show path construction,
      lineto code={
        \path (\tikzinputsegmentfirst) coordinate (P-0);
        \path (\tikzinputsegmentlast) coordinate (P-\M@glc);
        \path ($($(P-0)!1/\M@glc!(P-\M@glc)$) -(P-0)$) coordinate (v);
        \foreach \i in {1, ..., \N@glc}{%
          \path ($(P-0)!\i/\M@glc!(P-\M@glc)$)
          let
          \p1 = (v)
          in ++({#1*\rndPx{\i}*\x1}, {#1*\rndPy{\i}*\y1})
          coordinate (P-\i);
        }
        \foreach \i in {0, ..., \M@glc}{%
          \path ($(0, 0)!{#2*\cst{\i}*\rndVm{\i}}!\rndVa{\i}: (v)$)
          coordinate (v-\i);
        }
        \path[measureme] (P-0)  % produces \lrcG, the length
        \foreach \i [evaluate=\i as \j using {int(\i +1)}]
        in {0, ..., \N@glc}{%
          .. controls ++(v-\i) and ++([scale=-1] v-\j) .. (P-\j)
        };
        \tikzmath{%
          \stp = #3;
          \dMain = #4 -\lrcG;
          if abs(\dMain)<.05 then {%
            {%
              \draw[red, measureme] (P-0)
              \foreach \i [evaluate=\i as \j using {int(\i +1)}]
              in {0, ..., \N@glc}{%
                .. controls ++(v-\i) and ++([scale=-1] v-\j) .. (P-\j)
              };
            };
          } else {%
            if \dMain*\stp<0 then { \stp = -\stp/2; };
            \pScale = #1 +\stp;
            {%
              \path[random curve of given length={\pScale}{#2}{\stp}{#4}]
              (P-0) to (P-\M@glc);
            };
          };
        }
      }
    },
    decorate
  }  
}
\makeatother

\begin{document}

\begin{tikzpicture}[line cap=round]
  \pgfmathsetseed{19}
  \draw[gray!40] (0, 0) grid (10, 10);

  \path (1, 0) coordinate (Pini);
  \path (10, 9) coordinate (Pend);
  \begin{scope}[for smooth random curve={4}]
    \tikzmath{%
      \cst{0} = 2;
      \cst{1} = -1;
      \cst{3} = -1;
    }
    \draw[random curve test={1}{1}] (Pini) to (Pend);
    \draw[random curve of given length={1}{1}{.1}{30}] (Pini) to (Pend);
  \end{scope}
  \path let
  \p1 = ($(Pend) -(Pini)$),
  \n1 = {veclen(\x1, \y1)/1cm}
  in (Pini) ++(3, -1) node {curve of length \lrcG};
\end{tikzpicture}
\end{document}

相关内容