Archive for July 2010

Just Some Julia Sets

So one of the neat side things I learned at GHP was how the Mandelbrot Set works. Somehow I had the impression that the Mandelbrot Set was really complicated so I had never looked up the details. But it is really crazy-simple, assuming you know what a complex number is. Anyways, once I learned this, I just had to cook up my own mini-fractal generator and explore. I didn’t actually draw the Mandelbrot (yeah, now that I understand the Mandelbrot just doesn’t excite me anymore): I’m drawing some julia sets which are a very close relative.

And I did it in Processing which made it extra easy and fun.

class Cnum //complex number
{

    float r; //real
    float i; //imaginary
    Cnum(float r_, float i_) {
        r = r_;
        i = i_;
    }

    String irep()
    {
        return "[" + r + " + " + i + "i]";
    }

    String prep()
    {
        float theta = arg();
        float r2 = sqrt((i*i) + (r*r));
        return "[r=" + r2 + " theta=" + theta + "]";

    }

    String toString() {
        return irep();
    }

    boolean isInfinity()
    {
        return r == Float.POSITIVE_INFINITY;
    }

    boolean isZero()
    {
        return r == 0 && i == 0;
    }

    Cnum conj() 
    {
        return new Cnum(r, i*-1);
    }

    Cnum neg()
    {
        return new Cnum(-r,-i);
    }


    float arg()
    {
	return atan2(i,r);
    }

    float abs()
    {
        return sqrt(r*r + i*i);
    }
} 	

Cnum add(Cnum a, Cnum b)
{
    return new Cnum(a.r + b.r, a.i + b.i);
}
Cnum sub(Cnum a, Cnum b)
{
    return new Cnum(a.r - b.r, a.i - b.i);
}

Cnum mul(Cnum a, Cnum b)
{
     return new Cnum(a.r*b.r - a.i*b.i, a.i*b.r + a.r*b.i);
}

int WIDTH = 500;
int HEIGHT = 500;
boolean changeOnMove = true;    


void plot(Cnum a)
{
    float xPercentage = (a.r - upperLeft.r)/(lowerRight.r - upperLeft.r);
    float yPercentage = (a.i - lowerRight.i)/(upperLeft.i - lowerRight.i);
    int x = round(xPercentage*WIDTH);
    int y = round((1 - yPercentage)*HEIGHT);
    point(x, y);
}

Cnum convert(int x, int y)
{
    float xPercentage = x/float(WIDTH);
    float yPercentage = y/float(HEIGHT);
    return new Cnum((lowerRight.r - upperLeft.r)*xPercentage + upperLeft.r,
		    (upperLeft.i - lowerRight.i)*(1 - yPercentage) + lowerRight.i);
}

Cnum upperLeft, lowerRight;


PFont fontA;

void setup() {
    upperLeft = new Cnum(-2, 2);
    lowerRight = new Cnum(2, -2);
    size(WIDTH, HEIGHT);
    stroke(226);

    fill(226);

  fontA = loadFont("SansSerif.plain-12.vlw");

  // Set the font and its size (in units of pixels)
  textFont(fontA, 12);
  oldMouse = new Cnum(0,0);

}
	    

void keyPressed() {
    if (key == 'q')
	exit();
    if (key == 's') 
	save("output.png");
    if (key == ' ') {
	changeOnMove = !(changeOnMove);
	draggedX = 0;
	draggedY = 0;
    }
	
}

Cnum oldMouse;
int maxIter = 20;
void draw() {
    Cnum mouse; 
    background(0);

    if(changeOnMove) {
	mouse = convert(mouseX, mouseY);
	if(mouse.r == oldMouse.r && mouse.i == oldMouse.i) {
	    if(maxIter < 1000)
		maxIter = maxIter + 20;
	    else 
		return;
	} else {
	    maxIter = 5;
	    oldMouse = mouse;
	}
    } else {
	mouse = oldMouse;
    }
    for(int q = 0; q < WIDTH; q++)
	for(int j = 0; j < HEIGHT; j++) {
	    Cnum orig = convert(q,j);
	    //Cnum acc = add(mul(orig,orig), mouse) ;
	    Cnum acc = orig ;
	    //Cnum acc = add(orig, mouse);
	    for(int i = 0; i < maxIter; i++) {
		acc = add(mul(mul(acc,acc),acc), mouse) ;
		if(acc.abs() > 2){
		    int strokeColor = 255 - i*5;
		    if (strokeColor < 0 ) strokeColor = 0;
		    stroke(strokeColor);		    
		    plot(orig);
		    break;
		} 
	    }
	}
    fill(0,0,222);		    
    text("z^2 + cl c=" + mouse.r + " + " + mouse.i + "i", 30, 60);
    if(draggedX != 0 || draggedY != 0) {
	stroke(0,0,222);
	noFill();
	int max = max(mouseX - draggedX, mouseY - draggedY);
	rect(draggedX, draggedY, max, max);
    }
 
}

int draggedX = 0;
int draggedY = 0;

void mousePressed() 
{
    if(!changeOnMove) {
	draggedX = mouseX;
	draggedY = mouseY;
    }
}

void mouseReleased()
{
    if(!changeOnMove && draggedX != 0 && draggedY != 0) {

	int temp;
	if(mouseX < draggedX) {
	    temp = mouseX;
	    mouseX = draggedX;
	    draggedX = temp;
	}
	if(mouseY < draggedY) {
	    temp = mouseY;
	    mouseY = draggedY ;
	    draggedY = temp;
	}
	int max = max (mouseX - draggedX, mouseY - draggedY);


	Cnum lowerRightNew = convert(draggedX + max, draggedY + max);
	Cnum upperLeftNew = convert(draggedX, draggedY);

	upperLeft = upperLeftNew;
	lowerRight = lowerRightNew;
	draggedX = 0;
	draggedY = 0;
    }

}

My Ol’ Fractal Generator

So one of the students was curious about the fractal generator I built last winter, so I figured I ought to finally package it up in a way that was somewhat easy to download.

You download a zip from Google Code:

http://code.google.com/p/fraccontrol/downloads/list

Here’s a sample of the sort of image you can build with it:

Mike’s Ultimate Unix Scavenger Hunt

So working here at GHP, one of the things I get to do is teach seminars. Seminars happen outside of the usual classtime…they tend to be fun special-interest type things. I’m planning on doing a couple but I decided to do the first one on the Unix Command Line. Many of my students have installed Linux. Many even have feelings about which distro is better. But yet most of them have never used the command line. This is very nostalgic for me: ah for the halcyon days of my youth! I made it my business to install every distro yet basically had no clue what one would actually do with a distro once installed. Of course in those days just getting X to work was considered a major achievement.

So anyways I figured they should at least have exposure to some of the cool things you can do with the command line.

I organized it as a “scavenger hunt”. Basically I divided my students into 4 teams and then gave them a list of 30 things to figure out how to do on the command line. The rule was that everyone on the team had to be able to do everything for the team to get credit…when teams called me over I would quiz random team members. This was necessary because we had extremely varied levels of experience…I didn’t want the experienced people just going off and leaving new members to get frustrated.

Basically the whole thing worked like a charm once everybody started working (getting everybody started and on the same page was a bit of a pain). I never cease to be amazed by how much more intense student focus is when they’re working on concrete activities rather than listening to me lecture.

By the end, even students who basically had never worked with Unix before thought the whole thing was pretty cool. The teams basically only got through item 10, but when I asked them who wanted to continue the scavenger hunt next week everybody raised their hands. When I asked them if they wanted to just come back and continue from where we left off or research stuff outside on their own, two of my no-linux-experience girls argued that they just couldn’t wait till the next seminar without playing with it some more.

Funniest thing: a couple of students told me confidentially that they completely understood playing around with the command line for fun, but they weren’t completely convinced that it could actually do anything useful. I found this neat because it seems like normally people feel like command line stuff could be useful, but don’t want to actually go through the bother of learning. That said, I want to provide some persuasive examples next time about how command line stuff can be useful for real.

So unixy friends, here would be two helpful hints I could use from you:

  1. What are some simple and concrete things you can do with the command line that even high school students could understand is awesome
  2. I could use a few more items for my list of 30 command line things. I compromised with the girls: I asked everybody not to research stuff before the seminar so that all the teams could start on the same footing. But I said that I would make an auxiliary list of challenges for people who just couldn’t wait to play with in the meantime.