# Automatically generate graphics which shows light diffusion on a rough surface

I just want to make an image like this (using tikz or pstricks) of light reflexion and diffusion: What I am interested in is, how this can be done (semi)-automatically via tikz or pstricks:

• specify number (and spacing) of equi-distant incoming light rays and their angle
• draw the surface with a parameter r which controls the "roughness" r=0 is like the picture above, for larger r's the sourface becomes more and more rough (like the graph of a piecewiese linear continous function with more and more parts if r becomse larger)
• draw the reflected part such that the law reflexion (equal angles) is satisfied "locally"

Here's an attempt in Metapost. Using the direction x of y macro to find the required angle of reflection.

Here's what you get with r=0: And with r=0.33: prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1);

path base, ray[]; u = 5mm;

r=0.33;

base = (-6u,0) for x=-5.8u step 0.2u until 5.8u: -- (x,r*normaldeviate) endfor -- (6u,0);
draw base
-- point infinity of base shifted (0,-u)
-- point 0        of base shifted (0,-u) -- cycle
withcolor .67 red;

theta = -45;

for i=-2 upto 2:
ray[i] = (left--right) scaled 6u rotated theta shifted (i*u,0);
b := ypart(ray[i] intersectiontimes base);
drawarrow point 0 of ray[i]
-- point b of base
-- point 0 of ray[i] reflectedabout(point b of base, direction b of base
shifted point b of base
endfor

label.urt("r=" & decimal r, point 0 of base);

endfig;
end.


If you want to do something fancier with the reflected ray, then you can save it as a path instead of just drawing it. This lets you draw parts of it in different colours, or draw arrows part of the way along it. Like this: To get this effect, you can change the inner loop like this:

for i=-2 upto 2:
ray[i] = (left--right) scaled 6u rotated theta shifted (i*u,0);
b := ypart(ray[i] intersectiontimes base);
ray[i] := point 0 of ray[i]
-- point b of base
-- point 0 of ray[i] reflectedabout(point b of base, direction b of base
shifted point b of base
drawarrow subpath(0,0.3) of ray[i];
drawarrow subpath(0.3,1.7) of ray[i];
draw      subpath(1.7,infinity) of ray[i];
endfor


So instead of just drawing the reflected ray, this time I have stored it back in ray[i] (notice that I've used the assignment operator := to overwrite the previous value of the variable), and then drawn it afterwards in three segments to get the arrow heads in nice places.

Note: Since this solution depends on Metapost's normaldeviate function to generate random numbers, I recommend that you stick to the default number system. There is currently (MP version 1.902) a horrible bug in the way that the new number systems double and decimal implement the constants required for normaldeviate. As a result you will get rather wild results if you use either of these new number systems. I have raised an issue for this on the MP bug tracker.

• Amazing! Thank you very much. Just a little detail: How can it, such that the arrow tips are in the middle of the incoming and outcoming lines (and not at the end of the outcoming ones)? – Julia Sep 28 '14 at 18:22

Our TikZers getting lazy I guess. This can't get away without a TikZ answer :P Same idea but using decorations (over and over again).

\documentclass[tikz]{standalone}
\usetikzlibrary{decorations.pathmorphing,decorations.markings,calc}
\begin{document}
\begin{tikzpicture}
postaction=decorate,
decoration={markings,
mark= between positions 1cm and 3cm step 5mm with {% Places five of them
\node[transform shape,inner sep=1pt]
(mark-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) {};
}
}
]{
decorate[decoration={random steps,segment length=1.5mm,amplitude=1pt}]%Roughness is amplitude
{
(0,0) -- ++(4,0)
}
} -- ++(0,-5mm) -- ++(-4cm,0) -- cycle;
\foreach \x in {1,2,...,5}{
\draw[postaction=decorate,
decoration={markings,
mark=between positions 0.25 and 0.75 step 0.5 with{\arrow{latex}}
}]
(mark-\x.center)+(135:2cm)  --(mark-\x.center)
--($(mark-\x.north west)!2cm!45:(mark-\x.north east)$);
}
\end{tikzpicture}
\end{document} I've just seen that there is still missing a PSTricks solution ;)

Using at least version 5.0 of the pst-optexp package allows to use arbitrary paths as refractive or reflective surfaces.

Here is how you can simulate a rough surface. Basically you must use \pssavepath (from pst-intersect) to save some path to be used later as reflective surface: \documentclass[margin=5pt, pstricks]{standalone}
\usepackage{pst-optexp}
\makeatletter
\newOptexpTripole{roughsurface}
\def\roughsurface@nodes{%
\pssavepath[linestyle=none, arrows=-,ArrowInside=-]{\oenode@Path{A}}{%
\code{0 srand}% provides reproducable results
\moveto(!-3 Rand 0.5 sub 0.1 mul)
\multido{\r=-2.7+0.3}{20}{%
\lineto(!\r\space Rand 0.5 sub 0.1 mul)}%
}%
\newOptexpComp{%
{0 0} tx@IntersectDict /\PIT@name{\oenode@Path{A}} get 0 0 refl {PathIfc}
1 }%
}%
\def\roughsurface@comp{%
\pstracecurve{\oenode@Path{A}}
}%
\makeatother
\begin{document}
\begin{pspicture}(10,3)
\optplane[angle=90](1,3)
\roughsurface(0,3)(5,0)(10,3)