float speed = 1.1; float amplitude = 600/8; Vector qPos(double timeT) { return new Vector(width/2 + (amplitude)*sin((float)(speed*timeT)),height/2,0); } Vector qVel(double timeT) { return new Vector(-(amplitude)*speed*cos((float)(speed*timeT)),0,0); } Vector qAcc(double timeT) { return new Vector(-(amplitude)*(speed)*(speed)*sin(speed*(float)timeT),0,0); } // critical method: will return the time that the particle contributes, // so you can plug it into other things double c = 250; // speed of light = 150 pix/second double retardedTime(Vector fieldPoint,double fieldTime) { double tr = fieldTime; Vector displacementVector = qPos(tr); displacementVector.sub(fieldPoint); int i = 0; while( abs((float)(tr+displacementVector.length()/(c) - fieldTime)) > 0.02 ) { tr -= (tr+displacementVector.length()/(c) - fieldTime); displacementVector.set(qPos(tr)); displacementVector.sub(fieldPoint); if(i++>10) { break; } } return tr; } void setup() { size(600,400); frameRate(30); println("C: "+c+" max speed: "+((amplitude)*speed)); } Vector E(Vector fieldPoint,double fieldTime,boolean exaggerateRadiation) { double tr = retardedTime(fieldPoint,fieldTime); Vector r = fieldPoint; r.sub(qPos(tr)); Vector v = qVel(tr); Vector a = qAcc(tr); //a.mul(10); Vector u = new Vector(r); u.normalize(); u.mul(c); u.sub(v); double rdu = Vector.dot(r,u); double scaleFactor = r.length() / (rdu*rdu*rdu); Vector t1 = Vector.mul(u,(c*c-v.lengthSquared())); //t1.mul(10); Vector t2 = Vector.cross(r,Vector.cross(u,a)); if(exaggerateRadiation) { t2.mul(r.length()); t2.mul(50); } t1.add(t2); t1.mul(scaleFactor); //t1.mul(r.length()); return t1; } double time = 0; void mousePressed() { time = 0; } float maxFieldAtPoint = 100; void draw() { background(0,0,0); stroke(255,255,255); // time = ((double)mouseX / (double)width) * 25.0; for(float x = 0 ; x <= width ; x+=10) { for(float y = 0 ; y <= height ; y+=10) { Vector e = E(new Vector(x,y,0),time,true); e.mul(100); if(e.lengthSquared() >= 100) { e.normalize(); e.mul(10); } if(e.lengthSquared() <= 200) { float l = (float)(e.length()/10 * 255); stroke(l,l,l); line(x,y,x+(float)e.x,y+(float)e.y); } } } fill(200,200,200); ellipseMode(CENTER); ellipse((float)(qPos(time).x),(float)(qPos(time).y),10,10); time += 0.05; stroke(150,150,150); fill(0,0,0); rect(10,10,400,20); Vector dir = E(new Vector(mouseX,mouseY,0),time,false); dir.normalize(); float currentScaling = 20/maxFieldAtPoint; maxFieldAtPoint = 0; stroke(150,150,150); for(float x = 0 ; x < 400 ; x++) { float t = (float)time - (x/10); //float fieldstrength = (float)Vector.dot(dir,E(new Vector(mouseX,mouseY,0),t,false)); float fieldstrength = (float) E(new Vector(mouseX,mouseY,0),t,false).length(); point(10+x,30-fieldstrength*currentScaling); maxFieldAtPoint = max(maxFieldAtPoint,fieldstrength); } }