//Jeffery Kaye
//Kinetic Scuplture
int numPoints = 40;
int counter = -1;
int curPoint = 0;
int curNode = 0;
int curPeg = 0;
int pegCounter = 0;
boolean beenDragged = false;
boolean firstTime = true;
PImage startImage;
PFont arial;
Lattice myLattice;
void setup() {
size(600,300);
framerate(60);
startImage = loadImage("final_title.gif");
arial = loadFont("ArialMT-11.vlw");
myLattice = new Lattice();
}
void draw() {
if(firstTime) {
image(startImage, 0, 0);
} else {
background(255);
if (beenDragged) {
drawAgain();
myLattice.updateNodes();
myLattice.updatePegs();
myLattice.display();
}
}
}
void mouseDragged() {
myLattice.update();
beenDragged = true;
}
void mousePressed()
{
firstTime = false;
}
void drawAgain() {
push();
fill(0);
textFont(arial, 11);
text("press 'r' to restart applet", 450, 20);
pop();
if(keyPressed) {
if(key == 'r' || key == 'R') {
firstTime = true;
}
}
}
/****** CLASSES ******/
class Node {
Position p = new Position();
Vector v = new Vector();
float x, y, rad, myAngle;
float x1, y1, x2, y2;
float speed = .5;
int numPegs = 0;
int pointGroup;
int r = 200;
int g = 255;
int b = 255;
boolean flip = true;
boolean first = true;
int range = 10;
Node(float $x, float $y, float $rad) {
p.set($x, $y);
rad = $rad;
}
void update(float $x, float $y, float $rad) {
p.set($x, $y);
rad = $rad;
}
void makeColor(float $distValue) {
float tempValue = ($distValue/30)*255;
//println(tempValue);
r = int(random(tempValue));
g = int(random(tempValue));
b = int(random(tempValue));
}
void make(float $x, float $y) {
p.set($x, $y);
}
float getX() {
return p.x;
}
float getY() {
return p.y;
}
void addPeg() {
if(numPegs+1 < 5) {
numPegs++;
}
}
void addAngle(float $x1, float $y1, float $x2, float $y2) {
//println($x1 + " " + $y1 + " " + $x2 + " " + $y2);
myAngle = atan2($y1-$y2, $x1-$x2);
//println(myAngle);
x1 = p.x + range*cos(myAngle);
y1 = p.y + range*sin(myAngle);
x2 = p.x - range*cos(myAngle*PI);
y2 = p.y - range*cos(myAngle*PI);
//println(p.x + " " + x1 + " " + p.y + " " + y1);
}
float getX1() {
return x1;
}
float getY1() {
return y1;
}
float getX2() {
return x2;
}
float getY2() {
return y2;
}
float getAngle() {
return myAngle;
}
//keeps track of which Node is associated to with point
void addToGroup(int $pointGroup) {
pointGroup = $pointGroup;
}
int getGroup() {
return pointGroup;
}
void makeJiggle() {
if(flip) {
if(p.close_to(x1, y1, 1)) {
flip = false;
}
if(!p.close_to(x1, y1, 1)) {
float a = atan2(y1 - p.y, x1 - p.x);
v.set(speed, a);
p.add(v);
}
} else {
if(p.close_to(x2, y2, 1)) {
flip = true;
}
if(!p.close_to(x2, y2, 1)) {
float a = atan2(y2 - p.y, x2 - p.x);
v.set(speed, a);
p.add(v);
}
}
}
void go_to(float $x, float $y) {
/*if(first) {
getXYs();
first = false;
}*/
if(!p.close_to($x, $y, .05)) {
float a = atan2($y - p.y, $x - p.x);
v.set(speed, a);
p.add(v);
}
}
void getXYs() {
x1 = range*cos(myAngle);
y1 = range*sin(myAngle);
println(x1);
println(y1);
}
void findJiggleValues() {
x1 = range*cos(myAngle);
y1 = range*sin(myAngle);
x2 = range*cos(myAngle*PI);
y2 = range*sin(myAngle*PI);
println(x1);
println(y1);
println(x2);
println(y2);
}
void display() {
push();
fill(r, g, b);
strokeWeight(1);
stroke(0);
ellipse(p.x, p.y, rad*2, rad*2);
pop();
}
}
class Peg {
float x1, x2, y1, y2;
int begin, end;
Peg() {};
Peg(float $x1, float $y1, float $x2, float $y2) {
x1 = $x1;
x2 = $x2;
y1 = $y1;
y2 = $y2;
}
void modPeg(float $x1, float $y1, float $x2, float $y2) {
x1 = $x1;
x2 = $x2;
y1 = $y1;
y2 = $y2;
}
void addBegin(int $begin) {
begin = $begin;
}
void addEnd(int $end) {
end = $end;
}
int getBegin() {
return begin;
}
int getEnd() {
return end;
}
void connect() {
push();
strokeWeight(1);
stroke(0);
line(x1, y1, x2, y2);
pop();
}
}
class Lattice {
Node myNodes[];
Peg myPegs[];
int pegGroupNums[];
int pegCycle = 0;
float mx[];
float my[];
float pointAngles[];
float x, y;
boolean temp = false;
int pegGroups = 0;
int pegBegin = 0;
int pegEnd = 0;
int totalPegs = 0;
Lattice() {
myNodes = new Node[numPoints*4];
myPegs = new Peg[numPoints*12];
pegGroupNums = new int[numPoints*2];
mx = new float[numPoints];
my = new float[numPoints];
pointAngles = new float[numPoints];
for(int i=0; i<(numPoints*4); i++) {
myNodes[i] = new Node(0, 0, 3);
}
}
void updateNodes() {
for(int k=0; k<curNode; k++) {
myNodes[k+2].makeJiggle();
//myNodes[k].go_to(myNodes[k].getX1(), myNodes[k].getY1());
}
}
void updatePegs() {
for(int k=0; k<curPeg; k++) {
int begin = myPegs[k].getBegin();
int end = myPegs[k].getEnd();
myPegs[k].modPeg(myNodes[begin].getX(), myNodes[begin].getY(), myNodes[end].getX(), myNodes[end].getY());
}
}
void update() {
if (counter < ((5*numPoints) - 1)) { // looking to fetch numPoints of points
counter++;
if ((counter % 5) == 0) { // use every 7th mouse location
//println(counter + " " + curPoint + " " + curNode);
mx[curPoint] = mouseX;
my[curPoint] = mouseY;
if (curPoint == 0) { // first focus point
for (int i=0; i<2; i++) {
makeRadiusNodes(15);
curNode++;
}
} else { // all other points
float posDif = dist(mx[curPoint], my[curPoint], mx[curPoint-1], my[curPoint-1]);
//println(mx[curPoint] + " " + my[curPoint] + " " + mx[curPoint-1] + " " + my[curPoint-1]);
float hypot = posDif;
if (posDif < 0) { // always get positive distance
posDif *= (-1);
}
int randNumNodes = int(random(2,4.9));
for (int i=0; i<randNumNodes; i++) {
makeRadiusNodes(hypot);
myNodes[curNode].addToGroup(curPoint);
myNodes[curNode].makeColor(hypot);
myNodes[curNode].addAngle(mx[curPoint], my[curPoint], mx[curPoint-1], my[curPoint-1]);
//println(mx[curPoint] + " " + my[curPoint] + " " + mx[curPoint-1] + " " + my[curPoint-1]);
//println(myNodes[curNode].getGroup());
//myNodes[curNode].make((mx[curPoint]+random(-30,30)), (my[curPoint]+random(-30,30)));
curNode++;
}
createPegs();
}
curPoint++;
}
}
display();
}
float offspring() {
float jiggleAngle = atan2((my[curPoint]-my[curPoint-1]), (mx[curPoint]-mx[curPoint-1]));
return jiggleAngle;
}
void makeRadiusNodes(float $hypot) {
float randomAngle = random(TWO_PI);
float yValue = sin(randomAngle)*$hypot;
float xValue = cos(randomAngle)*$hypot;
myNodes[curNode].make(mx[curPoint]+xValue, my[curPoint]+yValue);
}
void createPegs() {
int curPointGroup = myNodes[curNode-1].getGroup();
for (int i=curNode-1; i>=0; i--) { // for every node in curPointGroup
if (myNodes[i].getGroup() == curPointGroup) {
float Max = 0;
int MaxIndex = 0;
float Min = 100000;
int MinIndex = 0;
float tempDist = 0;
int counter1 = 0;
int counter2 = 0;
int r1 = 0;
int r2 = 0;
for (int j=0; j<curNode; j++) { // for every node in curPointGroup and curPointGroup-1
if ((myNodes[j].getGroup() == curPointGroup) || (myNodes[j].getGroup() == (curPointGroup - 1)) ) {
tempDist = dist(myNodes[i].getX(), myNodes[i].getY(), myNodes[j].getX(), myNodes[j].getY());
if (tempDist < 0) {
tempDist *= (-1);
}
if (tempDist > Max) {
Max = tempDist;
MaxIndex = j;
}
if (tempDist < Min) {
Min = tempDist;
MinIndex = j;
}
}
}
/*for(int k=0; k<curNode; k++) {
myNodes[i].makeJiggle();
}*/
myPegs[curPeg] = new Peg(myNodes[i].getX(), myNodes[i].getY(), myNodes[MinIndex].getX(), myNodes[MinIndex].getY());
myPegs[curPeg].addBegin(i);
myPegs[curPeg].addEnd(MinIndex);
curPeg++;
myPegs[curPeg] = new Peg(myNodes[i].getX(), myNodes[i].getY(), myNodes[MaxIndex].getX(), myNodes[MaxIndex].getY());
myPegs[curPeg].addBegin(i);
myPegs[curPeg].addEnd(MaxIndex);
curPeg++;
//r1 = int(random(counter1));
//r2 = int(random(counter2));
//println(r1 + " " + r2);
//myPegs[curPeg] = new Peg(myNodes[curNode-r1].getX(), myNodes[curNode-r1].getY(), myNodes[curNode-counter1-r2].getX(), myNodes[curNode-counter1-r2].getY());
//curPeg++;
}
//else
//break;
}
}
void display() {
for(int i=0; i<curNode; i++) {
myNodes[i].display();
}
for (int i=0; i<curPeg; i++) { //for every peg
myPegs[i].connect();
}
}
}
void mouseReleased()
{
}
/*********************************************************************/
/*** POSITION AND VECTOR CLASSES ***/
/******* compliments of Lenny *******/
class Position
{
float x,y;
Position() {}
Position(float $x, float $y)
{
x = $x; y = $y;
}
Position(Position p)
{
x = p.x; y = p.y;
}
void add(Vector v)
{
x += cos(v.a)*v.m;
y += sin(v.a)*v.m;
}
void sub(Vector v)
{
x -= cos(v.a)*v.m;
y -= sin(v.a)*v.m;
}
void set(float $x, float $y)
{
x = $x; y = $y;
}
void set(Position p)
{
x = p.x; y = p.y;
}
boolean close_to(float $x, float $y, float $c)
{
if ( dist(x, y, $x, $y) < $c) {
return true;
} else {
return false;
}
}
}
class Vector
{
float m,a;
Vector() {}
Vector(float $m, float $a)
{
m = $m; a = $a;
}
void add(Vector v)
{
float x = cos(a)*m + cos(v.a)*v.m;
float y = sin(a)*m + sin(v.a)*v.m;
m = dist(0,0,x,y);
a = atan2(y,x);
}
void add(float $m, float $a)
{
float x = cos(a)*m + cos($a)*$m;
float y = sin(a)*m + sin($a)*$m;
m = dist(0,0,x,y);
a = atan2(y,x);
}
void set(float $m, float $a)
{
m = $m; a = $a;
}
}