/* Klasse Edge (Ast oder Kannte) Version 1.0 Eine Edge beschreibt eine Kannte, Ast mit zwei Punkten der Klasse Point Eine Edge enthŠlt neben den Punkten die dicke der Kannte und deren Winkel Konstruktor Parameter: Point1 = vom Typ Point Point2 = vom Typ Point thickness = Astdicke edgeAngle = Winkel der Edge myBranch = vom Typ Branch, jede Edge weiss, zu welcher Branch (Baum) sie gehšrt Methoden: makeNewEdge = einmaliges teilen der Edge divide = zweimaliges Teilen der Edge ending = erstellt kleine zweige am ender der gabelungen ending2 = erstellt einen kleinen zweig am ende jeder gabelung drawMe = zeichnet kannte drawMe = zeichnet Ellipsen (BlŠtter) */ class Edge { Point point1; // Startpunkt Point point2; // Endpunkt float thickness = 0; float edgeAngle; Branch myBranch; Edge(Point pa, Point pb, float t, Branch newBranch) { point1 = pa; point2 = pb; thickness = t; myBranch = newBranch; edgeAngle = atan((pa.y-pb.y)/(pa.x-pb.x)); // Winkel der Kante wird berechnet if (edgeAngle > 0 && point1.x > point2.x) // Korrigiert Winkel, da atan nur Winkel zwischen + - PI liefert. { edgeAngle = edgeAngle - PI; } if (edgeAngle < 0 && point1.y < point2.y && point1.x > point2.x) { edgeAngle = edgeAngle + PI; } } //-------------------------------------METHODEN---------------------------------------------------------------------- //--------einmaliges Teilen der Kannte void makeNewEdge(float l, float d, float winkel) // wird Benutzt vom "Baumtyp 1" { float tV = l; Edge e; Point tP = new Point(point1.x+tV*(point2.x-point1.x),point1.y+tV*(point2.y-point1.y)); // neuer Punkt auf der Kannte im TeilverhŠltnis TV wird erstellt thickness = thickness * schwindFaktor; float range = winkel; float w = edgeAngle + random(-range,range); // Winkel des neuen Punktes variiert um Winkel der zu teilenden Kannte float newXPosition = tP.x +(cos(w)*d); // neuer Punkt wird Berechnet float newYPosition = tP.y +(sin(w)*d); Point nPoint = new Point(newXPosition,newYPosition); if (nPoint.testAusgabeFenster () > 0) // Methode wird aufgerufen, die ŸberprŸft, ob neuer Punkt im Ausgabefeld liegt. 1 = liegt drinn { e = new Edge(tP,nPoint, thickness, myBranch); // Neue Kannte wird geschrieben und in constructlist fŸr weitere Teilungen geschrieben myBranch.constructList.add(e); } else { nPoint = nPoint.intersection (tP); // Schnittpunkt mit dem Ausgabefenster wird zurŸckgegeben e = new Edge(tP,nPoint, thickness, myBranch); // Kannnte bis zum Rand des Ausgabefeldes wird geschrieben } myBranch.printList.add(e); myBranch.pointList.add(new Point(newXPosition,newYPosition)); } //------------------ZWEIMALIGES TEILEN DIESER KANNTE----------------------------- void divide(float teilVerhaeltnis,float d, float winkel) { float range = winkel; float tV = teilVerhaeltnis; tV = random(tV,1); Point tP = new Point(this.point1.x+tV*(point2.x-point1.x),point1.y+tV*(point2.y-point1.y)); // neuer Punkt auf der Kannte im TeilverhŠltnis TV wird erstellt Edge e1 = new Edge(point1,tP,thickness, myBranch); // neue Teilstrecken auf der Kannnte werden definiert Edge e2 = new Edge(tP,point2,thickness, myBranch); Point tP2 = new Point(e1.point1.x+tV*(e1.point2.x-e1.point1.x),e1.point1.y+tV*(e1.point2.y-e1.point1.y)); // neuer Punkt auf der NEUEN Kannte im TeilverhŠltnis TV wird erstellt Edge e3 = new Edge(e1.point1,tP2,thickness, myBranch); // neue Teilstrecken auf der Kannnte werden definiert Edge e4 = new Edge(tP2,e1.point2,thickness, myBranch); thickness = thickness * schwindFaktor; // Astdicke verkleinern if (myBranch.type == 3 || myBranch.type == 4 || myBranch.type == 5) // Astdicke schneller verkleinern, weil bei diesen Typen pro Teilungszenario mehr Aeste entstehen { if (endPunktVariante != 2) { thickness = thickness * schwindFaktor; } } float w = edgeAngle + range; float newXPosition = tP.x +(cos(w)*d); // neuer Punkt wird Berechnet float newYPosition = tP.y +(sin(w)*d); Point newPoint = new Point(newXPosition,newYPosition); int positionPunkt = newPoint.testAusgabeFenster(); // Methode wird aufgerufen, die ŸberprŸft, ob neuer Punkt im Ausgabefeld liegt. 1 = liegt drinn if (positionPunkt==0) { newPoint = newPoint.intersection (tP); // Schnittpunkt mit dem Ausgabefenster wird zurŸckgegeben } Edge e5 = new Edge(tP,newPoint, thickness, myBranch); // Neue Kannte wird geschrieben w = edgeAngle - range; newXPosition = tP2.x +(cos(w)*d); // neuer Punkt wird Berechnet newYPosition = tP2.y +(sin(w)*d); newPoint = new Point(newXPosition,newYPosition); int positionPunkt2 = newPoint.testAusgabeFenster(); // Methode wird aufgerufen, die ŸberprŸft, ob neuer Punkt im Ausgabefeld liegt. 1 = liegt drinn if (positionPunkt2==0) { newPoint = newPoint.intersection (tP2); // Schnittpunkt mit dem Ausgabefenster wird zurŸckgegeben } Edge e6 = new Edge(tP2,newPoint, thickness, myBranch); myBranch.constructList.remove(this); // Kannte die 2mal geteiltwurde wird aus printList und constructList entfernt myBranch.printList.remove(this); myBranch.printList.add(e3); // zwei TeilstŸcke der inzwischen geteilten Kannte werden in die printList geschriebn myBranch.printList.add(e4); if (endPunktVariante == 1 || endPunktVariante == 2) { myBranch.printList.add(e2); } myBranch.printList.add(e5); myBranch.printList.add(e6); if (positionPunkt + positionPunkt2 == 2) // wenn Kannten im Ausgabefenster liegen: { // - Neue Kannten werden in zufŠlliger reihenfolge in constructlist geschrieben float a = random(1,10); // - Typen 3 und 4 kšnnen daher einfacher variiert werden und Typ 5 zeichnet sich nicht symetrisch (schšner if (a > 5) { myBranch.constructList.add(e5); myBranch.constructList.add(e6); myBranch.pointList.add(e5.point2); myBranch.pointList.add(e6.point2); } else { myBranch.constructList.add(e6); myBranch.constructList.add(e5); myBranch.pointList.add(e6.point2); myBranch.pointList.add(e5.point2); } } else // nur Kannte die nicht bis ans Ausgabefeld grenzen werden in constructList zum Weiterteiln geschrieben { if (positionPunkt==1) { myBranch.constructList.add(e5); myBranch.pointList.add(e5.point2); } if (positionPunkt2==1) { myBranch.constructList.add(e6); myBranch.pointList.add(e6.point2); } } } //---------------ERSTELLT KLEINE ZWEIGE AM ENDE DER GABELUNGEN Blatttyp 1 void ending (float winkel) // schreibt zwei kleine Zweige am Ende der Gabelungen (pointList) { // speicher diese in endingList float w = winkel; float l = d/4; for (int i = 0; i < myBranch.pointList.size(); i++) { Point start = (Point)myBranch.pointList.get(i); int l2 = int(random(l/2,l)); Point nP = new Point(start.x-l2/3,start.y-l2); Edge e = new Edge(start,nP,1,myBranch); myBranch.endingList.add(e); nP = new Point(start.x+l2/3,start.y-l2); e = new Edge(start,nP,1,myBranch); myBranch.endingList.add(e); l= l * (verkuerzung+0.02); } } //---------------ERSTELLT KLEINEN ZWEIG AM ENDE DER GABELUNG Blatttyp 2 void ending2 (float laenge) // schreibt einen kleinen Zweig am Ende der Gabelungen (pointList) { // speicher diesen in endingList float l = laenge; for (int i = 0; i < myBranch.pointList.size(); i++) { Point start = (Point)myBranch.pointList.get(i); Point nP = new Point(start.x,start.y-l); Edge e = new Edge(start,nP,1,myBranch); myBranch.endingList.add(e); l= l * verkuerzung; } } //---------------ZEICHNET KANNTE void drawMe(int rot, int gruen, int blau) { int r = rot; int g = gruen; int b = blau; strokeWeight(thickness); stroke(r,g,b); line(point1.x,point1.y,point2.x,point2.y); } //---------ZEICHNET ELLIPSE---------------------- void drawMe(float ellipseX, float ellipseY, int rot, int gruen, int blau, int nummerDerAusfuerung) // linie mit Endpunkt { int r = rot; int g = gruen; int b = blau; int nDA = nummerDerAusfuerung; // steuert Verkleinerung der Ellipse strokeWeight(thickness); stroke(r,g,b); fill(255); float rFactor; if (myBranch.type < 3) // Baumtypen 3, 4 und 5 mŸssen langsamer verkleinern { rFactor = pow(verkuerzung,nDA); } else { rFactor = pow(verkuerzung,nDA/3); } ellipse (point2.x, point2.y,ellipseX*rFactor,ellipseY*rFactor); } }