Remember in first-year physics when you inked zone plates onto glass and diffracted spots and images onto a screen further down an optics rail?

Me neither. For some obscure reason my own freshers’ physics neglected to include that experiment. I set out to rectify the problem with a bit of openSCAD code. From the wikipedia description, zone plate rings toggle from transparent to opaque every time the radius satisfies the criteria:

Where is the ring number, is the wavelength of light, and is the focus distance.

Feel free to use the code, .svg file, or .png image below for your own zone plates. Everything is available under a Creative Commons Attribution License and can be found on Github: https://github.com/theBilder/zonePlates

//********************************************

//This code is provided under a Creative Commons Attribution license (creativecommons.org/). Feel free to use it any way you like, but please retain this comment header

//Q. Tyrell Davis

//thebilder.wordpress.com

//CC BY

//********************************************//Parameters

lambda = 550*pow(10,-3);

//wavelength of light (in mm). Taken as an average green here.zones = 15;

//number of zones. With too many zones the width of each zone will be too thin for practical fabricationfocal = 80;

//the focus distance for the zone platestrutWidth = .75;

//width of the struts holding the zone plate ringsfineness = 68;

//determines how smooth the circles arerandom = 1;

// 0 for ordered placement, 1 for random struts. Ordered placement will result in diffraction spikesuiStruts = 4;

//Number of struts holding zones in place

//End parameters

//Formulae used to define the zone plate are from en.wikipedia.org/wiki/Zone_platevRand = random * rands(0,1,uiStruts*zones);

plateRadius = sqrt((zones+1)*focal*lambda)+2; //sqrt((zones)*focal*lambda+(pow(n,2)*pow(lambda,2))/4);//uncomment to echo the thinnest ring width

echo(“thinnest ring = “,sqrt((zones)*focal*lambda+(pow(zones,2)*pow(lambda,2))/4)-sqrt((zones-1)*focal*lambda+(pow((zones-1),2)*pow(lambda,2))/4));

//echo(“plate radius = “,plateRadius);//uncomment to echo the approx resolution

//echo(sqrt((zones)*focal*lambda+(pow(zones,2)*pow(lambda,2))/4)-sqrt((zones-1)*focal*lambda+(pow((zones-1),2)*pow(lambda,2))/4));/

//Building the zone plate

difference(){

circle(r=plateRadius,$fn=fineness);

//translate([-55,-27.5]) square([85,55]); //comment the circle above and uncomment this to make a business cardfor(n = [0:2:zones]){

union(){

difference(){

circle(r= sqrt((n)*focal*lambda+(pow(n,2)*pow(lambda,2))/4),$fn = fineness);

circle(r= sqrt((n-1)*focal*lambda+(pow(n,2)*pow(lambda,2))/4),$fn = fineness);for(k = [1:uiStruts]){

rotate([0,0,(vRand[k*n-1])*360/uiStruts+k*360/uiStruts]){

translate([-.1+sqrt((n-1)*focal*lambda+(pow(n,2)*pow(lambda,2))/4),0,0]){

square([sqrt((n)*focal*lambda+(pow(n,2)*pow(lambda,2))/4),strutWidth],center = true);

}//translate

}//rotate

}//for}//difference

}//union

}//for}//difference