// Displaying the accumulation grid class AttractorDisplay{ AccumulationGrid grid; // accumulation grid AttractorSystem attractorSystem; // associated attractor AttractorDisplayParameters parameters; // display parameters GaussianConvolutionKernel gck; float focus; PVector tempResult = new PVector(); int NOfUpdates; AttractorDisplay(GridParameters GP, AttractorSystemParameters ASP, AttractorDisplayParameters parameters){ this.parameters=parameters.get(); attractorSystem = new AttractorSystem(ASP); grid=new AccumulationGrid(GP); this.focus=1.5f; this.gck =new GaussianConvolutionKernel(20,10,2f, focus); NOfUpdates=0; } //estimate spatial extent of attractor void setLimits(int steps){ float xmin =grid.parameters.minVisX; float xmax=grid.parameters.maxVisX; float ymin=grid.parameters.minVisY; float ymax=grid.parameters.maxVisY; float dx,dy,dnx,dny; for (int rep=0;rep5) { // Ignore first few steps xmin=min(xmin,attractorSystem.particles[t].x); xmax=max(xmax,attractorSystem.particles[t].x); ymin=min(ymin,attractorSystem.particles[t].y); ymax=max(ymax,attractorSystem.particles[t].y); } } } dx=grid.parameters.maxVisX-grid.parameters.minVisX; dy=grid.parameters.maxVisY-grid.parameters.minVisY; dnx=xmax-xmin; dny=ymax-ymin; float sr=FastFunctions.sqrt(dx/dy*dny/dnx); grid.parameters.minVisX=(xmax+xmin)/2f-1.2f*sr*dnx/2f; grid.parameters.minVisY=(ymax+ymin)/2f-1.2f/sr*dny/2f; grid.parameters.maxVisX=(xmax+xmin)/2f+1.2f*sr*dnx/2f; grid.parameters.maxVisY=(ymax+ymin)/2f+1.2f/sr*dny/2f; reset(true,false); } // update all particles void update(int steps, boolean firstPass){ float px, py; if (firstPass) setLimits(steps);// if it's the first this attractor updates, rescale to its approximate limits. for (int rep=0;repparameters.cutoff) { if(ASP.rotation!=0f){ px=ASP.centerOfRotation.x+attractorSystem.cosRot*(attractorSystem.particles[t].x-ASP.centerOfRotation.x)-attractorSystem.sinRot*(attractorSystem.particles[t].y-ASP.centerOfRotation.y); py=ASP.centerOfRotation.y+attractorSystem.sinRot*(attractorSystem.particles[t].x-ASP.centerOfRotation.x)+attractorSystem.cosRot*(attractorSystem.particles[t].y-ASP.centerOfRotation.y); } else{ px=attractorSystem.particles[t].x; py=attractorSystem.particles[t].y; } grid.add(px,py,attractorSystem.particles[t].value,parameters.quality,focus,gck); } } NOfUpdates++; } firstPass=false; } void getPixels(){ ResultBin resultBin; loadPixels(); for(int i=0;i=parameters.displayX)&&(X<=parameters.displayX+parameters.displayWidth)&&(Y>=parameters.displayY)&&(Y<=parameters.displayY+parameters.displayHeight)){ PVector m= getSystemCoords(new PVector(X,Y)); PVector o; switch(parameters.centerMode){ case 0: o=getSystemCoords(new PVector(parameters.displayX+0.5f*parameters.displayWidth,parameters.displayY+0.5f*parameters.displayHeight)); float tx=m.x-o.x; float dy=m.y-o.y; float dx=attractorSystem.cosRot*tx-attractorSystem.sinRot*dy; dy=attractorSystem.cosRot*dy+attractorSystem.sinRot*tx; grid.parameters.minVisX+=dx; grid.parameters.maxVisX+=dx; grid.parameters.minVisY+=dy; grid.parameters.maxVisY+=dy; reset(false,false); break; case 1: attractorSystem.parameters.centerOfSymmetry=new PVector(m.x,m.y); reset(false,false); break; case 2: attractorSystem.parameters.centerOfMirror=new PVector(m.x,m.y); reset(false,false); break; case 3: attractorSystem.parameters.centerOfRotation=new PVector(m.x,m.y); reset(false,false); } } } void keyPressed(){ boolean redraw=false; if (key == CODED) { if (keyCode == UP) { grid.parameters.minVisY=grid.parameters.minVisY+0.05*(grid.parameters.maxVisY-grid.parameters.minVisY); grid.parameters.maxVisY=grid.parameters.maxVisY+0.05*(grid.parameters.maxVisY-grid.parameters.minVisY); reset(false,false); } else if (keyCode == DOWN) { grid.parameters.minVisY=grid.parameters.minVisY-0.05*(grid.parameters.maxVisY-grid.parameters.minVisY); grid.parameters.maxVisY=grid.parameters.maxVisY-0.05*(grid.parameters.maxVisY-grid.parameters.minVisY); reset(false,false); } else if (keyCode == RIGHT) { grid.parameters.minVisX=grid.parameters.minVisX-0.05*(grid.parameters.maxVisX-grid.parameters.minVisX); grid.parameters.maxVisX=grid.parameters.maxVisX-0.05*(grid.parameters.maxVisX-grid.parameters.minVisX); reset(false,false); } else if (keyCode == LEFT) { grid.parameters.minVisX=grid.parameters.minVisX+0.05*(grid.parameters.maxVisX-grid.parameters.minVisX); grid.parameters.maxVisX=grid.parameters.maxVisX+0.05*(grid.parameters.maxVisX-grid.parameters.minVisX); reset(false,false); } } else { if ((key == 'c')||(key == 'C')) { centerOnPixel(mouseX,mouseY); } else if (key=='+'){ float mx=0.5f*(grid.parameters.maxVisX+grid.parameters.minVisX); float my=0.5f*(grid.parameters.maxVisY+grid.parameters.minVisY); float nlx = mx-0.45f*(grid.parameters.maxVisX-grid.parameters.minVisX); float nux = mx+0.45f*(grid.parameters.maxVisX-grid.parameters.minVisX); float nly = my-0.45f*(grid.parameters.maxVisY-grid.parameters.minVisY); float nuy = my+0.45f*(grid.parameters.maxVisY-grid.parameters.minVisY); grid.parameters.minVisX=nlx; grid.parameters.maxVisX=nux; grid.parameters.minVisY=nly; grid.parameters.maxVisY=nuy; reset(false,false); } else if (key=='-'){ float mx=0.5f*(grid.parameters.maxVisX+grid.parameters.minVisX); float my=0.5f*(grid.parameters.maxVisY+grid.parameters.minVisY); float nlx = mx-0.55f*(grid.parameters.maxVisX-grid.parameters.minVisX); float nux = mx+0.55f*(grid.parameters.maxVisX-grid.parameters.minVisX); float nly = my-0.55f*(grid.parameters.maxVisY-grid.parameters.minVisY); float nuy = my+0.55f*(grid.parameters.maxVisY-grid.parameters.minVisY); grid.parameters.minVisX=nlx; grid.parameters.maxVisX=nux; grid.parameters.minVisY=nly; grid.parameters.maxVisY=nuy; reset(false,false); } } } } // class governing the interface and the various states. class AttractorDisplayArray{ static final int INIT=0; // initialization phase static final int WAITING=1; // initialization done, waiting for selecting static final int FULLSCREENACTIVE=2; // updating and rendering static final int FULLSCREENSTEALTH=3; // updating, rendering only on demand static final int FULLSCREENCOLOR=4; // no update, fast feedback for color changes static final int FULLSCREENMODIFY=5; // preview update only, fast feedback for geometry change static final int SAVING=6; // intermediate state, no input during saving Attractor[] attractors; // array of randomly selected attractors float[][] limits; // remember limits of the attractor systems AttractorDisplay activeDisplay; AttractorDisplay previewDisplay; int rows; int cols; int ax,ay,aw,ah; int px, py, pw, ph; int mode; int prevMode; boolean showCenters; boolean active; boolean responsiveToColorChange; boolean responsiveToGridChange; boolean responsiveToAttractorChange; boolean drawRequested; boolean updateOnce; int initCounter; AttractorDisplayParameters defaultADP; AttractorSystemParameters defaultASP; GridParameters defaultGP; framePoster fPost; AttractorDisplayArray(int rows, int cols, int ax, int ay,int aw, int ah, int px, int py,int pw, int ph){ this.rows=max(1,rows); this.cols=max(1,cols); this.ax=ax; this.ay=ay; this.aw=aw; this.ah=ah; this.attractors = new Attractor[this.rows*this.cols]; this.limits = new float[this.rows*this.cols][4]; defaultADP=new AttractorDisplayParameters(0,0,aw/cols,ah/rows,1,0,0,2, new genericFunction(1.0f,0.5f,1f,0f,0f,1f,false,false,false,false,false)); defaultASP = new AttractorSystemParameters(1000,100,-2f,2f,-2f,2f,1,new PVector(0f,0f),0,new PVector(0f,0f),0f,0f,new PVector(0f,0f),0,-1); defaultGP = new GridParameters(aw/(2*cols),ah/(2*rows),-2f,2f,-2f,2f); for(int i=0;i0){ mode=FULLSCREENCOLOR; prevMode=FULLSCREENMODIFY; processMode(); } break; case SAVING: if(prevMode!=SAVING){ mode=SAVING; prevMode=FULLSCREENACTIVE; processMode(); saveImage(); mode=prevMode; prevMode=SAVING; processMode(); } break; } break; case FULLSCREENMODIFY: switch(requestedMode){ case FULLSCREENACTIVE: mode=FULLSCREENACTIVE; prevMode=FULLSCREENMODIFY; processMode(); break; case FULLSCREENSTEALTH: mode=FULLSCREENSTEALTH; prevMode=FULLSCREENMODIFY; processMode(); break; case FULLSCREENCOLOR: if( activeDisplay.NOfUpdates>0){ mode=FULLSCREENCOLOR; prevMode=FULLSCREENMODIFY; processMode(); } break; } break; case FULLSCREENCOLOR: switch(requestedMode){ case FULLSCREENACTIVE: mode=FULLSCREENACTIVE; prevMode=FULLSCREENCOLOR; processMode(); break; case FULLSCREENSTEALTH: mode=FULLSCREENSTEALTH; prevMode=FULLSCREENCOLOR; processMode(); break; case FULLSCREENMODIFY: mode=FULLSCREENMODIFY; prevMode=FULLSCREENCOLOR; processMode(); break; case SAVING: if(prevMode!=SAVING){ mode=SAVING; prevMode=FULLSCREENCOLOR; processMode(); saveImage(); mode=prevMode; prevMode=SAVING; processMode(); } break; } break; case FULLSCREENSTEALTH: switch(requestedMode){ case FULLSCREENACTIVE: mode=FULLSCREENACTIVE; prevMode=FULLSCREENSTEALTH; processMode(); break; case FULLSCREENMODIFY: mode=FULLSCREENMODIFY; prevMode=FULLSCREENSTEALTH; processMode(); break; case FULLSCREENCOLOR: if( activeDisplay.NOfUpdates>0){ mode=FULLSCREENCOLOR; prevMode=FULLSCREENMODIFY; processMode(); } break; } break; } } void mousePressed(){ if((mouseX>=ax)&&(mouseX<=ax+aw)&&(mouseY>=ay)&&(mouseY<=ay+ah)){ if(mode==WAITING){ float resulti,resultj; resulti = (mouseX-ax)/(aw/(float)cols); resultj = (mouseY-ay)/(ah/(float)rows); if((resulti>=0)&&(resulti=0)&&(resultj