import java.util.LinkedList; import java.awt.*; import java.io.*; import javax.imageio.*; import java.awt.image.*; class Splice{ int pix[][]; double x; double y; double m; int w; int h; //velocity double v[]; public Splice(int x, int y, int w, int h, double vx, double vy){ this.x = x; this.y = y; this.w = w; this.h = h; this.w = w; this.h = h; v = new double[] {vx ,vy}; m = w*h; } } public class HW07a extends MISApplet{ //variables for mouse int mx = 0, my = 0,mdx = 0, mdy = 0; boolean isMouseDown = false; final int WHITE = pack(255,255,255); final int BLACK = pack( 0, 0, 0); final int GRAY = pack(128,128,128); final int RED = pack(255, 0, 0); final int BLUE = pack(0,0,128); final int GREEN = pack(0,128 , 0); final int YELLOW = pack(255, 255, 0); double cur_time = 0; LinkedList splices = new LinkedList(); int[] back; int[] hidden; //tool variables int invertW = 60; int invertH = 40; boolean isSplicing = false; int initial_x = 0; int initial_y = 0; Tool currentTool = Tool.SPLICER; Tool oldTool = Tool.SPLICER; public enum Tool{INVERTER, SPLICER} public enum Backdrop{ORIGINAL, PLAID1, PLAID2, STRIPES, VERONICA} Backdrop currentBackdrop = Backdrop.PLAID2; public void initialize() { //set mouse to middle of the applet mx = W/2; my = H/2; splices = new LinkedList(); switch(currentBackdrop){ case ORIGINAL: back = new int[W*H]; //construct backdrop /** INTEGER MATH ONLY */ for (int y = 0 ; y < H ; y++) for (int x = 0 ; x < W ; x++) { int i = xy2i(x,y); back[i] = pack(ilerp(x%(W/2),0,255),ilerp(y%(H/2),0,255), ilerp((x+y)%(W/4+H/4),0,255)); } hidden = back; break; case PLAID1: back = new int[W*H]; for (int y = 0 ; y < H ; y++) for (int x = 0 ; x < W ; x++) { int i = xy2i(x,y); int c = BLUE; if(x%128<16||(x+32)%128<16||(x+64)%128<16) c = avg(c,WHITE); if((y)%128<16||(y+32)%128<16||(y+64)%128<16) c = avg(c,WHITE); if((x-4)%128<8||(x+32-4)%128<8||(x+64-4)%128<8) c = avg(c,BLACK ); if((y-4)%128<8||(y+32-4)%128<8||(y+64-4)%128<8) c = avg(c,BLACK ); back[i] = c; } hidden = back; break; case PLAID2: back = new int[W*H]; for (int y = 0 ; y < H ; y++) for (int x = 0 ; x < W ; x++) { int i = xy2i(x,y); int c = GREEN; final int stripe_width = 3; final int diagonal_width = 3; final int twice_diagonal_width = 6; final int num_stripes_per_square = 28; if(x%(num_stripes_per_square*diagonal_width*2)<(num_stripes_per_square*diagonal_width)&& y%(num_stripes_per_square*diagonal_width*2)<(num_stripes_per_square*diagonal_width)) c = BLACK; if( (x%twice_diagonal_width-y%twice_diagonal_width=0)|| (x%twice_diagonal_width-y%twice_diagonal_width<-diagonal_width)){ if(x%(num_stripes_per_square*diagonal_width*2)<(num_stripes_per_square*diagonal_width)|| y%(num_stripes_per_square*diagonal_width*2)<(num_stripes_per_square*diagonal_width)) c = BLACK; } if((x-(num_stripes_per_square*diagonal_width/2)+stripe_width/2+(num_stripes_per_square*diagonal_width*2))%(num_stripes_per_square*diagonal_width*2)=0)|| (x%twice_diagonal_width-y%twice_diagonal_width<-diagonal_width))) c=YELLOW; } if((y-(num_stripes_per_square*diagonal_width/2)+stripe_width/2+(num_stripes_per_square*diagonal_width*2))%(num_stripes_per_square*diagonal_width*2)=0)|| (x%twice_diagonal_width-y%twice_diagonal_width<-diagonal_width))) c=YELLOW; } if((x+(num_stripes_per_square*diagonal_width/2)+stripe_width/2+(num_stripes_per_square*diagonal_width*2))%(num_stripes_per_square*diagonal_width*2)=0)|| (x%twice_diagonal_width-y%twice_diagonal_width<-diagonal_width))) c=BLACK; } if((y+(num_stripes_per_square*diagonal_width/2)+stripe_width/2+(num_stripes_per_square*diagonal_width*2))%(num_stripes_per_square*diagonal_width*2)=0)|| (x%twice_diagonal_width-y%twice_diagonal_width<-diagonal_width))) c=BLACK ; } back[i] = c; } hidden = back; break; case STRIPES: back = new int[W*H]; for (int y = 0 ; y < H ; y++) for (int x = 0 ; x < W ; x++) { int i = xy2i(x,y); int c = RED; final int diagonal_width = 8; final int twice_diagonal_width = 16; if( (x%twice_diagonal_width-y%twice_diagonal_width=0)|| (x%twice_diagonal_width-y%twice_diagonal_width<-diagonal_width)) c = BLACK; back[i] = c; } hidden = back; break; case VERONICA: backdropFromFile("Veronica01.jpg", "Veronica02.jpg" ); break; default: break; } } /** Overriden method that must define frame in doube pix[] array */ public void computeImage(double time) { //paint the backdrop for(int i=0;iW-s.w/2){ s.x = W-s.w/2; s.v[0] = -s.v[0]; } if(s.yH-s.h/2){ s.y = H-s.h/2; s.v[1] = -s.v[1]; } } } final int DASH_WIDTH = 4; final int DASH_LEN = 20; final int HALF_DASH_LEN = DASH_LEN/2; /** (1) if mouse down for first time start new splice (2) if mouse still down continue to define splice (3) if mouse up for first time after mouse has been down let splice go */ private void splice(double time){ int dashOffset = ((int) ((time%1)*DASH_LEN) ); //clip the mouse int mx = Math.max(Math.min(this.mx,W-DASH_WIDTH),0); int my = Math.max(Math.min(this.my,H-DASH_WIDTH),0); //start new splice? if(!isSplicing && isMouseDown){ isSplicing = true; initial_x = mx; initial_y = my; } if(isSplicing && isMouseDown){ //draw little box based on time int top = initial_ymy ? initial_y : my; int left = initial_xmx ? initial_x : mx; for(int j = 0; j< DASH_WIDTH; j++){ int i; for(int x = left; x < right; x++){ i = xy2i(x,top+j); pix[i] = (x-dashOffset) %DASH_LEN>HALF_DASH_LEN ? WHITE : BLACK; i = xy2i(x,bottom+j); pix[i] = (x-dashOffset) %DASH_LEN>HALF_DASH_LEN ? BLACK : WHITE; } for(int y = top; y < bottom; y++){ i = xy2i(left+j,y); pix[i] = ((y-dashOffset) % DASH_LEN)>HALF_DASH_LEN ? WHITE : BLACK; i = xy2i(right+j,y); pix[i] = ((y-dashOffset) %DASH_LEN)>HALF_DASH_LEN ? BLACK : WHITE; } } } if(!isMouseDown&&isSplicing){ isSplicing = false; //to avoid non-rectangles if(initial_x==mx) initial_x--; if(initial_y==my) initial_y--; //make a new splice and add it to the list int w = Math.abs(initial_x-mx); int h = Math.abs(initial_y-my); double vx = H/(initial_y-my); double vy = W/(initial_x-mx); Splice s = new Splice((mx+initial_x)/2, (my+initial_y)/2,w,h,vx,vy); s.pix = new int[w][h]; //capture pixels from background int ul_x = Math.min(initial_x,mx); int ul_y = Math.min(initial_y,my); for(int x=0;x= 0 && i < pix.length) { /** 256 as unity lerp parameter based on distance from center */ int c = Math.max(0, 255 * Math.max(Math.abs(x-mx),Math.abs(y-my))/Math.max(invertW,invertH)- 128); //get original (backdrop values) int r = unpack(hidden[i],0); int g = unpack(hidden[i],1); int b = unpack(hidden[i],2); //get inverted values int ir = 255-r; int ig = 255-g; int ib = 255-b; // with in radius then just write inverse if (c == 0) pix[i] = pack(ir, ig, ib); //otherwise blend in (this always makes grey... else { int red = ilerp(c,ir,r); int grn = ilerp(c,ig,g); int blu = ilerp(c,ib,b); pix[i] = pack(red, grn, blu); } } } } public boolean mouseDown(Event e, int x, int y) { isMouseDown = true; return true; } public boolean mouseUp(Event e, int x, int y) { isMouseDown = false; return true; } public boolean mouseMove(Event e, int x, int y) { mx = x; my = y; return true; } public boolean mouseDrag(Event e, int x, int y) { mx = x; my = y; mdx = x; mdy = y; return true; } public boolean keyUp(Event e, int key) { switch(key){ case '1': currentBackdrop = Backdrop.ORIGINAL; initialize(); break; case '2': currentBackdrop = Backdrop.STRIPES; initialize(); break; case '3': currentBackdrop = Backdrop.PLAID1; initialize(); break; case '4': currentBackdrop = Backdrop.PLAID2; initialize(); break; case '0': currentBackdrop = Backdrop.VERONICA; initialize(); break; case 'R': case 'r': initialize(); break; case 'x': case 'X': currentTool = oldTool; oldTool = null; break; default: break; } return true; } public boolean keyDown(Event e, int key) { switch(key){ case 'x': case 'X': if(null==oldTool) oldTool = currentTool; currentTool = Tool.INVERTER; break; default: break; } return true; } /** Collision for 2d, code in this method is modified from: * http://www.plasmaphysics.org.uk/programs/coll2d_cpp.htm * * modifies velocities */ private void collision( double m1, double w1, double h1, double x1, double y1, double v1[], double m2, double w2, double h2, double x2, double y2 ,double v2[]){ double m21=m2/m1; double x21=x2-x1; double y21=y2-y1; double vx21= v2[0]-v1[0]; double vy21= v2[1]-v1[1]; //are balls travelling at eachother? and touching eachother? if( (vx21*x21 + vy21*y21) < 0 && (Math.abs(x21)