// TRIPLETS
//
// this system works with each possible triplet of particles, attracting them
// to the average position of the trio. a diffusion filter slowly fades the
// display after each iteration. click/drag to interact
//
// Seb Chevrel | <A HREF="http://www.seb.cc">www.seb.cc</A>
// ———————————————————————————————————————————————————————————————
final int WIDTH=400;
final int HEIGHT=400;
final int num=6;
Point[] Pts=new Point[num];
void setup() {
size(WIDTH,HEIGHT);
noBackground();
stroke(255,255,255);
strokeWidth(2);
fill(0,0,0);
rect(0,0,WIDTH,HEIGHT);
for(int i=0;i<num;i++) {
Pts[i]=new Point(random(WIDTH),random(HEIGHT));
}
}
void loop() {
int i,j,k;
float cx,cy;
// for each triplet (there are 3^(n-2)+1 triplets)
for(i=0;i<(num-2);i++) {
for(j=i+1;j<(num-1);j++) {
for(k=j+1;k<num;k++) {
// average pos of the triplet
cx=(Pts[i].x+Pts[j].x+Pts[k].x)/3;
cy=(Pts[i].y+Pts[j].y+Pts[k].y)/3;
// attract pts to the center
Pts[i].attract(cx,cy);
Pts[j].attract(cx,cy);
Pts[k].attract(cx,cy);
}
}
}
blur();
for(i=0;i<num;i++) {
Pts[i].update();
if (i==0 && mousePressed) { Pts[0].x=mouseX; Pts[0].y=mouseY; Pts[0].vx=0; Pts[0].vy=0; }
Pts[i].render();
}
}
void blur() {
int index,sum,left,right,top,bottom;
for(int j=0;j<WIDTH;j++) {
for(int i=0;i<HEIGHT;i++) {
index=i*WIDTH+j;
// Wraparound offsets
if(j>0) left=-1; else left=WIDTH-1;
if(j==(WIDTH-1)) right=-WIDTH+1; else right=1;
if(i>0) top=-WIDTH; else top=(HEIGHT-1)*WIDTH;
if(i==(HEIGHT-1)) bottom=-(HEIGHT-1)*WIDTH; else bottom=WIDTH;
// Calculate the sum of n neighbors
sum=pixels[left+index] & 255; // left middle
//sum+=pixels[left+top+index] & 255; // left top
//sum+=pixels[left+bottom+index] & 255; // left bottom
sum+=pixels[right+index] & 255; // right middle
//sum+=pixels[right+top+index] & 255; // right top
//sum+=pixels[right+bottom+index] & 255; // right bottom
sum+=(pixels[index] & 255); // middle middle
sum+=pixels[index+top] & 255; // middle top
sum+=pixels[index+bottom] & 255; // middle bottom
sum=(sum/5);
pixels[index]=(sum<<16)+(sum<<8)+sum;
}
}
}
class Point {
public float x,y;
public float rx,ry;
public float vx,vy;
public int col;
Point(float cx,float cy) { x=rx=cx; y=ry=cy; vx=vy=0; col=0xFFFFFF;}
void update() {
rx=x;
ry=y;
x+=vx;
y+=vy;
if (x>WIDTH) x=rx=x % WIDTH;
if (x<0) x=rx=WIDTH+(x % WIDTH);
if (y>HEIGHT) y=ry=y % HEIGHT;
if (y<0) y=ry=HEIGHT+(y % HEIGHT);
}
void render() {
//stroke(col);
line(rx,ry,x,y);
}
void attract(float cx,float cy) {
float dx,dy,d2;
dx=cx-x; dy=cy-y; d2=dx*dx+dy*dy;
if(d2>20) {
vx=(vx + dx*40/d2 )*.98;
vy=(vy + dy*40/d2 )*.98;
}
}
};