11

I am trying to create the following illustration.

randomly filled shapes

Using Tikz, I managed to achieve a partial effect as shown below (please ignore the dimension mismatches). yet to be with random patterns

The code I used (MWE) for arriving thus far is the following:

\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}[every node/.style={draw,thin,minimum height=10mm}]

    \node [fill=orange]                                 (boxA) {};
    \node [text width=10mm,anchor=west]  at (boxA.east) (boxB)   {};
    \node [anchor=west]                  at (boxB.east) (boxC)   {};
    \node [text width=10mm,anchor=west]  at (boxC.east) (boxD)   {};
    \node [fill=black!30,anchor=west]    at (boxD.east) (boxE)   {};

\end{tikzpicture}
\end{document}

I'd like help on generating these random shapes (smooth, closed 2D capsules) that are in each section. I really need to achieve this using 'nodes',i.e. the basic structure needs to be created using nodes and not hand-drawn using 'rectangles' and 'co-ordinates'.

I have named the different nodes as 'boxA' through 'boxE'. Any help is much appreciated. PSTricks code is not good enough since the rest of my illustration (surrounding infrastructure, relative positions etc) is coded in TikZ.

  • You could create a few shapes by hand (6 or so) and choose from among them randomly with random rotation. – Skillmon Sep 15 '17 at 18:01
  • Related?: tex.stackexchange.com/questions/87497/…, – Ignasi Sep 15 '17 at 18:03
  • I wouldn't like to do them by hand...Choosing co-ordinates etc. is a mess and not elegant. Is there a programmatic way to achieve this effect. I don't have a problem if the placement of the capsules change (due to randomness) upon every compilation. – Krishna Sep 15 '17 at 18:03
  • @Ignasi , yes. Looks related indeed. But, in addition to randomising the co-ordinates of the capsules, I also have a need to randomise their shapes. I am a TikZ novice and I'd like a bit more help. – Krishna Sep 15 '17 at 18:08
  • A hepful link?:Poisson disc sampling implemented in luatex – Bobyandbob Sep 15 '17 at 18:08
15

Each "blob" can be drawn using a technique taken from this answer, but modified to use Hobby package which produces smoother results.

In the next example I define a pic which draws one of these "blobs". Being a pic is very easy to rotate, scale and translate the shape, so I draw 35 of them in a regular grid. Instead of a regular grid you can use the random positions generated by a Poisson disc sampling.

This is my minimal example code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{hobby}
\usetikzlibrary{calc}
\begin{document}

\tikzset{
 pics/blob/.style={
   code={
   \draw[use Hobby shortcut, fill, closed] (0,0) +($(0:1+4*rnd)$)
       \foreach \a in {60,120,...,350} {  .. +($(\a: 1+4*rnd)$) };
   }
}}

\foreach \x in {0,...,5} {
  \foreach \y in {0,...,7} {
    \pgfmathsetmacro{\scale}{0.1+0.1*rnd}
    \pic at (\x,\y)  [fill=green!30, scale=\scale, rotate=360*rnd]{blob};
  }
};
\end{document}

And this is the result:

Result

Update: using Poisson sampling

Using the lua code from this answer the (x,y) of each blob is generated. The remaining of the code is the same. This is the complete main tex file:

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

\tikzset{
 pics/blob/.style={
   code={
   \draw[use Hobby shortcut, fill, closed] (0,0) +($(0:1+4*rnd)$)
       \foreach \a in {60,120,...,350} {  .. +($(\a: 1+4*rnd)$) };
   }
}}

\begin{document}
\edef\mylist{\poissonpointslist{5}{5}{0.4}{15}}
\begin{tikzpicture}
     \foreach \x/\y in \mylist {
       \pgfmathsetmacro{\scale}{0.02+0.1*rnd}
        \pic at (\x,\y)  [fill=green!30, scale=0.1, rotate=360*rnd]{blob};
     }
\end{tikzpicture}
\end{document}

And this is the result:

Result

To compile it you have to use Lualatex (it takes a while to complete).

Final update

This version uses the code in the OP's question, and then my code to fill its nodes. It was necessary to tweak the scale of the blobs, because the area to fill is very small, and the line width of the blobs for the same reason. Also, inner sep=0pt was added to the OP's nodes, to have full control over their width and height.

Finally, since in the figure provided by the OP both boxes are filled exactly with the same shapes, but in a different color, I fixed a random seed and restored it before filling the second box.

The code:

\documentclass{article}
\usepackage{tikz}
\usepackage{poisson}
\usetikzlibrary{hobby}
\usetikzlibrary{calc}
\usetikzlibrary{positioning}

\tikzset{
 pics/blob/.style={
   code={
   \draw[use Hobby shortcut, fill, closed] (0,0) +($(0:1+4*rnd)$)
       \foreach \a in {60,120,...,350} {  .. +($(\a: 1+4*rnd)$) };
   }
}}
\newcounter{mathseed}
\setcounter{mathseed}{3}

\begin{document}
\edef\mylist{\poissonpointslist{1}{.9}{0.06}{10}}
\begin{tikzpicture}[every node/.style={draw,thin,minimum height=10mm,inner sep=0pt}]

    \node [fill=orange,text width=2mm]                                (boxA) {};
    \node [text width=11mm,anchor=west]                at (boxA.east) (boxB) {};
    \node [anchor=west, text width=2mm]                at (boxB.east) (boxC) {};
    \node [text width=11mm,anchor=west]                at (boxC.east) (boxD) {};
    \node [fill=black!30,anchor=west, text width=2mm]  at (boxD.east) (boxE) {};
    \pgfmathsetseed{\arabic{mathseed}}
     \foreach \x/\y in \mylist {
       \pgfmathsetmacro{\scale}{0.01+0.01*rnd}
        \pic at ($(boxB.south west)+(\x+.06,\y+.05)$)
            [line width=0.05mm,fill=green!80!black, 
             scale=\scale, rotate=360*rnd]{blob};
    }
    \pgfmathsetseed{\arabic{mathseed}}
     \foreach \x/\y in \mylist {
       \pgfmathsetmacro{\scale}{0.01+0.01*rnd}
        \pic at ($(boxD.south west)+(\x+.06,\y+.05)$)
            [line width=0.05mm,fill=magenta!80!black, 
             scale=\scale, rotate=360*rnd]{blob};
    }
\end{tikzpicture}
\end{document}

The result:

Result

  • Thank you. I plan to adapt this answer to my problem. How do I obtain the x and y-cordinates of my boxB and boxD so as to plug them in to your \foreach iterates' upper limit? – Krishna Sep 15 '17 at 18:43
  • @Krishna boxB.north east, boxB.north west, boxB.south east, etc... – JLDiaz Sep 15 '17 at 18:48
  • Unfortunately, that does not seem to work. The compiler produces an error message complaining "Missing number, treated as zero <to be read again" – Krishna Sep 15 '17 at 19:06
  • @Krishna See my latest update – JLDiaz Sep 15 '17 at 20:07
  • Thank you for the wonderful answer. Marked as accepted. Much appreciate your help on this :) – Krishna Sep 15 '17 at 21:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.