I did a little exploratory work in April with Processing. I wanted to have a generative system for creating series of curves that output as time/pitch on a grid.
Ultimately this would be a generative system where a musical object could be looped with slight changes in each iteration. The curves would change each time, and where the curves break the grid is the time between each pitch event (x=time, y=pitch).
My creativePact will try to extend this.
This first effort was just in making a single randomly changing bezier curve. That was easy enough, but the accidental fanning effect was so nice I left it in: may find a use for it later.
Here's the code (highlighting is for Java so may not be entirely accurate)
int start = millis();
void setup() {
size(400,400);
background(255);
smooth();
}
void draw() {
float pointA = 0;
float pointB = 0;
float pointC = 0;
float pointD = 0;
int steps = 40; //breaks the curve into X line segments
int i;
int distance = 20; //distance between gridlines
int amount = 20; // amount of gridlines
float[] pointsX = new float[100];
float[] pointsY = new float[100];
float[] intersections = new float[100];
int q = 1; //counter, how many horizontal lines crossed
int p = 1;
int time = 1000;
if(millis() - start > time) { // redraw after "time"
fill(255,255,255,200); //transparent background layer
rect(0,0,400,400);
pushMatrix(); //draw horizontal grid lines
int k;
for (k=0;k<amount;k++) {
stroke(120);
translate(0,distance);
line(0,0,width,0);
}
popMatrix();
pushMatrix(); //draw v grid erticallines
for (k=0;k<amount;k++) {
stroke(120);
translate(distance,0);
line(0,0,0,height);
}
popMatrix();
//sets the 1st bezier curve
float thing = (20 + random(380)); //random control points
float thing1 = (20 + random(380)); //random control points
for (int j = 0; j <= steps; j++) {
float t = j / float(steps);
float x = bezierPoint(0, thing, thing1, 400, t);
float y = bezierPoint(0, thing1, thing, 400, t);
stroke(0);
point(x, y);
line(pointA, pointB,x,y);
pointA = x;
pointB = y;
pointsX[j] = x;
pointsY[j] = y;
}
//finds and sets the elipses for the horizontal grid
for (int m = 1; m < steps; m++) {
if ((pointsY[m-1] <= (distance*q)) && (pointsY[m] >= (distance*q))) {
float theta = atan2(pointsY[m] - pointsY[m-1] ,pointsX[m] - pointsX[m-1]); //FIX HERE check correct atan2 values, translate to 0,0!
float opposite = ((distance*q) - pointsY[m-1]) / (tan(theta));
stroke(255,0,0);
int po = int(pointsX[m-1]+opposite);
int op = int(distance*q);
ellipse(po, op, 5, 5);
q++;
}
continue;
}
//sets the 2nd bezier curve
float thing2 = (20 + random(380)); //random control points
float thing3 = (20 + random(380)); //random control points
for (int j = 0; j <= steps; j++) {
float t = j / float(steps);
float x = bezierPoint(0, thing2, thing3, 400, t);
float y = bezierPoint(0, thing3, thing2, 400, t);
stroke(0);
point(x, y);
line(pointA, pointB,x,y); //fan accidentent happens here as pointA/B not connected to following pointC/D
pointC = x;
pointD = y;
pointsX[j] = x;
pointsY[j] = y;
}
//finds and sets the elipses for the horizontal grid
for (int m = 1; m < steps; m++) {
if ((pointsY[m-1] <= (distance*q)) && (pointsY[m] >= (distance*q))) {
float theta = atan2(pointsY[m] - pointsY[m-1] ,pointsX[m] - pointsX[m-1]); //FIX HERE check correct atan2 values, translate to 0,0!
float opposite = ((distance*q) - pointsY[m-1]) / (tan(theta));
stroke(255,0,0);
int po = int(pointsX[m-1]+opposite);
int op = int(distance*q);
ellipse(po, op, 5, 5);
q++;
}
continue;
}
start = millis();
}
}