[Tex/LaTex] Generating Random arrows in tikz

arrowsmetapostpstrickstikz-pgf

I would like to draw this figure :
enter image description here
Hence, I resort to TikZ. But, it seems to be very difficult drawing arrows precisely in TikZ with the precise locations (x,y). I have achieved this:
enter image description here
Here is the MWE:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\filldraw[color=gray] (1,0) rectangle (10,5);
\draw[->, line width=2pt, color=red] (2,1) -- (3,1);
\draw[->, line width=2pt, color=red] (2,2) -- (3,2.5);
\draw[->, line width=2pt, color=red] (3,2) -- (30:3);
\end{tikzpicture}
\end{document} 

Now, my question is

How to generate arrows of random length (between 2cm and 3cm) and random inclination (if possible of random colors too like red, yellow, violet, etc.) without crossing in TikZ. Is there any function to generate Random Numbers

Note:

If not Tikz, pstricks or MetaPost will also do. For now, Asmptote will not work because there seems an error in the execution in my system.

Best Answer

Updated version (without crossing):

A possibility with random colors, widths, directions, lengths; the image was produced using

\RandArrow

\def\Columns{10}
\RandArrow[80]

enter image description here

The code:

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

\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

\def\maxArrow{30}
\def\Columns{6}

\newcommand\randomarrow{
  \pgfmathsetseed{\pdfuniformdeviate 10000000}
  \edef\R{\pdfuniformdeviate 255}
  \edef\G{\pdfuniformdeviate 255}
  \edef\B{\pdfuniformdeviate 255}
  \xdefinecolor{mycolor}{RGB}{\R,\G,\B}
  \tikz\draw[->,line width=2pt*rnd+1pt,color=mycolor] 
    (rnd,rnd) -- ++(rnd*360:rnd+0.2);
}
\newcommand\RandArrow[1][30]{%
  \def\maxArrow{#1}  
  \begin{tikzpicture}
  \foreach [count=\i] \val in {1,...,\maxArrow} 
  { 
    \path  
      let \n{row}={int(mod(\i -1, \Columns))}, 
            \n{col}={ int( ( \i - 1 ) / (-\Columns) ) } 
      in 
         (\n{row}, \n{col}) rectangle  +(1,1) 
         +(0.5, 0.5) node{\randomarrow};
  }
  \begin{pgfonlayer}{background}
  \draw[orange!70!black,line width=1pt,fill=yellow!15]
    (current bounding box.north west)
      rectangle
    (current bounding box.south east);
  \end{pgfonlayer}
  \end{tikzpicture}%
}

\begin{document}

\RandArrow

\def\Columns{10}
\RandArrow[80]

\end{document}

The idea to avoid crossing arrows is to have a grid and place each arrow in one of the squares of the grid.

  1. \maxArrows allows to specify the number of arrows (initially set to 30).

  2. \Columns controls the number of rows of the grid (initially set to 6).

  3. \randomarrow draws an arrow; the width, length, color and direction are chosen randomly using rnd; the length will only be (in the worst case) 0.2cm larger than the width of the square; this is to prevent arrows from having zero length.

  4. The main command is \RandArrow with an optional argument allowing to decide the number of arrows to be drawn; the default value is 30.

  5. As suggested by Paul Gaborit in his answer, \pgfmathsetseed{\pdfuniformdeviate 10000000} was used in the definition of \randomarrow to change the seed used by the pseudo-random generator at each compilation.

Introducing some randomness in the grid gives better results:

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

\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

\def\maxArrow{30}
\def\Columns{6}

\newcommand\randomarrow{
  \pgfmathsetseed{\pdfuniformdeviate 10000000}
  \edef\R{\pdfuniformdeviate 255}
  \edef\G{\pdfuniformdeviate 255}
  \edef\B{\pdfuniformdeviate 255}
  \xdefinecolor{mycolor}{RGB}{\R,\G,\B}
  \tikz\draw[->,line width=2pt*rnd+1pt,color=mycolor] 
    (rnd,rnd) -- ++(rnd*360:rnd+0.1);
}
\newcommand\RandArrow[1][30]{%
  \pgfmathsetseed{\pdfuniformdeviate 10000000}
  \def\maxArrow{#1}  
  \begin{tikzpicture}
  \foreach [count=\i] \val in {1,...,\maxArrow} 
  { 
    \path  
      let \n{row}={ int(mod(\i -1, \Columns))}, 
            \n{col}={ int( ( \i - 1 ) / (-\Columns) ) } 
      in 
         (\n{row}, \n{col}) rectangle  +({random(2,3)},rand) 
         node[near start] {\randomarrow};
  }
  \begin{pgfonlayer}{background}
  \draw[orange!70!black,line width=1pt,fill=yellow!15]
    (current bounding box.north west)
      rectangle
    (current bounding box.south east);
  \end{pgfonlayer}
  \end{tikzpicture}%
}

\begin{document}

\RandArrow

\def\Columns{10}
\RandArrow[80]

\end{document}

enter image description here