20111024

Animating quasicrystals

This post is inspired by the recent Nobel prize for the discovery of quasicrystals in nature.

We spoke briefly of quasicrystals previously : patterns that appear somewhat periodic but never actually repeat. Two-dimensional quasicrystals can be generated by summing together four or more plane waves. In collaboration with Keegan, we've explored what happens when you make these plane waves travel, and also viewing the quasicrystals in logarithmic coordinates as shown in this earlier post.

 

The Java code below generated sequences of images for animation. Once you have a series of images, you can use Gimp to make an animated GIF. (Convert to black-and-white and 8-color indexed mode before saving to reduce file size.)

import java.awt.image.BufferedImage;  
 import java.io.File;  
 import java.io.IOException;  
 import javax.imageio.ImageIO;  
 import static java.lang.Math.*;  
 public class QUASI1 {  
   public static void main(String [] args) throws IOException {  
     int k=4;     //numer of plane waves  
     int stripes = 27; //number of stripes per wave  
     int N = 800;   //image size in pixels  
     int N2 = N/2;  
     BufferedImage it = new BufferedImage(N,N,BufferedImage.TYPE_INT_RGB);  
     for (double phase=0; phase<2*PI; phase+=2*PI/30) {  
       for ( int i=0; i<N; i++ ) for ( int j=0; j<N; j++ ) {  
         double x = j-N2, y = i-N2; //cartesian coordinates  
         double theta = atan2(y,x); //log-polar coordinates  
         double r = log(sqrt(x*x+y*y));  
         double C=0;        // accumulator  
         for (double t=0; t<PI; t+=PI/k)  
           C+=cos((theta*cos(t)-r*sin(t))*stripes+phase);  
           // use the following line for cartesian crystals:  
           //C+=cos((x*cos(t)+y*sin(t))*2*PI*stripes/N+phase);  
         int c=(int)((C+k)/(k*2)*255);  
         it.setRGB(i,j,c|(c<<8)|(c<<16));  
       }  
       ImageIO.write(it,"png",new File("Test"+(int)(180*phase/PI)+".png")) ;  
     }  
   }  
 }  

To execute this code, copy it into a file names "QUASI1.java". Then, from the terminal, run "javac QUASI1.java", and finally "java QUASI1" to execute it. Or, paste it into your favorite Java IDE.

Changing K will change the degree of symmetry in the crystal. Changing N sets the size of the output images. Changing stripes sets how many wave cycles fit in the rendered image, with larger numbers leading to finer structure.

Since quasicrystals are aperiodic, it is not possible to wrap them around the log-polar "tunnel" ( seen on the left above ) such that two edges of the image meet perfectly. However, for quasicrystals composed of only a few plane waves, you can sometimes get two regions to align well enough to be unnoticeable, especially in black and white.
 
Be sure to check out Keegan's implementation, which doubles as a nice introduction to coding in Haskell.


9 comments:

  1. OO, so pretty. Net beans gets angry at me every time I try to run it, but I'm classifying that as a wetware problem for now.

    ReplyDelete
  2. What does it say? I didn't spend very much time explaining the code, I might have made a mistake.

    ReplyDelete
  3. Ok, I didn't run into trouble using Netbeans, but there are some details you need to watch out for.

    The code needs to be in a file called QUASI1.java ( or the class name needs to be changed to match the file name ).

    The code is set up for the "default" package. When netbeans creates a new project, it automatically puts all classes in a package with the same name as the project.

    You can fix this by moving the class file to the default project, or by adding the line "package (myprojectname);" to the very top of the source file.

    I would just "run file" instead of "run project", since I'm just using Java for a quick and dirty script. That's Shift+F6 on my version of netbeans.

    ReplyDelete
  4. You can fix this by moving the class file to the default **package, or by adding the line "package (myprojectname);" to the very top of the source file.

    ReplyDelete
  5. You can also just copy that main block into the tempated main block that Netbeans makes when you create a new project. Also copy over the import lines, or choose Source→Fix Imports to make sure you get all the right libraries.

    ReplyDelete
  6. run file and changing the class from default worked. I really should get around to actually learning java

    ReplyDelete
  7. also thank you!

    ReplyDelete
  8. Just saw a post on Boing Boing about the work of computer animation pioneer John Whitney. In his 1961 work "Catalog" there's a segment (at the 30-second point) that looks a lot like your animated quasicrystals:

    http://boingboing.net/2012/02/02/john-whitneys-1960s-computer.html

    Thought that you might enjoy it. It would be interesting to know the specific details of how he made that segment, which was done with an analog computer and a special camera setup.

    ReplyDelete
  9. Thanks ! I do wonder how they did it -- it doesn't look exactly the same, but may be a similar mechanism.

    ReplyDelete