Message Boards Message Boards


A filled glass or the mathematics of dioptric anamorphism

Posted 1 month ago
4 Replies
13 Total Likes

Back in 1638, Minim Father Jean François Niceron wrote a ground-breaking book for architects and artists alike: "La Perspective Curieuse". In this book he describes the mathematical methods to obtain drawings and paintings using perspective, catoptric anamorphism (with cylindrical and conical mirrors) and dioptric anamorphism by means of refraction in crystals.

enter image description here

The refractive telescope in the above illustration used a polyhedral lens consisting of 8 crystals and was meant to recompose 8 pictures into a single one by means of refraction. Although a digital reconstruction of the apparatus exists, the actual telescope was lost in a Venice flood. It would be a mathematical tour de force to study the mathematics of the refractive optics through the multi faced lens. To get a feel of what is refractive anamorphism (contrary to catoptric anamorphism), I made a short study about anamorphism by means of refraction in a cylinder filled with a sugar solution. The crystals used by Niceron had a refractive index of at least 1.55. The highest index I could obtain was 1.448 by using a 65% sucrose solution inside a cylindrical glass. Let us first see what we can do with Mathematica to emulate refraction through a solution filled cylinder and create a dioptric anamorphic image.

enter image description here

The above optical ray diagrams show a 3D view (left) and a 2D horizontal {top right) and vertical (bottom right) cross section. A ray leaving the point R in the x-y plane will meet the viewer's eye at V. This after being refracted at intersection points Q2 between air and cylinder liquid and Q1 between liquid and air. The resulting light ray from V to R is a combination of: 1. refraction in the horizontal plane through Q1 and Q2 (top right) and 2. refraction in the vertical plane through Q1 and Q2 (bottom right). The result is that the viewer sees the point R in the x-y plane as a virtual point P in a view plane inside the cylinder. R can be defined as the dioptric (refractive) anamorphic of P or, inversely, P can be defined as the refracted image of R. In both cases, Snell's law of refraction applies:

enter image description here

n1 and n2 are the two refractive indices: 1.448 for air -> sucrose solution and 1/1.448 for sucrose solution -> air. Theta 1 and Theta 2 are the incident and refracted angles. Since the relation between anamorphic points R and virtual points P is rather complex, we use an interpolation function ifR to compute the coordinates of R in the x-y plane from the coordinates of P in the view plane. The following code makes a table tblR of R and P coordinates using Snell's law and plain geometry. The interpolation function ifR is derived from the data in tblR:

tblR = With[{c = 1, yv = 10, zv = 10, 
    nr = 1.448},(*the cylinder radius is 1 and the viewpont is at {10,
     Module[{yc, ptVh, ptVv, ptPh, ptPv, ptQ1h, ti1, tr1, ti1v, tr1v, 
       ptQ2h, ti2, tr2, ti2v, tr2v, ptQ1v, ptQ2v, ptRv, ptR},
      (*view plane location and width*)yc = c^2/yv; 
      wi = Round[c Sqrt[1 - c/yv^2], .001];
      ptVh = {yv, 0}; ptPh = {yc, xp}; ptVv = {yv, zv}; 
      ptPv = {yc, zp};
      (*incoming intersection point Q1*)
      ptQ1h = 
        NSolveValues[{Element[{x, y}, Line[{ptPh, ptVh}]] \[And] 
           x^2 + y^2 == c^2}, {x, y}];
      (*angle of incidence*)ti1 = VectorAngle[ptVh - ptQ1h, ptQ1h];
      (*angle of refraction*)tr1 = Sign[xp] ArcSin[Sin[ti1]/nr];
      ptQ2h = 
         NSolveValues[{Element[{x, y}, 
              ptQ1h, -AngleVector[-tr1 + ArcTan @@ ptQ1h]]] \[And] 
            x^2 + y^2 == c^2}, {x, y}], First];
      (*outgoing intersection point Q2*)
      (*angle of incidence*)
      ti2 = tr1;
      (*angle of refraction*)tr2 = ArcSin[Sin[ti2]*nr];
      (*incoming ray*)
(*intersection point*)
      ptQ1v = 
        NSolveValues[{Element[{x, y}, Line[{ptVv, ptPv}]] \[And] 
           x == ptQ1h[[1]]}, {x, y}];
      (*angle of incidence*)ti1v = VectorAngle[ptVv - ptQ1v, {1, 0}];
      (*angle of refraction*)tr1v = -ArcSin[Sin[ti1v]/nr];
      (*outgoing ray*)
      (*intersection point*)
      ptQ2v = 
        NSolveValues[{Element[{x, y}, 
            HalfLine[ptQ1v, {-1, Tan[tr1v]}]] \[And] 
           x == ptQ2h[[1]]}, {x, y}];
      (*angle of incidence*)ti2v = tr1v;
      (*angle of refraction*)tr2v = ArcSin[Sin[ti2v]*nr];
      ptRv = 
        NSolveValues[{Element[{x, y}, 
            HalfLine[ptQ2v, {-1, Tan[tr2v]}]] \[And] y == 0}, {x, 
      ptR = 
        NSolveValues[{Element[{x, y}, 
             AngleVector[tr2 + ArcTan @@ ptQ2h]]] \[And] 
           x == ptRv[[1]]}, {x, y}];
      {{xp, zp}, ptR}], {zp, .75, 7.5, .05}, {xp, -.99, .99, .02}]];
ifR = Interpolation[Flatten[tblR, 1]]

enter image description here

Below, we apply the function ifR to a set of concentric circles in the view plane and compute the corresponding refractive anamorphic mapping in the x-y plane. The hatched disk is the cross section of the cylinder and shows its relative size and position.

enter image description here

Using the same function ifR, we can make an animation in 3D of a point rotating around a circle in the view plane and see it traveling around the circle's refractive anamorphic image in the x-y plane:

enter image description here

We are now ready to experiment with some real images. The first trial is with the the "Bugs Bunny" popular curve. We map the function ifR to the point coordinates and get the refractive anamorphic image:

centerAndScale[g_] := 
 Module[{lns, pts, xMin, xMax, yMin, yMax, centeredLns, scaledLines},
  lns = Cases[g[[1]], _Line, \[Infinity]]; 
  pts = Flatten[lns[[All, 1]], 1]; {xMin, xMax} = 
   MinMax[pts[[All, 1]]]; {yMin, yMax} = MinMax[pts[[All, 2]]]; 
  centeredLns = Map[#1 - {(xMax + xMin)/2, +yMin} &, lns, {3}]; 
  Map[1.35` #1/Abs[xMax - xMin] &, centeredLns, {3}]]
bugsbunnyPrimitives = 
      Entity["PopularCurve", "BugsBunnyCurve"]["ParametricEquations"][
       t], {t, 0, 40 \[Pi]}]]] /. {x_?NumericQ, y_?NumericQ} :> 
    1.35 {x, 1.05 y + 1};
refractedPrimitives = MapAt[ifR @@ # &, prims, {All, 1, All}];
Graphics[{{HatchFilling[], Disk[]}, Circle[], AbsoluteThickness[1], 
  refractedPrimitives}, Axes -> False, Ticks -> None, 
 AxesOrigin -> {0, 0}]

enter image description here

Below demonstrates how the printout of the anamorphic image looks like the original after refraction through a glass filled with a sucrose solution:

enter image description here

The same can be done with any photographic image. We use the function ImageSquareDivide from the Wolfram Function Repository to divide the image into a set of colored polygons and map the function ifR to the coordinates of polygon's vertices:

mandrill = ImageResize[ExampleData[{"TestImage", "Mandrill"}], 50];
gr = ResourceFunction["ImageSquareDivide"][
    mandrill] /. {x_, y_} -> .7 {x, y + 5};
Graphics[gr, Axes -> True, AxesOrigin -> {0, 0}];
grR = Quiet@MapAt[ifR @@ # &, gr, {All, -1, 1, All}];
Graphics[{{HatchFilling[], Disk[]}, Circle[], grR}, 
 AxesOrigin -> {0, 0}]

enter image description here

Here again, we see the original image after refraction of the anamorphic printout:

enter image description here

Refraction does not result in the strong deformations obtained by reflection in cylindrical mirrors. The use of polished glass lenses or crystals as documented by Niceron would undoubtedly result in more spectacular results.

4 Replies

enter image description here -- you have earned Featured Contributor Badge enter image description here Your exceptional post has been selected for our editorial column Staff Picks and Your Profile is now distinguished by a Featured Contributor Badge and is displayed on the Featured Contributor Board. Thank you!

Posted 1 month ago

From mirror to lens, history, animation, code and experiment. ------ I love to read Erik's story.

One suggestion, refractive index of water (1.33) and glass (1.5) are different, the cylinder lens can be modeled in a composed way, with consider the glass thickness ?

Posted 1 month ago

Glad you like this, Frederick. I know there is also refraction through the (relatively thin) glass wall of the drinking glass. The error is more significant toward the edges where there is a very sharp angle of incidence. This is why I avoided the edges and I put a smaller image in the middle! It would take quite some computation to include the glass wall. The book by Niceron I mentioned, is very interesting indeed. It is remarkable that back in 1635 people were writing computational essays (albeit without the help of Mathematica)!

Posted 9 days ago

Dear Erik,

I hope this message finds you well.

I am an artist and I'm fascinated by your research and work.

Do you mind if I contact you about a new project that I am working on now, that has a lot to do with anamorphosis, refraction and reflection.

Apologies for this unusual way of contacting you, I couldn't find your personal site or email.

Best regards,


Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract