class Zelle { //-------------------------------------------------------------------------------------------------- // Variabeln //-------------------------------------------------------------------------------------------------- int ZelleIndex; // Position im Zellen-Array float xZelle, yZelle; // Koordinaten des Mittelpunktes der Zelle float rZelle; // Radius der Zelle // zur effizienten BerŸhrungszŠhlung wird die FlŠche in verschiedene Felder aufgeteilt: int Spalte, Zeile; // Spalten-/ bzw. Zeilennnummer im Raster int FeldIndex; // Feldnummer (Numerierung Zeile fŸr Zeile, oben links = 0) color cInnen = c1wachsen; // Farbe Kreis innen color cMitte = c2wachsen; // Farbe Kreis Mitte color cAussen = c3wachsen; // Farbe Kreis aussen boolean fertig; // Zellen, die mind. 3 andere berŸhren sind "ausgewachsen" // Variabeln fŸr das Wachsen/Bewegen der Zellen (wird bei jedem Durchgang neu gesetzt) int Beruehrungszaehler = 0; // wird bei jedem Durchgang von Neuem hochgezŠhlt float [] Beruehrungspunkt = new float [4]; // Koordinaten 1. und 2. BerŸhrungspunkt // Variabeln zum Zeichnen der verschachtelten Kreise (bleiben nach der ersten BerŸhrung unverŠndert) int AnzahlBeruehrungen = 0; // effektive Anzahl BerŸhrungen float xB1, yB1; // Koordinaten bei der 1. BerŸhrung (rel. zum Zellenmittelpunkt) float r1; // Radius bei der 1. BerŸhrung float xB2, yB2; // Koordinaten bei der 2. BerŸhrung (rel. zum Zellenmittelpunkt) float r2; // Radius bei der 2. BerŸhrung float [] z1 = new float [2]; // Koordinaten des Mittelpunkts des 1. BerŸhrungskreises float [] z2 = new float [2]; // Koordinaten des Mittelpunkts des 2. BerŸhrungskreises //-------------------------------------------------------------------------------------------------- // Konstruktoren //-------------------------------------------------------------------------------------------------- Zelle () // Generierung an einer unbelegten Zufallsposition { starten (); } //-------------------------------------------------------------------------------------------------- // Methoden //-------------------------------------------------------------------------------------------------- // lŠsst die Zellen wachsen und verschiebt sie gegebenenfalls (der Anzahl BerŸhrungen entsprechend) void entwickeln () { if (getFertig () == false) // falls die Zelle noch nicht fertig ist { int Beruehrungen = BeruehrungenZaehlen (); // Zelle testen switch (Beruehrungen) { case 0: // keine BerŸhrung -> wachsen wachsen(); break; case 1: // 1 BerŸhrung -> bewegen, wachsen loeschen(); bewegen_Ber_1(); wachsen(); break; case 2: // 2 BerŸhrung -> bewegen, wachsen loeschen(); bewegen_Ber_2(); wachsen(); break; default: // 3 oder mehr BerŸhrungen if (getGeometrie () [2] < minR) { // zu kleine Zellen werden neu gestartet loeschen (); starten (); } else { // grosse Zellen werden "fertig" gesetzt setFertig (true); zeichnen (); } break; } } } //-------------------------------------------------------------------------------------------------- // zeichnet die Zellen (unterschiedlich, je nach Anzahl BerŸhrungen) void zeichnen () { switch (AnzahlBeruehrungen) { case 0: // keine BerŸhrung zeichne_Kreis (xZelle, yZelle, rZelle, cMitte); if (rZelle > Rand) { zeichne_Kreis (xZelle, yZelle, rZelle-Rand, cInnen); } break; case 1: // 1 BerŸhrung zeichne_Kreis (xZelle, yZelle, rZelle, cMitte); z1 = zeichne_KreisInKreis (xZelle, yZelle, rZelle, xB1, yB1, r1, cInnen); break; default: // 2 oder mehr BerŸhrungen zeichne_Kreis (xZelle, yZelle, rZelle, cAussen); z2 = zeichne_KreisInKreis (xZelle, yZelle, rZelle, xB2, yB2, r2, cMitte); z1 = zeichne_KreisInKreis (z2 [0], z2 [1], r2, xB1, yB1, r1, cInnen); break; } } //-------------------------------------------------------------------------------------------------- // lšscht (bzw. Ÿberzeichnet) die Zelle (fŸr die Bildschirmdarstellung) void loeschen () { zeichne_Kreis (xZelle, yZelle, rZelle, Hintergrund); } //-------------------------------------------------------------------------------------------------- // wachsen: vergršssern des Radius und neu zeichnen void wachsen () { rZelle += f; zeichnen (); } //-------------------------------------------------------------------------------------------------- // gibt die Anzahl BerŸhrungen der Zelle zurŸck und schreibt die Koordinaten der BerŸhrungspunkte // ins Beruehrungspunkt-Array (mit der Methode SetBerKoor ()) int BeruehrungenZaehlen () { Beruehrungszaehler = 0; // Zellen (sucht BerŸhrungen mit anderen Zellen im entsprechenden Feld) int AnzEinflussZ = meinFeld [FeldIndex].getAnzEinflusszellen (); for (int i=0; i < AnzEinflussZ; i++) { int IndexNachbarzelle = meinFeld [FeldIndex].getBeeinflussendeZelle (i); float xNachbar = meineZelle [IndexNachbarzelle].getGeometrie () [0]; float yNachbar = meineZelle [IndexNachbarzelle].getGeometrie () [1]; float rNachbar = meineZelle [IndexNachbarzelle].getGeometrie () [2]; float Abstand = sqrt(sq(xNachbar - xZelle) + sq(yNachbar -yZelle)); if (Abstand <= rZelle + minA + rNachbar && Abstand != 0) { // bei BerŸhrung: SetBerKoor () setBerKoor (xZelle + (rZelle/Abstand)*(xNachbar - xZelle), yZelle + (rZelle/Abstand)*(yNachbar - yZelle)); } } // …ffnungen (sucht BerŸhrungen mit …ffnungen) for (int i=0; i < AnzahlOeffnungen; i++) { float xL = meineOeffnung [i].getGeometrie () [0]; float xR = meineOeffnung [i].getGeometrie () [1]; float yO = meineOeffnung [i].getGeometrie () [2]; float yU = meineOeffnung [i].getGeometrie () [3]; if (yZelle <= yU + rZelle + minA && yZelle >= yO - rZelle -minA // nur schlaufen, falls && xZelle <= xR + rZelle + minA && xZelle >= xL - rZelle - minA) // BerŸhrung mšglich { if (yZelle < yU && yZelle > yO && xZelle < xR && xZelle > xL) { // Mittelpunkt liegt setBerKoor (99, 99); // innerhalb der …ffnung } else if (yZelle <= yU && yZelle >= yO) { // BerŸhrung links oder rechts if (xZelle < xL) { // BerŸhrung links setBerKoor (xZelle + rZelle, yZelle); } else if (xZelle > xR) { // BerŸhrung rechts setBerKoor (xZelle - rZelle, yZelle); } } else if (xZelle <= xR && xZelle >= xL) { // BerŸhrung oben oder unten if (yZelle < yO) { // BerŸhrung oben setBerKoor (xZelle, yZelle + rZelle); } else if (yZelle > yU) { // BerŸhrung rechts setBerKoor (xZelle, yZelle - rZelle); } } else { // BerŸhrung an einer Ecke if (sqrt(sq(xL - xZelle) + sq(yU -yZelle)) <= rZelle + minA) { // Ber. unten links float Abstand = sqrt(sq(xL - xZelle) + sq(yU -yZelle)); setBerKoor (xZelle + (rZelle/Abstand)*(xL - xZelle), yZelle + (rZelle/Abstand)*(yU - yZelle)); } else if (sqrt(sq(xR - xZelle) + sq(yU -yZelle)) <= rZelle + minA) { // Ber. unten rechts float Abstand = sqrt(sq(xR - xZelle) + sq(yU -yZelle)); setBerKoor (xZelle + (rZelle/Abstand)*(xR - xZelle), yZelle + (rZelle/Abstand)*(yU - yZelle)); } else if (sqrt(sq(xR - xZelle) + sq(yO -yZelle)) <= rZelle + minA) { // Ber. oben rechts float Abstand = sqrt(sq(xR - xZelle) + sq(yO -yZelle)); setBerKoor (xZelle + (rZelle/Abstand)*(xR - xZelle), yZelle + (rZelle/Abstand)*(yO - yZelle)); } else if (sqrt(sq(xL - xZelle) + sq(yO -yZelle)) <= rZelle + minA) { // Ber. oben links float Abstand = sqrt(sq(xL - xZelle) + sq(yO -yZelle)); setBerKoor (xZelle + (rZelle/Abstand)*(xL - xZelle), yZelle + (rZelle/Abstand)*(yO - yZelle)); } } } } // RŠnder (sucht BerŸhrungen mit den RŠndern) if (xZelle <= rZelle + minA) { // BerŸhrung links setBerKoor (xZelle - rZelle, yZelle); } if (xZelle >= width - rZelle - minA) { // BerŸhrung rechts setBerKoor (xZelle + rZelle, yZelle); } if (yZelle <= rZelle + minA) { // BerŸhrung oben setBerKoor (xZelle, yZelle - rZelle); } if (yZelle >= height - rZelle - minA) { // BerŸhrung unten setBerKoor (xZelle, yZelle + rZelle); } // bei der jeweils ersten zusŠtzlichen BerŸhrung wird setBeruehrungspunkt () aufgerufen if (Beruehrungszaehler > AnzahlBeruehrungen) { setBeruehrungspunkt (Beruehrungszaehler); } return (Beruehrungszaehler); } //-------------------------------------------------------------------------------------------------- // bewegt die Zelle bei nur einer BerŸhrung vom BerŸhrungspunkt weg void bewegen_Ber_1 () { xZelle += g*(xZelle - Beruehrungspunkt [0])/rZelle; // Mittelpunkt verschieben yZelle += g*(yZelle - Beruehrungspunkt [1])/rZelle; } //-------------------------------------------------------------------------------------------------- // bewegt die Zelle bei zwei BerŸhrung von den BerŸhrungspunkten weg void bewegen_Ber_2 () { float xMitte = (Beruehrungspunkt [0] + Beruehrungspunkt [2])/2; float yMitte = (Beruehrungspunkt [1] + Beruehrungspunkt [3])/2; float AbstandMitte = sqrt(sq(xMitte - xZelle) + sq(yMitte - yZelle)); // float CosinusWinkel = AbstandMitte / rZelle; if (AbstandMitte > 0.2) { // Rundungsungenauigkeiten vermeiden xZelle += g*((xZelle - xMitte)/AbstandMitte); // Mittelpunkt verschieben yZelle += g*((yZelle - yMitte)/AbstandMitte); } else { // zwischen 2 anderen eingeklemmte setFertig (true); // Zelle = fertig } } //-------------------------------------------------------------------------------------------------- // schreibt den Index der Zelle in das eigene (Spalte, Zeile) und in die 8 angrenzenden Felder void EinflussEinschreiben () { int FeldZaehler; for (int s = Spalte - 1; s <= Spalte + 1; s++) { for (int z = Zeile - 1; z <= Zeile + 1; z++) { FeldZaehler = z * AnzSpalten + s; meinFeld [FeldZaehler].ZelleEinschreiben (ZelleIndex); } } } //-------------------------------------------------------------------------------------------------- // erhšht den BerŸhrungszŠhler und schreibt die Koordinaten des BerŸhrungspunktes ins Array void setBerKoor (float x, float y) { Beruehrungszaehler++; if (Beruehrungszaehler<=2) { Beruehrungspunkt [Beruehrungszaehler*2-2] = x; // x-Wert BerŸhrunspunkt Beruehrungspunkt [Beruehrungszaehler*2-1] = y; // y-Wert BerŸhrunspunkt } } //-------------------------------------------------------------------------------------------------- // schreibt beim jeweils ersten Ansteigen des BerŸhrungszŠhlers Koordinaten und Radius in die // entsprechenden Variabeln void setBeruehrungspunkt (int BerZaehl) { AnzahlBeruehrungen = BerZaehl; if (xB1 == -99) { // erster BerŸhrungspunkt wurde noch nicht gesetzt r1 = rZelle; xB1 = Beruehrungspunkt [0] - xZelle; yB1 = Beruehrungspunkt [1] - yZelle; } if (AnzahlBeruehrungen > 1 && xB2 == -99) { // zweiter BerŸhrungspunkt wurde noch nicht gesetzt r2 = rZelle; xB2 = Beruehrungspunkt [2] - xZelle; yB2 = Beruehrungspunkt [3] - yZelle; } } //-------------------------------------------------------------------------------------------------- // sucht eine freie Position und setzt die Variabeln zurŸck void starten () { int Ber = 99; while (Ber != 0) // freie Position Suchen { xZelle = random (width); yZelle = random (height); rZelle = 0; Spalte = (int) (xZelle / FeldBreite) + 1; Zeile = (int) (yZelle / FeldHoehe) + 1; FeldIndex = Zeile * AnzSpalten + Spalte; Ber = BeruehrungenZaehlen (); } ZelleIndex = n; cInnen = c1wachsen; // alle Variabeln zurŸcksetzen cMitte = c2wachsen; cAussen = c3wachsen; fertig = false; AnzahlBeruehrungen = 0; Beruehrungspunkt = new float [4]; xB1 = -99; yB1 = -99; xB2 = -99; yB2 = -99; EinflussEinschreiben (); // Zellenindex in Enflussarray schreiben } //-------------------------------------------------------------------------------------------------- // gibt die Koordinaten des Mittelpunktes gefolgt vom Radius in einem Array aus float [] getGeometrie () { float [] Geometrie = { xZelle, yZelle, rZelle }; return Geometrie; } //-------------------------------------------------------------------------------------------------- // setzt die Zelle "fertig", setzt deren Farben neu und erhšht den ZŠhler "AnzahlFertigeZellen" void setFertig (boolean f) { fertig = f; cInnen = c1fertig; cMitte = c2fertig; cAussen = c3fertig; AnzahlFertigeZellen++; println ("fertige Zellen: " + AnzahlFertigeZellen); if (AnzahlFertigeZellen == AnzahlZellen) { noLoop (); } } // -------------------------------------------------------------------------------------------------- // liest die Variable "fertig" aus boolean getFertig () // Variable "fertig" auslesen { return fertig; } //-------------------------------------------------------------------------------------------------- }