Javakurs/Übungsaufgaben/DiffusionLimitedAggregation/Musterlösung
< Javakurs | Übungsaufgaben | DiffusionLimitedAggregation
Version vom 28. März 2010, 14:33 Uhr von Jörg F (Diskussion | Beiträge) (erste Version einer Musterlösung)
import java.awt.Color; public class DLA { public static void main(String[] args) { // Feld fuer Kollisionsueberpruefung erstellen int[][] field = new int[400][400]; // Grenzen fuer Koordinaten der Partikel aus field berechnen (.length // verwenden) int maxX = field.length; int maxY = field[0].length; // Fenster fuer Grafikausgabe vorbereiten und anzeigen Pad drawPad = new Pad(); drawPad.setBackground(Pad.black); drawPad.setPadSize(maxX, maxY); drawPad.setVisible(true); drawPad.setColor(Pad.white); // "Samen" erzeugen. Also den ersten Partikel in der Mitte des Feldes // setzen (Color: Pad.white) setPixel(drawPad, field, maxX / 2, maxY / 2, Pad.white); // Radius des Partikels der am weitesten vom Zentrum entfernt ist int maxR = 0; for (int x = 0; x < maxX; x++) { for (int y = 0; y < maxY; y++) { if (testPixel(field, x, y)) { maxR = (int) Math.max(maxR, Math.sqrt(Math.pow( (x - maxX / 2), 2) + Math.pow((y - maxY / 2), 2))); } } } // Abbruchbedingung boolean isAtBorder = false; // Schleifenkopf, solange maxR nicht den Rand des Fensters // beruehrt, sollen neue Punkte gezeichnet werden while (!isAtBorder) { // einen Punkt auf einem Kreis um den Mittelpunkt mit dem Radius // maxR+20 erzeugen double x = Math.random() * 360; int movingPixelX = limit((int) (Math.cos(x) * (maxR + 20)) + maxX / 2, 0, maxX); int movingPixelY = limit((int) (Math.sin(x) * (maxR + 20)) + maxY / 2, 0, maxY); // Schleife zum bewegen des Partikels while (!isTouching(field, movingPixelX, movingPixelY) && inRange(movingPixelX, movingPixelY, maxR + 30, maxX, maxY)) { // Partikelkoordinaten zufaellig bewegen (moveRandom) movingPixelX = moveRandom(movingPixelX); movingPixelY = moveRandom(movingPixelY); } // Schleife zuende, ueberpruefe ob eine Beruehrung vorliegt: if (isTouching(field, movingPixelX, movingPixelY)) { // Farbwertberechnung fuer 1337 blau-Effekt int k = limit( 255 - (int) (255 * ((double) maxR * 2) / (double) maxX), 0, 255); Color c = new Color(255, k, k); // den Partikel setzen und zeichnen setPixel(drawPad, field, movingPixelX, movingPixelY, c); // Radius zum Mittelpunkt berechnen, // wenn groesser als altes Maximum, ueberschreiben maxR = (int) Math.max(maxR, Math.sqrt(Math.pow( ((double) movingPixelX - (double) maxX / 2), 2) + Math.pow(((double) movingPixelY - (double) maxY / 2), 2))); if (movingPixelX - 1 <= 0 || movingPixelX + 1 >= maxX || movingPixelY - 1 <= 0 || movingPixelY + 1 >= maxY) { isAtBorder = true; } } // System.out.println(maxX + "\t" + maxY + "\t " + maxR + "\t" // + movingPixelX + "\t" + movingPixelY + "\t"+isAtBorder); } } // ...Math.toRadians( public static void setPixel(Pad drawPad, int[][] field, int x, int y, Color c) { if (x > 0 && y > 0 && x < field.length - 1 && y < field[0].length - 1) { field[x][y] = 1; drawPad.setColor(c); drawPad.drawDot(x, y); } } /** * Prüft ob sich ein Punkt innerhalb eines Radius vom Mittelpunkt eines * Rechtecks befindet * * @param x * die x Koordinate des fields * @param y * die y Koordinate des fields * @param maxR * der Radius * @param maxX * die x Koordinate des Rechtecks * @param maxY * die y Koordinate des Rechtecks+30 */ public static boolean inRange(int x, int y, int maxR, int maxX, int maxY) { // Mittelpunkt des Rechtecks ausrechen int middleX = maxX / 2; int middleY = maxY / 2; // Der Abstand vom Mittelpunkt sqrt(a² + b²) mit Hilfe der in Java // intigrierten Klasse "Math" int distance = (int) Math.sqrt(Math.pow((x - middleX), 2) + Math.pow((y - middleY), 2)); if (distance < maxR) { return true; } return false; } /** * Testet ob das gegebene Pixel an ein anderes grenzt * * @param field * das Array von Pixeln * @param x * die x Koordinate des fields * @param y * die y Koordinate des fields * @return grenzt an ein anders Pixel (true) oder nicht (false) */ public static boolean isTouching(int[][] field, int x, int y) { // ist eigentlich unschön, in diesem Fall aber wesentlich einfacher zu // lesen und zu verstehen if (testPixel(field, x - 1, y - 1) || testPixel(field, x - 1, y) || testPixel(field, x - 1, y + 1) || testPixel(field, x, y - 1) || testPixel(field, x, y + 1) || testPixel(field, x + 1, y - 1) || testPixel(field, x + 1, y) || testPixel(field, x + 1, y + 1)) { return true; } return false; // #TODO ergänzen } /** * Testet ob der Wert des Pixels größer 0 ist. (Falls der Wert außerhalb der * Grenzen ist wird er mit der limit() Methode gelimited) * * @param field * das Array von Pixeln * @param x * die x Koordinate des fields * @param y * die y Koordinate des fields * @return ob der Wert größer 0 ist (true) oder nicht (false) */ public static boolean testPixel(int[][] field, int x, int y) { // länge des ersten arrays x = limit(x, 0, field.length - 1); y = limit(y, 0, field[0].length - 1); // länge des zweiten arrays if (field[x][y] > 0) { return true; } return false; } /** * Limitiert einen Wert auf einen Bereich * * @param value * der zu limitierende Wert * @param lower * die untere Grenze * @param upper * die obere Grenze * @return den limitierten Wert */ public static int limit(int value, int lower, int upper) { if (value < lower) { return lower; } if (value > upper) { return upper; } return value; } /** * Bewegt eine Pixelkoordinate randommäßig -1, +1 oder gar nicht * * @param movePixel * die zu bewegende Pixel-Koordinate * @return die Bewegte Pixel-Koordinate */ public static int moveRandom(int movePixel) { // erstelle eine random-Zahl zwischen 1 und int random = 1 + (int) (Math.random() * 3); // Math.random() gibt eine double-Zahl >= 0.0 und < 1.0 zurück switch (random) { case 1: return movePixel - 1; case 2: return movePixel; default: return movePixel + 1; } } }