3

I would like to draw a random curve of specified length between two points. As an example, take the points (0,0) and (10,10). How would one be able to connect them with a random curve of length 20?

According to this answer, there is a way to find the length of an already drawn curve, but I do not know where to begin on specifying the length beforehand. Any help is appreciated.

  • This sounds like a math question and not a PGF/TikZ one. Finding one path with the specified length is probably easy (equilateral triangle or an arc). You could probably adjust the random steps decoration so that the amplitude is adjusted for the correct length. Does it need to be exact? Who's going to measure it? Are you talking about the length on the paper (i.e. with units) or the distance in the xyz coordinate system (without units like your coordinates)? – Qrrbrbirlbel Jun 14 '23 at 19:27
  • The diagonal is 14.something, i.e. shorter than 20. So you‘ll have an infinite number of curves of all kind of shapes … Unless you have more constraints … – MS-SPO Jun 14 '23 at 19:34
  • @Qrrbrbirlbel Exact is preferred, but maybe I'm being too anal! I am using the distance according to the xyz coordinate plane. I will look into the random steps decoration and see if I can get anywhere. The shape I desire for the random curve is analogous to dropping a string on the ground. I am aware of the controls command to draw smooth curves, but it does not have the capabilities to define a length to the curve. – Logan Weinert Jun 14 '23 at 19:46
  • this is not reasonable to solve in latex (and isn't that easy even with a computational algebra system. even if you restrict to a single curve segment, the length from the control points is an integral expression so to get the control points from the length you need to numerically solve the intgral equation. – David Carlisle Jun 15 '23 at 07:59
  • @DavidCarlisle Thanks for the info. I'll abandon the exact length I wanted and just eyeball it instead. – Logan Weinert Jun 15 '23 at 15:46

1 Answers1

5

0

This is a random smooth curve from (1, 0) to (10, 9) of length ~30. It is obtained through a recursive decoration, random curve of given length. This decoration takes four arguments: the scaling factor for the "random points", the scaling factor for the tangent vectors at the random points, the step variation for the first factor, and the desired length.

Some explanations concerning the construction

  1. It is based on a style for random smooth curves introduced through a scope. This style takes one argument, the number of random points. It performs some computations (mainly introduce the random numbers needed in the sequel and some individual constants \cst{\i} that allow some control on the random tangent vectors for aesthetic reasons (see 2.).

  2. The curve is constructed (if needed) using a decoration random curve test which takes only two arguments (the first two of the recursive decoration). See the figure below.

2

Assume we don't like the curve around the points 1 and 3. We change the sign of the individual constants and arrive at the next figure.

3

  1. We construct the desired curve using the recursive decoration.

enter image description here

  1. I'm using @Gonzalo Medina idea for the length of the curve.

  2. The seed if fixed through \pgfmathsetseed{19}. You might want to comment that line; notice that the testing phase makes no sense then. But there is a problem then; I decided to adopt a simple solution for the sign of the third argument of random curve of given length when it is invoked; it is based on the test step! If needed, I can modify the code...

The code (It produces the last drawing.)

\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 = \pgfdecoratedpathlength1pt/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.5rand; \rndPy{\i} = .5 -1.5rand; };
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}

Daniel N
  • 5,687
  • Hi @Logan Weinert . I was waiting for some reaction. Is my idea useful, or close to what you are looking for? – Daniel N Jun 21 '23 at 08:01
  • Hi Daniel. At first glance it looks good; I will have time to play around with it later today. Thank you for taking the time to work on this. It is very impressive. – Logan Weinert Jun 21 '23 at 17:06