27

I just want to make an image like this (using tikz or pstricks) of light reflexion and diffusion:

Light 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"
30

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:

enter image description here

And with r=0.33:

enter image description here

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 
                                                              rotatedabout(point b of base, 90));
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:

enter image description here

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 
                                                              rotatedabout(point b of base, 90));
  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.

  • 2
    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
25

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}
\shadedraw[thick,top color=gray!10,bottom color=gray,
  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}

enter image description here

8

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:

enter image description here

\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)
\addtopsstyle{Beam}{beamalign=abs, beamangle=-45, arrows=->, arrowscale=2}
\multido{\r=0+0.3}{6}{%
\drawbeam[beampos=\r]{1}{2}{1}}
\end{pspicture}
\end{document}

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.