20111024

Animated Quasicrystals

Inspired by this recent Nobel prize, we've been playing with two-dimensional quasi-crystal patterns again. 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 ( for entertainment purposes entirely ), what happens when you make these plane waves travel, and also viewing the quasicrystals in log-transformed coordinates as shown in this earlier post. There are more animations over at the Imgur album.


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. I converted to black-and-white and 8-color indexed mode before saving to cut down on file size, and used about 80ms/frame for animation speed.
 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. The image on the right was actually rendered using the equation "C+=cos(abs(x*cos(t)+y*sin(t))*2*PI*stripes/N+phase);", with the absolute value added to enforce flow outward from the center.

Since quasicrystals are not periodic, 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. In the Imgur album, you can see that some crystals were lined up better than others. Brain massage.


Be sure to check out Keegan's implementation, which doubles as a nice introduction to coding in Haskell. Also, check out this in-browser JavaScript powered port.


10 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
  10. Thankyou very much for this, I enjoyed the article a lot.

    ReplyDelete