View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide

form+code

Home   How To   Code Pool   Public Library   Theory   Events
code examples from the book FORM+CODE. http://www.formandcode.com
ported from Processing to SuperCollider

Parameterize_Waves.scd

/**
 * Parameterize: Wave
 * from Form+Code in Design, Art, and Architecture 
 * by Casey Reas, Chandler McWilliams, and LUST
 * Princeton Architectural Press, 2010
 * ISBN 9781568989372
 * 
 * This code was written for Processing 1.2+
 * Get Processing at http://www.processing.org/download
 */

//ported to SuperCollider by redFrik

(
var width= 1200, height= 768;
var win= Window("Parameterize: Wave", Rect(99, 99, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
var brickWidth= 40;
var brickHeight= 15;
var cols= 20;
var rows= 24;
var columnOffset= 60;
var rowOffset= 30;
var rotationIncrement= 0.15;
usr.background= Color.white;
usr.drawFunc= {
	Pen.smoothing= true;
	Pen.strokeColor= Color.black;
	Pen.translate(30, 30);
	cols.do{|i|
		var r, dir;
		Pen.push;
		Pen.translate(i*columnOffset, 0);
		r= rrand(-0.25pi, 0.25pi);
		dir= 1;
		rows.do{|j|
			Pen.push;
			Pen.translate(0, rowOffset*j);
			Pen.rotate(r);
			Pen.strokeRect(Rect(0-brickWidth/2, 0-brickHeight/2, brickWidth, brickHeight));
			Pen.pop;
			r= r+(dir*rotationIncrement);
			if(r>0.25pi or:{r< -0.25pi}, {dir= dir* -1});
		};
		Pen.pop;
	};
};
win.front;
CmdPeriod.doOnce({if(win.isClosed.not, {win.close})});
)


Repeat_Embedded.scd

/**
 * Repeat: Embedded Iteration 
 * from Form+Code in Design, Art, and Architecture 
 * by Casey Reas, Chandler McWilliams, and LUST
 * Princeton Architectural Press, 2010
 * ISBN 9781568989372
 * 
 * This code was written for Processing 1.2+
 * Get Processing at http://www.processing.org/download
 */

//ported to SuperCollider by redFrik

(
var width= 400, height= 300;
var win= Window("Repeat: Embedded Iteration", Rect(99, 99, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
var option= 1;
usr.background= Color.white;
usr.animate= true;
usr.drawFunc= {
	Pen.smoothing= true;
	Pen.strokeColor= Color.black;
	if(option==1, {
		//Option 1: Stitches
		50.forBy(width-50, 20, {|x|
			50.forBy(height-50, 20, {|y|
				Pen.line(Point(x-5, y-5), Point(x+5, y+5));
				Pen.line(Point(x+5, y-5), Point(x-5, y+5));
			});
		});
		Pen.stroke;
	}, {
		if(option==2, {
			//Option 2: Perspective
			50.forBy(width-50, 20, {|x|
				50.forBy(height-50, 20, {|y|
					Pen.line(Point(x, y), Point(width/2, height/2));
				});
			});
			Pen.stroke;
		}, {
			if(option==3, {
				//Option 3: Overlapping circles
				50.forBy(width-50, 20, {|x|
					50.forBy(height-50, 20, {|y|
						Pen.addOval(Rect(x-20, y-20, 40, 40));
					});
				});
				Pen.stroke;
			}, {
				if(option==4, {
					//Option 4: Rotating arcs
					var count= 120;
					50.forBy(width-50, 20, {|x|
						50.forBy(height-50, 20, {|y|
							var s= count.linlin(0, 120, 2pi*2, 0, nil);
							Pen.addArc(Point(x, y), 7.5, s, pi);
							count= count-1;
						});
					});
					Pen.stroke;
				}, {
					if(option==5, {
						//Option 5: Groups of five
						50.forBy(width-50, 20, {|x|
							50.forBy(height-50, 20, {|y|
								//Pen.addRect(Rect(x-10, y-10, 22, 22));
								0.forBy(15, 4, {|i|
									Pen.line(Point(x+i, y), Point(x+i, y+12));
								});
								Pen.line(Point(x, y), Point(x+12, y+12));
							});
						});
						Pen.stroke;
					});
				});
			});
		});
	});
};
usr.mouseDownAction= {
	option= option+1;
	if(option>5, {
		option= 1;
	});
};
win.front;
CmdPeriod.doOnce({if(win.isClosed.not, {win.close})});
)


Repeat_RecursiveTree.scd


/**
 * Repeat: Recursive Tree
 * from Form+Code in Design, Art, and Architecture 
 * by Casey Reas, Chandler McWilliams, and LUST
 * Princeton Architectural Press, 2010
 * ISBN 9781568989372
 *
 * This program is based on Context Free program 
 * "Foggy Tree by Chris Coyne:
 * http://www.contextfreeart.org/gallery/view.php?id=4 
 * 
 * This code was written for Processing 1.2+
 * Get Processing at http://www.processing.org/download
 */

//ported to SuperCollider by redFrik

(
var dotSize= 9;
var angleOffsetA;
var angleOffsetB;
var width= 900, height= 600;
var frameRate= 1;	// Redraw the tree once a second
var win= Window("Repeat: Recursive Tree", Rect(99, 99, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
var seed1, seed2;
angleOffsetA= 1.5.degrad;	// Convert 1.5 degrees to radians
angleOffsetB= 50.degrad;	// Convert 50 degrees to radians
usr.background= Color.white;	// White background
usr.drawFunc= {
	Pen.smoothing= true;
	Pen.fillColor= Color.black;
	Pen.translate(width/2, height);	// Move to the center, bottom of the screen
	seed1.value(dotSize, 270.degrad, 0, 0);	// Start the tree
};
seed1= {|dotSize, angle, x, y|
	var r, newx, newy;
	if(dotSize>1, {
		// Create a random number between 0 and 1
		r= 1.0.rand;
		// 98% chance this will happen
		if(r>0.02, {
			Pen.fillOval(Rect(x, y, dotSize, dotSize));
			newx= x+(cos(angle)*dotSize);
			newy= y+(sin(angle)*dotSize);
			seed1.value(dotSize*0.99, angle-angleOffsetA, newx, newy);
		}, {
			// 2% chance this will happen
			Pen.fillOval(Rect(x, y, dotSize, dotSize));
			newx= x+cos(angle);
			newy= y+sin(angle);
			seed2.value(dotSize*0.99, angle+angleOffsetA, newx, newy);
			seed1.value(dotSize*0.60, angle+angleOffsetB, newx, newy);
			seed2.value(dotSize*0.50, angle-angleOffsetB, newx, newy);
		});
	});
};
seed2= {|dotSize, angle, x, y|
	var r, newx, newy;
	if(dotSize>1, {
		// Create a random number between 0 and 1
		r= 1.0.rand;
		// 95% chance this will happen
		if(r>0.05, {
			Pen.fillOval(Rect(x, y, dotSize, dotSize));
			newx= x+(cos(angle)*dotSize);
			newy= y+(sin(angle)*dotSize);
			seed2.value(dotSize*0.99, angle+angleOffsetA, newx, newy);
		}, {
			// 5% chance this will happen
			Pen.fillOval(Rect(x, y, dotSize, dotSize));
			newx= x+cos(angle);
			newy= y+sin(angle);
			seed1.value(dotSize*0.99, angle+angleOffsetA, newx, newy);
			seed2.value(dotSize*0.60, angle+angleOffsetB, newx, newy);
			seed1.value(dotSize*0.50, angle-angleOffsetB, newx, newy);
		});
	});
};
Routine({
	inf.do{
		usr.refresh;
		frameRate.wait;
	};
}).play(AppClock);
win.front;
CmdPeriod.doOnce({if(win.isClosed.not, {win.close})});
)


Simulate_DLA.scd


/**
 * Simulate: Diffusion-Limited Aggregation
 * from Form+Code in Design, Art, and Architecture 
 * by Casey Reas, Chandler McWilliams, and LUST
 * Princeton Architectural Press, 2010
 * ISBN 9781568989372
 * 
 * This code was written for Processing 1.2+
 * Get Processing at http://www.processing.org/download
 */

//ported to SuperCollider by redFrik

(
var win= Window("Simulate: Diffusion-Limited Aggregation", Rect(99, 99, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
var width= 1024, height= 700;
var particle= (
	x: 0, y: 0,
	stuck: false,
	m_reset: {|self|
		// keep choosing random spots until an empty one is found
		while({
			self.x= width.rand.floor;
			self.y= height.rand.floor;
			field[self.y*width+self.x];
		}, nil);
	},
	m_update: {|self|
		var skip= false;
		// move around
		if(self.stuck.not, {
			self.x= self.x+rrand(-1, 1).round;
			self.y= self.y+rrand(-1, 1).round;
			if(self.x<0 or:{self.y<0 or:{self.x>=width or:{self.y>=height}}}, {
				self.m_reset;
				skip= true;
			});
			// test if something is next to us
			if(skip.not and:{self.m_alone.not}, {
				self.stuck= true;
				field[self.y*width+self.x]= true;
			});
		});
	},
	// returns true if no neighboring pixels
	m_alone: {|self|
		var res= true, skip= false;
		var cx= self.x;
		var cy= self.y;
		// get positions
		var lx= cx-1;
		var rx= cx+1;
		var ty= cy-1;
		var by= cy+1;
		if(cx<=0 or:{cx>=width or:{
			lx<=0 or:{lx>=width or:{
				rx<=0 or:{rx>=width or:{
					cy<=0 or:{cy>=height or:{
						ty<=0 or:{ty>=height or:{
							by<=0 or:{by>=height}}}}}}}}}}}, {
								res= true;
								skip= true;
							});
		// pre multiply the ys
		cy= cy*width;
		by= by*width;
		ty= ty*width;
		if(skip.not, {
			// N, W, E, S
			if(field[cx+ty] or:{
				field[lx+cy] or:{
					field[rx+cy] or:{
						field[cx+by]}}}, {
							res= false;
							skip= true;
						});
			if(skip.not, {
				// NW, NE, SW, SE
				if(field[lx+ty] or:{
					field[lx+by] or:{
						field[rx+ty] or:{
							field[rx+by]}}}, {
								res= false;
							});
			});
		});
		res;
	}
);

// this number might need to be smaller for some computers
var particleCount= 20000;
var particles= Array.newClear(particleCount);
// create an array that stores the position of our particles
var field= Array.fill(width*height, {false});
// add seed in the center
var fcenterX= width.div(2);
var fcenterY= height.div(2);
field[fcenterX+(fcenterY*width)]= true;
// make particles
particleCount.do{|i|
	particles[i]= particle.copy;
};
usr.background= Color.white;	// White background
usr.drawFunc= {
	Pen.smoothing= false;
	Pen.fillColor= Color.black;
	particleCount.do{|i|
		particles[i].m_update;
		if(particles[i].stuck, {
			Pen.addRect(Rect(particles[i].x, particles[i].y, 1, 1));
		});
	};
	Pen.fill;
};
usr.animate= true;
win.front;
CmdPeriod.doOnce({if(win.isClosed.not, {win.close})});
)


Simulate_Particles.scd


/**
 * Simulate: Particles
 * from Form+Code in Design, Art, and Architecture 
 * by Casey Reas, Chandler McWilliams, and LUST
 * Princeton Architectural Press, 2010
 * ISBN 9781568989372
 * 
 * This code was written for Processing 1.2+
 * Get Processing at http://www.processing.org/download
 */

//ported to SuperCollider by redFrik

(
var win= Window("Simulate: Particles", Rect(99, 99, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
var width= 1024, height= 768;
var heading2D= {|v|
	var angle= (0-v.y).atan2(v.x);
	-1*angle;
};
var mag= {|v|
	v.x.sumsqr(v.y).sqrt;
};
var particle= (
	loc: Point(0, 0),
	vel: Point(0, 0),
	acc: Point(0, 0),
	hist: [],
	counter: 0,
	// create the particle
	m_init: {|self, l|
		var randmin= -0.5pi;
		var randmax= 0;
		var r= rrand(0, 2pi);
		var x= cos(r);
		var y= sin(r);
		var q= 1.0.rand;
		self.acc= Point(x/250, y/250);
		r= rrand(randmin, randmax);
		x= cos(r)*q;
		y= sin(r)*q;
		self.vel= Point(x, y);
		self.loc= l;
		self.hist= Array.newClear(1000);
	},
	// update location
	m_update: {|self|
		self.vel= self.vel+self.acc;
		self.loc= self.loc+self.vel;
		// save location every 10 frames
		if(usr.frame%10==0 and:{self.counter<self.hist.size}, {
			self.hist[self.counter]= self.loc;
			self.counter= self.counter+1;
		});
	},
	// draw particle
	m_draw: {|self|
		self.drawArrowHead(self.vel, self.loc, 10);
		// draw history path
		Pen.strokeColor= Color.grey(0, 100/255);
		self.counter.do{|i|
			if(i==0, {
				Pen.moveTo(Point(self.hist[i].x, self.hist[i].y));
			}, {
				Pen.lineTo(Point(self.hist[i].x, self.hist[i].y));
			});
		};
		if(self.counter>0, {
			Pen.lineTo(Point(self.loc.x, self.loc.y));
		});
		Pen.stroke;
	},
	drawArrowHead: {|self, v, loc, scale|
		var arrowsize= 8;
		var len;
		Pen.push;
		// Translate to location to render vector
		Pen.translate(loc.x, loc.y);
		// rotate to heading
		Pen.rotate(heading2D.value(v));
		// Calculate length of vector & scale it to be bigger or smaller if necessary
		len= mag.value(v)*scale;
		arrowsize= len.linlin(0, 10, 0, 1)*arrowsize;
		// Draw point
		Pen.strokeColor= Color.grey(0, 100/255);
		Pen.fillColor= Color.grey(0, 100/255);
		Pen.line(Point(0, 0), Point(len-arrowsize, 0));
		Pen.stroke;
		Pen.moveTo(Point(len, 0));
		Pen.lineTo(Point(len-arrowsize, arrowsize/2));
		Pen.lineTo(Point(len-arrowsize, 0-arrowsize/2));
		Pen.fill;
		Pen.pop;
	}
);

var particles= Array.newClear(1000);
var saving= false;
// create particles
particles.size.do{|i|
	particles[i]= particle.copy.m_init(Point(100, height-100));
};
usr.background= Color.white;
usr.drawFunc= {
	Pen.smoothing= true;
	// draw the particles
	particles.size.do{|i|
		particles[i].m_update;
		particles[i].m_draw;
	};
};
usr.animate= true;
win.front;
CmdPeriod.doOnce({if(win.isClosed.not, {win.close})});
)


Visualize_Superformula.scd


/**
 * Visualize: Superformula
 * from Form+Code in Design, Art, and Architecture 
 * by Casey Reas, Chandler McWilliams, and LUST
 * Princeton Architectural Press, 2010
 * ISBN 9781568989372
 * 
 * This code was written for Processing 1.2+
 * Get Processing at http://www.processing.org/download
 */

//ported to SuperCollider by redFrik

(
var win= Window("Visualize: Superformula", Rect(99, 99, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
var width= 700, height= 700;
var scaler= 200;
var m= 2;
var n1= 18;
var n2= 1;
var n3= 1;
var superformula= {|m, n1, n2, n3|
	var numPoints= 360;
	var phi= 2pi/numPoints;
	var points= Array.fill(numPoints+1, {|i|
		superformulaPoint.value(m, n1, n2, n3, phi*i);
	});
	points;
};
var superformulaPoint= {|m, n1, n2, n3, phi|
	var r;
	var t1, t2;
	var a= 1, b= 1;
	var x= 0;
	var y= 0;
	t1= cos(m*phi/4)/a;
	t1= abs(t1);
	t1= pow(t1, n2);
	t2= sin(m*phi/4)/b;
	t2= abs(t2);
	t2= pow(t2, n3);
	r= pow(t1+t2, 1/n1);
	if(abs(r)==0, {
		x= 0;
		y= 0;
	}, {
		r= 1/r;
		x= r*cos(phi);
		y= r*sin(phi);
	});
	Point(x, y);
};
usr.background= Color.black;
usr.drawFunc= {
	var newscaler= scaler;
	Pen.smoothing= true;
	Pen.strokeColor= Color.white;
	Pen.push;
	Pen.translate(width/2, height/2);
	16.do{|i|
		var s= 16-i;
		var mm= m+s;
		var nn1= n1+s;
		var nn2= n2+s;
		var nn3= n3+s;
		var sscaler, points;
		newscaler= newscaler*0.98;
		sscaler= newscaler;
		points= superformula.value(mm, nn1, nn2, nn3);
		Pen.moveTo(points[points.size-1]*sscaler);
		points.size.do{|i|
			Pen.lineTo(points[i]*sscaler);
		};
		Pen.lineTo(points[0]*sscaler);
		Pen.stroke;
	};
	Pen.pop;
};
win.front;
CmdPeriod.doOnce({if(win.isClosed.not, {win.close})});
)


todo:

Link to this Page