Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I wish to generate a rectangle with circular features present within (to represent water particles), something like this:

enter image description here

Which shows that the incoming radiation decreases with distance (as expressed by the shading of the arrow). This rather simplistic example was generated in power point, how would I draw this with tikz.

I can obviously draw a normal rectangle and arrow with:

\begin{tikzpicture}
\draw (0,0) rectangle (2,1);
\draw[>=stealth, <-] (1,0) -- (1,1);
\end{tikzpicture} 

but how do I fill the rectangle with circles as shown and how do I apply a shading to the arrow?

share|improve this question
    
About the arrow: How would you draw an arrow filled with a gradient? –  Jake Feb 18 '13 at 16:19
    
@jake do you think picture mode would be easier? –  David Carlisle Feb 18 '13 at 16:36
    
@DavidCarlisle: Actually, in this case I think it might be. –  Jake Feb 18 '13 at 16:37
2  
@Kate: (Just kidding, TikZ is definitely easier for something like this for everybody but David) –  Jake Feb 18 '13 at 16:39
2  
Related: tikz: Distribute evenly and randomly circles –  Torbjørn T. Feb 18 '13 at 16:41

3 Answers 3

up vote 11 down vote accepted

The answer Torbjørn points in the comments is related, but the circles there have always the same radius.

Another approach:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{fadings,shapes.arrows,shadows}

\usepackage{xparse}

\tikzfading[name=arrowfading, top color=transparent!0, bottom color=transparent!95]
\tikzset{arrowfill/.style={#1,general shadow={fill=black, shadow yshift=-0.8ex, path fading=arrowfading}}}
\tikzset{arrowstyle/.style n args={3}{draw=#2,arrowfill={#3}, single arrow,minimum height=#1, single arrow,
single arrow head extend=.3cm,}}

\NewDocumentCommand{\tikzfancyarrow}{O{2cm} O{FireBrick} O{top color=OrangeRed!20, bottom color=Red} m}{
\tikz[baseline=-0.5ex]\node [arrowstyle={#1}{#2}{#3}] {#4};
}

% Parameters

\def\height{5}
\def\width{10}
\def\numpoints{500}
\def\maxpointwidth{1.75}

\begin{document}


\begin{tikzpicture}
\path (0,0) rectangle (\width,\height);

\foreach \point in {1,...,\numpoints}{
  \pgfmathparse{random()}
  \pgfmathsetmacro\xpos{\width*\pgfmathresult}
  \pgfmathparse{random()}
  \pgfmathsetmacro\ypos{\height*\pgfmathresult}
  \pgfmathrandom{0.1,\maxpointwidth}
  \let\pointwidth\pgfmathresult

  \node[circle,inner sep=\pointwidth pt,fill=blue!30] (point-\point) at (\xpos,\ypos) {};
}

\node [arrowstyle={\height cm}{black}{top color=orange,bottom color=yellow,shape border rotate=270}] at (\width/2,\height/2) {};

\end{tikzpicture}


\end{document}

enter image description here

This uses Fancy arrows with TikZ to create the gradient and the various parameters could be set in the preamble.


This could be probably an overkilling solution, but allows to achieve an higher customization:

\documentclass[tikz,png]{standalone}

\usepackage{tikz}
\usetikzlibrary{fadings,shapes.arrows,shadows}

\usepackage{xparse}
\newif\ifshadecircle
\pgfkeys{/tikz/.cd,
     height rect/.initial=5,
     height rect/.get=\height,
     height rect/.store in=\height,
     width rect/.initial=10,
     width rect/.get=\width,
     width rect/.store in=\width,
     num points/.initial=500,
     num points/.get=\numpoints,
     num points/.store in=\numpoints,
     point width/.initial=1.5pt,
     point width/.get=\maxpointwidth,
     point width/.store in=\maxpointwidth,
     point style type/.is choice,
     point style type/fill/.style={fill=\pointcolor},
     point style type/radial shade/.style={inner color=\pointinnercolor,outer color=\pointoutercolor},
     point style type/vertical shade/.style={top color=\pointtopcolor,bottom color=\pointbottomcolor},
     point style type/horizontal shade/.style={left color=\pointleftcolor,right color=\pointrightcolor},
     point style/.initial={/tikz/point style type/fill},
     point style/.get=\pointstyle,
     point style/.store in=\pointstyle,
     point fill color/.initial=blue!30,
     point fill color/.get=\pointcolor,
     point fill color/.store in=\pointcolor,
     point inner color/.initial=white,
     point inner color/.get=\pointinnercolor,
     point inner color/.store in=\pointinnercolor,
     point outer color/.initial=blue!30,
     point outer color/.get=\pointoutercolor,
     point outer color/.store in=\pointoutercolor,
     point top color/.initial=white,
     point top color/.get=\pointtopcolor,
     point top color/.store in=\pointtopcolor,
     point bottom color/.initial=blue!30,
     point bottom color/.get=\pointbottomcolor,
     point bottom color/.store in=\pointbottomcolor,
     point left color/.initial=blue!30,
     point left color/.get=\pointleftcolor,
     point left color/.store in=\pointleftcolor,
     point right color/.initial=white,
     point right color/.get=\pointrightcolor,
     point right color/.store in=\pointrightcolor,
     arrow top color/.initial=orange,
     arrow top color/.get=\arrowtopcolor,
     arrow top color/.store in=\arrowtopcolor,
     arrow bottom color/.initial=yellow,
     arrow bottom color/.get=\arrowbottomcolor,
     arrow bottom color/.store in=\arrowbottomcolor,
     arrow border color/.initial=black,
     arrow border color/.get=\arrowbordercolor,
     arrow border color/.store in=\arrowbordercolor,
}

\tikzfading[name=arrowfading, top color=transparent!0, bottom color=transparent!95]
\tikzset{arrowfill/.style={#1,general shadow={fill=black, shadow yshift=-0.8ex, path fading=arrowfading}}}
\tikzset{arrowstyle/.style n args={3}{draw=#2,arrowfill={#3}, single arrow,minimum height=#1, single arrow,
single arrow head extend=.15cm,}}

\pgfkeys{/tikz/random point diagram/.code={
   \path (0,0) rectangle (\width,\height);

   \foreach \point in {1,...,\numpoints}{
     \pgfmathparse{random()}
     \pgfmathsetmacro\xpos{\width*\pgfmathresult}
     \pgfmathparse{random()}
     \pgfmathsetmacro\ypos{\height*\pgfmathresult}
     \pgfmathparse{random()}
     \pgfmathsetmacro\pointwidth{\maxpointwidth*\pgfmathresult}

     \node[circle,inner sep=\pointwidth pt, \pointstyle] (point-\point) at (\xpos,\ypos) {};
   }

   \node [arrowstyle={\height cm}{\arrowbordercolor}{top color=\arrowtopcolor, bottom color=\arrowbottomcolor,shape border rotate=270}, anchor=north] at (\width/2,\height) {};
  }
}

% that's just an alias for \node
\makeatletter
\def\drawdiagram{\tikz@path@overlay{node}}
\makeatother

\begin{document}

\begin{tikzpicture}
\drawdiagram[random point diagram] at (0,0) {};
\end{tikzpicture}

\begin{tikzpicture}[height rect=4,width rect=8,
 num points=600,
 point style={/tikz/point style type/vertical shade}, 
 point top color=white,
 point bottom color=orange,
 arrow border color=violet,
 arrow top color=violet!50!magenta!80,
 arrow bottom color=magenta!20]
\drawdiagram[random point diagram] at (0,0) {};
\end{tikzpicture}

\end{document}

The first example with the default values gives the previous picture, while the second customized example:

enter image description here

share|improve this answer
    
With two arguments, pgfmathrandom{x,y} generates a random integer... –  Paul Gaborit Feb 21 '13 at 22:06
    
My original idea was in that direction, but then I thought: "maybe this ends up with points on the grid" so I used the other way. Do you think I'm introducing too much correlation in the point generation? –  Claudio Fiandrino Feb 22 '13 at 8:24
    
The call of pgfmathrandom with two arguments is used only for \pointwidth. –  Paul Gaborit Feb 22 '13 at 8:45
    
That's right: thanks. :) I'll edit in a minute. –  Claudio Fiandrino Feb 22 '13 at 10:03
    
You may use something like \pgfmathsetmacro\pointwidth{rnd*(\maxpointwidth-0.1)+0.1}... –  Paul Gaborit Feb 22 '13 at 10:55

The \foreach loop construct and \pgfmathramdominteger are your friend:

\documentclass{standalone}
\usepackage{tikz}

\usetikzlibrary{shapes.arrows, fadings}

\begin{document}
\begin{tikzpicture}
    \foreach \x in {1,...,300}
        {
            \pgfmathrandominteger{\a}{5}{995}
            \pgfmathrandominteger{\b}{5}{395}
            \pgfmathrandominteger{\c}{30}{60}
            \fill[shade=blue!80!white] (0.01*\a,0.01*\b) circle (0.001*\c);
        };
    \node at (5,2) [
        right color=red!80!yellow,
        left color = red!20!yellow,
        single arrow,
        single arrow head extend=0.2cm,
        single arrow tip angle=110,
        single arrow head indent=0.05cm,
        minimum height=4cm,
        inner sep=1pt,
        shading angle=90+90,
        rotate=270
    ] {};
\end{tikzpicture}
\end{document}

enter image description here

With thanks to Jake for the link to How would you draw an arrow filled with a gradient?, where I copied the arrow from.

share|improve this answer

Just for fun with PSTricks and it is not supposed to be the correctest way to go. Please feel free to edit.

enter image description here

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-grad}% for gradient
\SpecialCoor
\newpsstyle{mygradient}
{
    fillstyle=gradient,
    gradbegin=orange,
    gradend=yellow,
    %gradangle=90,
    gradmidpoint=1,
}   
\begin{document}
\begin{pspicture}(8,6)
    \psLoop{500}{\pscircle*[linecolor=blue!80!white]
        (!rand 800 mod 100 div rand 600 mod 100 div){!rand 100 mod 1000 div}}
    \pspolygon[style=mygradient](3.75,6)(3.75,1)(3.25,1)(4,0)(4.75,1)(4.25,1)(4.25,6)
\end{pspicture}
\end{document}

Note that I assumed that the bubbles are allowed to overlap each other.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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