I wanted to draw a prism compressor with the respective beamlines. The general setup works, but the exact control of the beam alignment within the prisms fails.

Here is the code that I have so far:


tx@addDict begin Red Green Blue end}% 


\i\space 620 590 sub 59 div mul 590 add tx@addDict begin wavelengthToRGB end }%
\drawbeam[beamangle=\i\space 0.1 mul 3 sub]{1}{2-}


enter image description here

"Prism compressor"

Two problems:

  • how to get the ray drawn within the first prism
  • how to align the rays horizontally within the second prism

If someone could help me on that I would be really grateful :). Thanks in advance


4 Answers 4


Not my solution, it's from Christoph, the package author



% uncomment for debugging
% \psset[optexp]{pswarning, useNA=false}

\definecolor[ps]{bl}{rgb}{tx@addDict begin Red Green Blue end}%


\addtopsstyle{Beam}{linecolor=bl,linewidth=0.3\pslinewidth, beampathskip=1}
     \r\space 620 590 sub 59 div mul 590 add tx@addDict begin wavelengthToRGB end }%
  \drawbeam[n=3.3 0.002 \r\space mul add, beampos=\r\space -0.0002 mul](S1){1-3}


enter image description here

  • That looks great - thank you. Am I right in the assumption that to find the right n to hit the second prism is just a matter of trial and error?
    – spookyfw
    Commented Jul 11, 2013 at 9:14
  • yes, that's true
    – user2478
    Commented Jul 11, 2013 at 11:11
  • actually the search for n can be completely circumvented by disabling raytracing and using the loadbeampoints again...maybe useful for systems that involve more components...
    – spookyfw
    Commented Jul 11, 2013 at 11:26
  • setting \psset[optexp]{pswarning, useNA=false} makes sense
    – user2478
    Commented Jul 11, 2013 at 20:43

Slightly off-topic and probably useless for an answer, but after seeing this question I couldn't resist but write a LaTeX document that produces the following picture:

enter image description here

See the code below. I have only a limited understanding of physics (got a bit rusty on refraction indices), but I hope that it actually computes the refraction angles correctly. The exact values of the refraction indices were chosen just for the dramatic effect. :)





% Define rainbow colors
\def\colors{{"red", "orange", "yellow", "green", "blue", "purple"}}



\coordinate (O1) at (-3, -3);         % Bottom left corner of picture
\coordinate (O2) at ( 3,  3);         % Top right corner of picture
\coordinate (A)  at (-4, -0.2);       % Start point of incoming ray
\coordinate (B)  at ( 4, 2.2);        % End point of incoming ray if prism weren't there
\coordinate (BL) at (-1, 0);          % Bottom left corner of the prism
\coordinate (BR) at (1, 0);           % Bottom right corner of the prism
\coordinate (T)  at (0, {sqrt(3)});   % Top corner of the prism
\coordinate (C)  at (0, {sqrt(3)/2}); % Center of the prism

% Clip and draw black background
\clip (O1) rectangle (O2);
\fill[black] (O1) rectangle (O2);

% Define top and bottom coordinates of ray
\coordinate (A1)  at ($(A)+(0,0.5\rayWidth)$);
\coordinate (A2)  at ($(A)+(0,-0.5\rayWidth)$);
\coordinate (B1)  at ($(B)+(0,0.5\rayWidth)$);
\coordinate (B2)  at ($(B)+(0,-0.5\rayWidth)$);

% Draw prism
\foreach \z in {0, 0.5, ..., 10} {
   \fill[rounded corners=\d pt, black!\s] ($(T)!\d pt!(C)$) -- ($(BR)!\d pt!(C)$) -- ($(BL)!\d pt!(C)$) -- cycle;

% Draw incoming ray
\path[name path=left side]  (T) -- (BL);
\path[name path=right side] (T) -- (BR);
\path[name path=mid line] (T) -- ($(BR)!.5!(BL)$);
\path[name path=ray top] (A1) -- (B1);
\path[name intersections={of=left side and ray top,by=P1}];
\path[name path=ray bottom] (A2) -- (B2);
\path[name intersections={of=left side and ray bottom,by=P2}];
\fill [white, thick] (A1) -- (P1) -- (P2) -- (A2) -- cycle;

% Calculate angle of incidence

% Calculate refraction angles

% Draw shaded "triangle" inside the prism
\path[name path=path1] (P1) -- ($(P1)!1!-\deltaAngleTopL:(B1)$);
\path[name intersections={of=mid line and path1,by=Q1}];
\path[name intersections={of=right side and path1,by=R1}];
\path[name path=path2] (P2) -- ($(P2)!1!-\deltaAngleBottomL:(B2)$);
\path[name intersections={of=mid line and path2,by=Q2}];
\path[name intersections={of=right side and path2,by=R2}];
\shade[shading=axis, left color=white, right color=black] 
  (P1) -- (Q1) -- (Q2) -- (P2) -- cycle;

% Calculate incidence angles


% Draw rainbow
\coordinate (T1) at ($(P1)!12!-\deltaAngleTopR:(Q1)$);
\coordinate (T2) at ($(P2)!15!-\deltaAngleBottomR:(Q2)$);

\foreach \i in {0, ..., 5} {
   \fill[fill=\color] ($(R1)!\a!(R2)$) -- ($(T1)!\a!(T2)$) -- ($(T1)!\b!(T2)$) -- ($(R1)!\b!(R2)$) -- cycle;

And here is an animated version: I am on fire! :)

enter image description here

Homework exercise: Write a LaTeX code that produces an image of a famous building in London with a pig flying above it.

  • 6
    \usepackage[dsotm]{pinkfloyd} :) Commented Jul 11, 2013 at 1:00
  • 1
    haha...looks great..I will include that in my Master-thesis instead of the compressor...
    – spookyfw
    Commented Jul 11, 2013 at 9:15
  • Whoah that animation renders great!! Brain damage!
    – percusse
    Commented Jul 21, 2013 at 15:14

Inspired by the other answers, I added a new line style fade to the pst-optexp package version 4.5.

  \optprism[prismalign=center, linecolor=white](A)(B)(C)
    tx@addDict begin Red Green Blue end}%
  \addtopsstyle{Beam}{linestyle=fade, beaminsidelast, fadeto=black}
    \drawbeam[n=1.5 \i\space 0.003 mul add, linecolor=white, beampathskip=1]{1-2}
    \pstVerb{\i\space 650 400 sub 59 div mul 400 add 
      tx@addDict begin wavelengthToRGB end }%
    \drawbeam[n=1.5 \i\space 0.003 mul add, linecolor=bl, beampathskip=2, fadefuncname=linear, linewidth=0.3\pslinewidth]{-}%
  • Your drawing is very nice, but not correct, unfortunately; the colours need to be reversed since the violet light will bend the most and the red the least. I would love to use a correct version of your drawing so how I can do the reversal of the colours? Commented Aug 16, 2023 at 18:54
  • 1
    @SvendTveskæg argh, yes, you are right. Try n=1.68 \i\space 0.003 mul sub for the drawbeam calls. That reverses the drawing of the colors
    – Christoph
    Commented Aug 24, 2023 at 17:37

and another dsotm with colors defined by its wavelength

enter image description here

\usepackage{multido} \SpecialCoor
\pnode(! /AnglePrisme 30 def /AnglePlan1 19 def /AnglePlan2 54 def
    /C1x -8 def  /C1y 7 def  /C2x 11 def  /C2y 5 def
    /u 1.5 def
    /g1x AnglePrisme sin neg def % -sin(A/2)
    /g1y AnglePrisme cos def     %  cos(A/2)
    /u1x AnglePlan1 sin neg def  /u1y AnglePlan1 cos neg def
    /E1x C1x u u1x mul add def   /E1y C1y u u1y mul add def
    /n1x AnglePlan1 cos def     /n1y AnglePlan1 sin neg def
    /Lambda {E1x g1y mul E1y g1x mul neg add n1y g1x mul neg n1x g1y mul add div neg} bind def
    /i1x {E1x Lambda n1x mul add} bind def /i1y {E1y Lambda n1y mul add} bind def
    0 0){Stockage_parametres_prisme}
     (O)(! 7 90 AnglePrisme add cos mul 7 90 AnglePrisme add sin mul)%
        (! 7 90 AnglePrisme sub cos mul 7 90 AnglePrisme sub sin mul)
\multido{\iLAMBDA=400+5}{80}{\pstVerb{ /lambda \iLAMBDA\space def }%
\pnode(! /L2 {lambda 1e-3 mul dup mul} bind def
    /N {1 1.539259 L2 mul L2 0.011931 sub div add
          0.247621 L2 mul L2 0.055608 sub div add
          1.038164 L2 mul L2 116.416755 sub div add sqrt} bind def
    /alpha1 AnglePlan1 AnglePrisme add def /sinB1 alpha1 sin N div def
    /B1 sinB1 asin def /Delta1 AnglePrisme B1 sub def
    /g2x AnglePrisme sin def  /g2y AnglePrisme cos def
    /d12x Delta1 cos def % d12x
    /d12y Delta1 sin def % d12y
    /Lambda2 {i1x g2y mul i1y g2x mul sub d12y g2x mul d12x g2y mul sub div} bind def
    /i2x {i1x Lambda2 d12x mul add} bind def /i2y {i1y Lambda2 d12y mul add} bind def
    /B2  AnglePrisme 2 mul B1 sub def /sinA2 N B2 sin mul def
    /alpha2 sinA2 asin def
    /u2x AnglePlan2 sin def /u2y AnglePlan2 cos neg def
    /Delta2 alpha2 AnglePrisme sub def
    /d2x Delta2 cos def /d2y Delta2 sin def /s2x i2x C2x sub def /s2y i2y C2y sub def
    /dA d2x u2y mul d2y u2x mul sub def  /dM d2x s2y mul d2y s2x mul sub def
    /r2x C2x dM dA div u2x mul add def  /r2y C2y dM dA div u2y mul add def
0 0){factice}
\pnodes(! C1x C1y){C1}(! C2x C2y){C2}(! E1x E1y){E1}(! i1x i1y){I1}(! i2x i2y){I2}(! r2x r2y){R2}
\psline[linecolor=prisme](I1)(I2)(R2)} \psline[linecolor=white,linewidth=0.5mm](E1)(I1)
\psline[linecolor=white,linewidth=0.5mm,arrowscale=2]{->}(E1)(!i1x E1x add 2 div i1y E1y add 2 div)

  • 1
    Great answer, Herbert! :) Commented Jul 19, 2013 at 11:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .