Amoeba shape with TikZ

I would like to draw generic amoeba-like shapes with TikZ and don't really want to think too deeply about its boundary. Basically a closed connected set with smooth locally convex boundaries.

Any ideas how to do this easily?

-
Perhaps this can help you get started: Curve through a sequence of points with Metapost and TikZ. It just a matter of picking the points to get the desired shape. Try adapting it and if you run into difficulties post an update here. –  Peter Grill May 8 '12 at 21:46
Thanks Peter. It might take me a while, but I will try it and report back. –  fg nu May 9 '12 at 7:53

Here's an example using one of the examples from the question that Peter Grill links to. You need the code from the TeX-SX Launchpad site: download the file hobby.dtx and run tex hobby.dtx to generate the files. Run pdflatex hobby.dtx to produce the documentation. Once you've done that, the code is simple:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{hobby}

\begin{document}
\begin{tikzpicture}
\fill[green!50] (0,0) .. (1,0) .. (1,3) .. (0,3) .. (0,1.5) .. cycle;
\fill[green!50] (3,0) .. +(1,0) .. +(1,2) .. +(1,3) .. +(0,3) .. cycle;
\fill[green!50] (6,0) .. +(1,0) .. +(1,1) .. +(1,2) .. +(1,3) .. +(0,3) .. +(0,1.5) .. cycle;
\end{tikzpicture}
\end{document}


produces:

(although you should be aware that the specific syntax I've used above might break in future versions of TikZ; there's an alternative notation that definitely won't)

-
Much appreciated Andrew. :) –  fg nu May 30 '12 at 19:35
Note that the .. cycle syntax no longer works with hobby. See tex.stackexchange.com/a/121310/86 for details and how to fix it. –  Andrew Stacey Jul 9 '13 at 8:01

More realistic amoeba with PSTricks.

First Version

Please skip this first version (as there is a small glitch) and jump to the final version.

In this version I use \psparametricplot. After meticulously figuring out its behavior, I noticed that the last node is always included to create the closed curve. As a result, the first node and the last node are on the same radial line that make the curve has a visual defect on the curved line joining them.

I have no idea how to exclude the last node when using \psparametricplot.

\documentclass[pstricks]{standalone}
\usepackage{pst-plot}
\psset
{
plotstyle=ccurve,
fillstyle=solid,
fillcolor=gray,
}
\begin{document}
\begin{pspicture}(-3,-3)(3,3)
\psparametricplot[plotpoints=40]{0}{360}{/R rand 1001 mod 1000 div 1.5 add def R t PtoC}
\end{pspicture}
\end{document}


Animation

\documentclass[pstricks]{standalone}
\usepackage{pst-plot}
\psset
{
plotstyle=ccurve,
fillstyle=solid,
fillcolor=gray,
}

\begin{document}
\multido{\i=4+4}{20}{%
\begin{pspicture}(-3,-3)(3,3)
\psparametricplot[plotpoints=\i]{0}{360}{/R rand 1001 mod 1000 div 1.5 add def R t PtoC}
\end{pspicture}}
\end{document}


Final version

In this version I use \curvepnodes to produce a list of nodes. \Pnodecount represents the index of the last element.

Therefore,

\multido{\i=0+1}{\Pnodecount}{\xdef\points{\points (P\i)}}


exludes the last node.

One advantage of using \curvepnodes is that we don't need to calculate the angle step.

\documentclass[pstricks]{standalone}

\usepackage{pst-node,pst-plot}
\psset{fillstyle=solid,fillcolor=gray}

\def\points{}
\pstVerb{666 srand}
\def\N{25}

\begin{document}
\begin{pspicture}(-3,-3)(3,3)
\curvepnodes[plotpoints=\N]{0}{360}{rand 16 mod 15 div 1.5 add t PtoC}{P}
\multido{\i=0+1}{\Pnodecount}{\xdef\points{\points (P\i)}}
\expandafter\psccurve\points
\end{pspicture}
\end{document}


Animation

\documentclass[pstricks]{standalone}

\usepackage{pst-node,pst-plot}
\usepackage{graphicx}

\newsavebox\IBox
\savebox\IBox{\includegraphics[width=6cm]{example-grid-100x100pt}}
\psset
{
fillstyle=solid,
fillcolor=gray,
xunit=\dimexpr\wd\IBox/6,
yunit=\dimexpr\ht\IBox/6,
}

\pstVerb{666 srand}

\begin{document}
\multido{\io=15+5}{10}{%
\def\points{}%
\begin{pspicture}(-3,-3)(3,3)
\curvepnodes[plotpoints=\io]{0}{360}{rand 16 mod 15 div 1.5 add t PtoC}{P}
\multido{\ii=0+1}{\Pnodecount}{\xdef\points{\points (P\ii)}}
\begin{psclip}{\expandafter\psccurve\points}
\rput(0,0){\usebox\IBox}
\end{psclip}
\end{pspicture}}
\end{document}

-

I [...] don't really want to think too deeply about its boundary. Basically a closed connected set with smooth locally convex boundaries.

Whenever I have to draw curves when I don't want to think too deeply about its boundary, I just use randomized curves. For example, here is a solution using Metapost + Metafun (I am posting ConTeXt code, but it should work in standalone metapost as well)

EDIT As Karl's student's answer illustrates, you get more realistic looking amoeba shapes if you start randomizing with more points. Based on that idea, here is another solution: (I think that the amoeba with 20 points looks rather realistic).

\startMPdefinitions
vardef amoeba (expr n) =
(for i = 0 step 360/n until 360 - 360/n : (0.5*tand(i mod (30) + 20) randomized 0.1)*dir(i randomized 5) .. endfor cycle)
enddef;
\stopMPdefinitions

\starttext

\startMPpage[offset=2mm]
path a ;

for i = 1 upto 5 :
a := amoeba(10*i) scaled 2cm shifted (i*3cm,0);

fill a withcolor 0.8white;
draw a withpen pencircle scaled 2bp;
endfor

\stopMPpage

\stoptext


Breakdown of code:

• n: Number of points.
• (0.5*tand(i mod (30) + 20) randomized 0.1): vary the distance of the point from the origin according to the angle i.
• dir(i radnomized 5): i denotes the angle. Randomize the angle by 5 degrees.

or with less randomness

These curves were obtained using

\startMPdefinitions
vardef amoeba =
(fullcircle randomized 0.8 cornered 0.15 randomized 0.1)
enddef;
\stopMPdefinitions

\starttext

\startMPpage[offset=2mm]
path a ;

for i = 1 upto 5 :
a := amoeba scaled 2cm shifted (i*3cm,0);

fill a withcolor 0.8white;
draw a withpen pencircle scaled 2bp;
endfor

\stopMPpage

\stoptext


In the second diagram, I changed randomized 0.8 to randomized 0.3. Breakdown of the code:

• fullcircle: draws a circle of diameter 1 centered around origin
• randomized 0.8: randomizes each "point" of the circle by 0.8. Since the circle has diameter 1, this changes the shape a lot. Lowering this number produces more circular looking shapes.
• cornered 0.15: Join the random points by a straight line, but instead of lines joining at right angles to one-another, join the lines by a corner of radius 0.15.
• randomized 0.1: Randomize all the points again, giving a scattered look. Leave this out if you want a smooth output.

Instead of starting with a circle, you can start with a more amoeba like shape to get more realistic output.

-