void setup() { size(600, 600); background(0); smooth(8); noFill(); stroke(250, 15); strokeWeight(0.9); x1=y1=-3; x2=y2=3; y=y1; step=(x2-x1)/(2.321*width); } float x1, y1, x2, y2; // function domain float step; // step within domain float y; boolean go = true; void draw() { if (go) { for (int i=0; (i<20)&go; i++) { // draw 20 lines at once for (float x=x1; x<=x2; x+=step) { drawVariation(x, y); } y+=step; if (y>y2) { go = false; println("done"); //save("pdj + hyperbolic * pdj.png"); } } } } void drawVariation(float x, float y) { PVector v = new PVector(x, y); float amount = 2.0; v = addF(pdj(v,amount),mulF(hyperbolic(v,amount),pdj(v,amount))); //wrapping v.x = (v.x - x1) % (x2-x1); if(v.x<0) v.x += (x2-x1); v.y = (v.y - y1) % (y2-y1); if(v.y<0) v.y += (y2-y1); v.x += x1; v.y += y1; float xx = map(v.x+0.003*randomGaussian(), x1, x2, 20, width-20); float yy = map(v.y+0.003*randomGaussian(), y1, y2, 20, height-20); point(xx, yy); } PVector sinusoidal(PVector v, float amount) { return new PVector(amount * sin(v.x), amount * sin(v.y)); } PVector hyperbolic(PVector v, float amount) { float r = v.mag() + 1.0e-10; float theta = atan2(v.x, v.y); float x = amount * sin(theta) / r; float y = amount * cos(theta) * r; return new PVector(x, y); } // parametrization P={pdj_a,pdj_b,pdj_c,pdj_d} float pdj_a = 0.4; float pdj_b = 1.23; float pdj_c = -0.3; float pdj_d = -1.98; PVector pdj(PVector v, float amount) { return new PVector( amount * (sin(pdj_a * v.y) - cos(pdj_b * v.x)), amount * (sin(pdj_c * v.x) - cos(pdj_d * v.y))); } PVector addF(PVector v1, PVector v2) { return new PVector(v1.x+v2.x, v1.y+v2.y); } PVector subF(PVector v1, PVector v2) { return new PVector(v1.x-v2.x, v1.y-v2.y); } PVector mulF(PVector v1, PVector v2) { return new PVector(v1.x*v2.x, v1.y*v2.y); } PVector divF(PVector v1, PVector v2) { return new PVector(v2.x==0?0:v1.x/v2.x, v2.y==0?0:v1.y/v2.y); }