// NMI's Java Code Viewer 6.0a // www.trinnion.com/javacodeviewer // Registered to Evaluation Copy // Generated Mon May 26 2003 01:41:48 // Source File Name: ForceField.java // Original at http://www.colorado.edu/physics/2000/waves_particles/wavpart3.html // Get from http://www.colorado.edu/physics/2000/applets/forcefield/wpos.gif // Images are passed in as parameters (can change them) import java.applet.Applet; import java.awt.*; import java.awt.image.MemoryImageSource; import java.awt.image.PixelGrabber; import java.io.PrintStream; import java.net.URL; import java.util.Random; public class ForceField extends Applet { private Image offscreen; private Image posImage; private Image negImage; private Image backImage; private Image clipImage; private Point posTerm; private Point negTerm; private int inset; private int pixels[]; private Dimension d; private Runtime rt; private boolean linesOn; private boolean sentinel; private boolean isMac; private PixelGrabber pg; private Rectangle r; private int last_x; private int last_y; private static final int OK_DISTANCE = 10; private static final long NUM_ITERATIONS = 500L; private static final int RADIUS = 20; private static final int CHARGE_RADIUS = 5; private static final double SCALE_FACTOR = 1D; private static final int SLEEP_TIME = 10; private static final Color LINE_COLOR = new Color(100, 100, 100); private static final Color HEAD_COLOR = new Color(140, 0, 0); private static final int WHITE_COLOR; private static final int BORDER_COLOR; public boolean keyDown(Event evt, int key) { if(key == 8 || key == 127) { reset(); return true; } if(key == 114 || key == 82) { randomDraw(); return true; } if(key == 108 || key == 76) { if(!linesOn && isMac) deliverEvent(new Event(this, 0L, 401, 0, 0, 127, 0)); toggleLines(); return true; } else { return false; } } public void test() { Dimension d = size(); Random r = new Random(200L); Graphics g = getGraphics(); long startTime = System.currentTimeMillis(); for(int i = 0; (long)i < 500L; i++) { int xPoint = (int)(r.nextFloat() * (float)d.width); int yPoint = (int)(r.nextFloat() * (float)d.height); drawArrow(xPoint, yPoint); } long endTime = System.currentTimeMillis(); float answerTotal = endTime - startTime; float answerEach = answerTotal / 500F; System.out.println("The total time to draw " + 500L + " arrows was " + answerTotal + " milliseconds."); System.out.println("The time to draw each arrow was " + answerEach + " milliseconds."); } private void displayOffScreen(Rectangle r) { pixels = new int[r.width * r.height]; pg = new PixelGrabber(offscreen, r.x, r.y, r.width, r.height, pixels, 0, r.width); try { pg.grabPixels(); } catch(InterruptedException e) { System.out.println("Interrupted"); } for(int i = 0; i < r.width * r.height; i++) if(pixels[i] == WHITE_COLOR) pixels[i] = 0xffffff; clipImage = createImage(new MemoryImageSource(r.width, r.height, pixels, 0, r.width)); Graphics g = getGraphics(); g.drawImage(clipImage, r.x, r.y, r.width, r.height, this); sentinel = false; } private synchronized void reset() { offscreen = null; sentinel = true; repaint(); } public void paint(Graphics g) { checkOffscreen(); if(!linesOn) { g.drawImage(offscreen, 0, 0, this); } else { g.drawImage(backImage, 0, 0, this); if(!isMac) { displayOffScreen(bounds()); drawBorder(g); } } } private void drawBorder(Graphics g) { Dimension d = size(); g.setColor(new Color(BORDER_COLOR)); g.drawRect(0, 0, d.width - 1, d.height - 1); } private void toggleLines() { linesOn = !linesOn; sentinel = true; repaint(); } private void drawArrow(int x, int y) { int OFF_SET = 90; double force[] = forceAt(x, y); Point endPoint = new Point(x + (int)force[0], y + (int)force[1]); int r2 = 400; int distance = (negTerm.y - y) * (negTerm.y - y) + (negTerm.x - x) * (negTerm.x - x); int end = (int)(Math.pow(negTerm.y - endPoint.y, 2D) + Math.pow(negTerm.x - endPoint.x, 2D)); if(distance < r2) return; distance = (posTerm.y - y) * (posTerm.y - y) + (posTerm.x - x) * (posTerm.x - x); if(distance < r2 || end < r2) { return; } else { Graphics g = offscreen.getGraphics(); g.setColor(LINE_COLOR); g.drawLine(x, y, endPoint.x, endPoint.y); g.setColor(HEAD_COLOR); g.fillOval(endPoint.x - 1, endPoint.y - 1, 3, 3); g = getGraphics(); g.setColor(LINE_COLOR); g.drawLine(x, y, endPoint.x, endPoint.y); g.setColor(HEAD_COLOR); g.fillOval(endPoint.x - 1, endPoint.y - 1, 3, 3); return; } } private void checkOffscreen() { if(offscreen == null) { offscreen = createImage(d.width, d.height); Graphics g = offscreen.getGraphics(); g.setColor(Color.white); g.fillRect(0, 0, d.width, d.height); g.setColor(Color.gray); drawBorder(g); drawTerminals(g); } } public void update(Graphics g) { if(sentinel) { paint(g); sentinel = false; } } private double[] forceAt(int xPos, int yPos) { int x = 0; int y = 1; int d = 2; double result[] = new double[2]; int distance = negTerm.x - posTerm.x; Point posDiff = new Point(xPos - posTerm.x, yPos - posTerm.y); Point negDiff = new Point(xPos - negTerm.x, yPos - negTerm.y); double posR[] = normal(posDiff); double negR[] = normal(negDiff); double posD = Math.pow(posR[d] / (double)distance, 1.0D) / 2D; double negD = Math.pow(negR[d] / (double)distance, 1.0D) / 2D; result[x] = posR[x] / posD - negR[x] / negD; result[y] = posR[y] / posD - negR[y] / negD; return result; } private void drawTerminals(Graphics g) { int w = posImage.getWidth(this); int h = posImage.getHeight(this); g.drawImage(posImage, posTerm.x - w / 2, posTerm.y - h / 2, this); w = negImage.getWidth(this); h = negImage.getHeight(this); g.drawImage(negImage, negTerm.x - w / 2, negTerm.y - h / 2, this); } public ForceField() { sentinel = true; r = new Rectangle(); } public void loadImages() { MediaTracker mt = new MediaTracker(this); String posName = getParameter("posImage"); // wpos.jpg String negName = getParameter("negImage"); // wneg.jpg String backName = getParameter("backImage"); // fieldlines.jpg posImage = getImage(getCodeBase(), posName); negImage = getImage(getCodeBase(), negName); backImage = getImage(getCodeBase(), backName); mt.addImage(posImage, 0); mt.addImage(negImage, 1); mt.addImage(backImage, 2); try { mt.waitForAll(); } catch(InterruptedException e) { System.err.println("Interrupted while loading images."); } } public boolean mouseDown(Event e, int x, int y) { last_x = x; last_y = y; if((e.modifiers & 1) == 1) reset(); else drawArrow(x, y); return true; } public Image getImage(URL url, String name) { Image image = super.getImage(url, name); MediaTracker mt = new MediaTracker(this); mt.addImage(image, 0); try { mt.waitForAll(); } catch(InterruptedException exp) { System.err.println("Interrupted while loading images."); } if(name.substring(name.length() - 3).equalsIgnoreCase("gif") && System.getProperty("os.name").equals("Windows 95") && System.getProperty("java.vendor").equals("Netscape Communications Corporation")) { int h = image.getHeight(this); int w = image.getWidth(this); int pixels[] = new int[h * w]; PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w); try { pg.grabPixels(); } catch(InterruptedException e) { System.err.println("Interrupted"); } image = createImage(new MemoryImageSource(w, h, pixels, 0, w)); } return image; } public void init() { d = size(); rt = Runtime.getRuntime(); inset = d.width / 6; posTerm = new Point(inset, d.height / 2); negTerm = new Point(d.width - inset, d.height / 2); if(System.getProperty("os.name").equals("MacOS")) isMac = true; loadImages(); } private double[] normal(Point input) { double result[] = new double[3]; double distance = Math.sqrt(input.x * input.x + input.y * input.y); result[0] = (double)input.x / distance; result[1] = (double)input.y / distance; result[2] = distance; return result; } public void randomDraw() { Dimension d = size(); long seed = System.currentTimeMillis(); Random r = new Random(seed); for(int i = 0; (long)i < 500L; i++) { int xPoint = (int)(r.nextFloat() * (float)d.width); int yPoint = (int)(r.nextFloat() * (float)d.height); drawArrow(xPoint, yPoint); } rt.gc(); } public boolean mouseDrag(Event e, int x, int y) { if(distance(x, y, last_x, last_y) > 10) { last_x = x; last_y = y; drawArrow(x, y); return true; } else { return false; } } private int distance(int x, int y, int old_x, int old_y) { return (int)Math.sqrt(Math.pow(old_x - x, 2D) + Math.pow(old_y - y, 2D)); } static { WHITE_COLOR = Color.white.getRGB(); BORDER_COLOR = Color.gray.getRGB(); } }