// mas964 ps2 // interactive balance demonstration // Generates random balanced pictures. Not super cool, but ok. import java.applet.*; import java.awt.*; import java.lang.Math; import DoubleBufferApplet; public class Balance extends DoubleBufferApplet { int balanceY, balanceMiddle, balanceLeft, balanceRight; int blockSizes[] = new int[100]; double blockPositions[] = new double[100]; // -1 .. 1 int numBlocks; public boolean mouseDown(Event e, int x, int y) { Graphics g = imageBuffer.getGraphics(); // when mouseclicks happen, create a new instance rebalance(); render(); repaint(); return true; } // draw the data onto the screen public void render() { clearImageBuffer(); calculatePositions(); renderBlocks(); renderBalance(); } // draw the blocks themselves. Loop through each block, draw it // as a rectangle 2x1 of the blockSize with a border public void renderBlocks() { Graphics g = imageBuffer.getGraphics(); g.setColor(this.getForeground()); int i; for (i = 0; i < numBlocks; i++) { int x; x = ((int) (blockPositions[i] * (balanceRight - balanceLeft) / 2)) + balanceMiddle - blockSizes[i] / 2; g.setColor(this.getBackground()); // white outline g.fillRect(x - 1, balanceY - 2 * blockSizes[i] - 1, blockSizes[i] + 2, 2 * blockSizes[i] + 2); g.setColor(this.getForeground()); // black box g.fillRect(x, balanceY - 2 * blockSizes[i], blockSizes[i], 2 * blockSizes[i]); } } // figure out where the balance should be drawn. we draw 2/3 down the // screen, from 1/6 to 5/6 across. public void calculatePositions() { balanceY = 2 * imageBufferSize.height / 3 ; balanceLeft = imageBufferSize.width / 6; balanceRight = imageBufferSize.width * 5 / 6; balanceMiddle = imageBufferSize.width / 2; } // draw the balance itself. This is just some paint commands public void renderBalance() { Graphics g = imageBuffer.getGraphics(); g.setColor(new Color(127, 127, 127)); // 10 pixel fudge factor g.drawLine(balanceLeft - 10, balanceY, balanceRight + 10, balanceY); int triangleSize = imageBufferSize.height / 10; int x[] = { balanceMiddle, balanceMiddle - triangleSize, balanceMiddle + triangleSize}; int y[] = { balanceY, balanceY + triangleSize, balanceY + triangleSize }; g.fillPolygon(x, y, 3); } // generate some random blocks and balance them public void rebalance() { numBlocks = (int)(Math.random() * 6) + 3; // 3 .. 8 random blocks // make n-1 random blocks, putting each on the ligher side of the balance int i; for (i = 0; i < numBlocks - 1; i++) { blockSizes[i] = (int)(Math.random() * 10) + 5; // 5 .. 14 size, blockPositions[i] = Math.random() * 0.8 + 0.2; // 0.2 .. 1.0 away double weight = calcWeight(i); if (weight > 0) { // right side heavier? blockPositions[i] = -blockPositions[i]; // put it on the left } } // ok, now we need to balance using the last block double remainingWeight = calcWeight(numBlocks - 1); // pick a size from the possible range int minSize = (int)(Math.ceil(Math.sqrt(Math.abs(remainingWeight) / 2))); int maxSize = (int)(Math.sqrt(Math.abs(remainingWeight) / (2 * 0.2))); int size = (int)(Math.random() * (maxSize - minSize) + minSize); if (size <= 0) { numBlocks--; // already balanced } else { // ok, now we've got a size: position is determined. Make it. blockSizes[numBlocks - 1] = size; blockPositions[numBlocks - 1] = -remainingWeight / (2 * size * size); } } // figure out the balance of the system for the # of blocks asked for public double calcWeight(int numToCalc) { double weight = 0; int i; for (i = 0; i < numToCalc; i++) { weight += blockPositions[i] * blockSizes[i] * blockSizes[i] * 2; } return weight; } public void init() { this.setBackground(Color.white); this.setForeground(Color.black); super.init(); } }