# Is there a way to randomize a Lindenmayersystem?

I'm trying to draw a classical Koch-Curve using the lindenmayersystem, but everytime a line segment is transformed there should be a 50/50 chance of it to be flipped left or right. The goal is to generate a realistic looking coastline made out of the directions for Koch-Curve-constructions. I'm really not familiar with the random function of tikz, so my attempt doesn't work at all:

\documentclass[border=9,tikz]{standalone}
\usetikzlibrary{lindenmayersystems}
\begin{document}
\pgfdeclarelindenmayersystem{Koch curve}{
\symbol{A}{\pgflsystemdrawforward}
\symbol{B}{\pgflsystemdrawforward}
\rule{A -> A+A--A+A}
\rule{B -> B-B++B-B}
\rule{S -> (random(A,B))}
}

\tikz\draw[lindenmayer system={Koch curve,angle=60,axiom=S,order=4}]lindenmayer system;

\end{document}


Edit: I almost got it now, the only remaining problem is that after each sequence (four lines with a pike) the angles stay randomized. That causes the overall segments of the curve to not follow the initial construction rule for the Koch-Curve (A+A--A+A):

\documentclass[border=9,tikz]{standalone}
\usetikzlibrary{lindenmayersystems}
\begin{document}
\pgfdeclarelindenmayersystem{Koch curve}{
\symbol{A}{\pgflsystemdrawforward}

\symbol{a}{\pgfmathrandom{0}{1}\ifnum\pgfmathresult=0%
\def\pgflsystemrightangle{120}\def\pgflsystemleftangle{60}%
\else\def\pgflsystemrightangle{-120}\def\pgflsystemleftangle{-60}\fi}

\symbol{+}{\pgflsystemturnleft}
\symbol{-}{\pgflsystemturnright}

\rule{A -> Aa+A-A+A}
}

\tikz\draw[lindenmayer system={Koch curve,axiom=A,order=2}]lindenmayer system;

\end{document}


The last segment that goes to the top left should lust go straight to the right just like the first segment. Does anybody know how to fix that?

• Yes, this is built-in. There are some keys that start with randomize. At the lower-level, the commands start with \pgflsystemrandomize… which are already used by \pgflsystemdrawforward and for example \pgflsystemturnleft. Commented Dec 8, 2022 at 14:29
• @Qrrbrbirlbel ok thank you very much! Do you by any chance know where I can find information on how to use those commands correctly? Commented Dec 12, 2022 at 9:42
• The manual itself explains them pretty good. That said, I've digged around a bit and there is no built-in way to randomnize between A and B inside a rule. I've also tried making a symbol that calls another symbol based on a random number but that's not that easy because we would need to mess with the parser. But it wouldn't be hard to do random stuff inside a symbol. \pgfmathrandom{0}{1}\ifnum\pgfmathresult=0 \pgflsystemdrawforward\else\pgftransformrotate{180}\pgflsystemdrawforward\fi. Commented Dec 12, 2022 at 10:04
• @Qrrbrbirlbel thanks again! I'll try to implement that later, hopefully It'll work! Commented Dec 12, 2022 at 12:43
• Ok 7 hours in and I still can't do it. I tried to change around the angles but that doesn't seem to be the solution. Commented Dec 12, 2022 at 20:14

Since this old Q is still waiting for a TikZ answer, here is a comparison in Metapost, the graphics language that is available to lualatex with the luamplib package.

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
vardef complicate(expr a, b) =
save c, d, m; pair c, d, m;
c = 1/3[a, b];
d = 2/3[a, b];
m = d rotatedabout(c, 60 normaldeviate);
if abs(b-a) > 2:
complicate(a, c) &
complicate(c, m) &
complicate(m, d) &
complicate(d, b)
else:
a--c--m--d--b
fi
enddef;
input colorbrewer-rgb
beginfig(1);
path coast;
coast = complicate(origin, 400 right) -- (400, -100) -- (0, -100) -- cycle;

color water, land;
water = Blues 9 2; land = Oranges 9 2;

fill bbox coast withcolor water;
fill coast withcolor land;
draw coast withpen pencircle scaled 1/4;

endfig;
\end{mplibcode}
\end{document}


You need to compile this with lualatex.

## Notes

I do not know of any formal L-system for MP, but it is not too hard to write your own recursive function as I have done here. The recursive function complicate(a, b) takes the two end points, and works out three intermediate points. If the distance between a and b is more than 2pt (0.7mm), it calls itself again four times, otherwise it just returns the path through the five points. The results from the recursive calls are spliced together with & so that the top level call returns a <path> value.

Some of the results look better than others. I ran it a few times before I got the picture of Brittany above.

If you were to remove the random part, and just put this:

m = d rotatedabout(c, 60);


in line 4 of the function, then you would get the regular Koch snowflake curve:

• All you had to do was draw the coastline of French Bretagne. :-) Commented Jul 10 at 8:20