Java: Koch Schneeflocken Anwendung

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Java: Koch Schneeflocken Anwendung

    Die Koch-Kurve ist ein Beispiel für eine überall stetige, aber nirgends differenzierbare Kurve. Es handelt sich bei ihr ferner um eines der ersten formal beschriebenen fraktalen Objekte. Die Koch-Kurve ist auch in Form der kochschen Schneeflocke bekannt, die durch geeignete Kombination dreier Koch-Kurven entsteht.


    Wie zeichne ich ein regelmäßiges Polygon?
    X Koordinate mit dem Sinus von 2 Pi * Zaehler / Anzahl der Polygone multiplizieren
    Y Koordinate mit dem Sinus von 2 Pi * Zaehler / Anzahl der Polygone multiplizieren

    so gebt ihr z.B. die Punkte aus

    Quellcode

    1. for(int i=0; i<AnzahlDerPunkte; i++) {
    2. double phi = i*2*Math.PI/AnzahlDerPunkte;
    3. double x = Math.sin(phi) * r;
    4. double y = Math.cos(phi) * r;
    5. System.out.println(x+";"+y);
    6. }


    Wie man aus eine Linie eine KochKurve erstellt hat unser Proffessor ausführlich an der Tafel erklärt.
    Die Formeln solltet ihr mitgeschrieben haben.

    R = 2/3 p + q/3
    T = 2/3 q + p/3
    S = knifflig ;)

    Meine rekursive Funktion ruft übrigens 4 weitere Funktionen auf und trägt den schönen Namen. MachAusEinerLinieVier()

    übergeben tue ich neben den Koordinaten noch das Graphics Objekt und die rekursionsstufe
    Und was meint ihr in welchem Fall ich die Rekursion beende?
    Richtig.. gar nicht so schwer...
    fehlt nur noch die bunte GUI. Die habe ich aber noch nicht

    UPDATE: Fertiger Code

    KochApplication.java

    Quellcode

    1. import java.awt.event.*;
    2. /**
    3. * Applikation (verbindet GUI und Kochkurve)
    4. * @author tbr
    5. *
    6. */
    7. public class KochApplication implements ItemListener, WindowListener {
    8. public static int depth=1, polygons=3;
    9. public static boolean clockwise=true;
    10. @SuppressWarnings("static-access")
    11. /**
    12. * reagiert auf Aenderungen im Formular
    13. * @param arg0 Item
    14. */
    15. public void itemStateChanged(ItemEvent arg0) {
    16. String s = arg0.getItem().toString();
    17. if(s.substring(0,5).equals("depth"))
    18. this.depth = Integer.parseInt(s.substring(6));
    19. else if(s.equals("clockwise"))
    20. this.clockwise = true;
    21. else if(s.equals("counterclockwise"))
    22. this.clockwise = false;
    23. else //4-sided
    24. this.polygons = Integer.parseInt(s.substring(0,s.indexOf("-")));
    25. }
    26. public void windowClosing(WindowEvent arg0) {
    27. System.exit(0);
    28. }
    29. public void windowOpened(WindowEvent arg0) {
    30. // TODO Auto-generated method stub
    31. }
    32. public void windowClosed(WindowEvent arg0) {
    33. // TODO Auto-generated method stub
    34. }
    35. public void windowIconified(WindowEvent arg0) {
    36. // TODO Auto-generated method stub
    37. }
    38. public void windowDeiconified(WindowEvent arg0) {
    39. // TODO Auto-generated method stub
    40. }
    41. public void windowActivated(WindowEvent arg0) {
    42. // TODO Auto-generated method stub
    43. }
    44. public void windowDeactivated(WindowEvent arg0) {
    45. // TODO Auto-generated method stub
    46. }
    47. }
    Alles anzeigen


    KochCanvas.java

    Quellcode

    1. import java.awt.*;
    2. /**
    3. * Klasse zum Zeichnen (reagiert auf Knopfdruck)
    4. * @author tbr
    5. *
    6. */
    7. @SuppressWarnings("serial")
    8. public class KochCanvas extends Canvas {
    9. /**
    10. * Konstruktor
    11. */
    12. public KochCanvas() {
    13. super.setBackground(Color.GRAY);
    14. }
    15. /**
    16. * Zeichne
    17. */
    18. public void paint(Graphics g) {
    19. //(Graphics g, weite, hoehe, rekursionstiefe, ecken, uhrzeigersinn?) {
    20. new Kochkurve(g, this.getWidth(), this.getHeight(), KochApplication.depth, KochApplication.polygons, KochApplication.clockwise);
    21. }
    22. }
    Alles anzeigen



    KochGUI.java

    Quellcode

    1. import java.awt.*;
    2. import java.awt.event.*;
    3. /**
    4. * GUI von Kochvis
    5. * @author tbr
    6. *
    7. */
    8. @SuppressWarnings("serial")
    9. public class KochGUI extends Frame {
    10. @SuppressWarnings("static-access")
    11. public KochGUI(KochApplication application) {
    12. super("KochGUI");
    13. GridBagLayout layout = new GridBagLayout();
    14. setLayout(layout);
    15. GridBagConstraints constraint = new GridBagConstraints();
    16. constraint.gridwidth = 1;
    17. constraint.gridheight = 7;
    18. constraint.gridx = 1;
    19. constraint.gridy = 1;
    20. final Canvas content = new KochCanvas();
    21. content.setSize(400,570);
    22. // constraint.fill = constraint.VERTICAL;
    23. constraint.fill = constraint.HORIZONTAL;
    24. layout.setConstraints(content, constraint);
    25. add(content);
    26. constraint.gridheight = 1;
    27. constraint.gridx = 2;
    28. constraint.gridy = 1;
    29. Label text1 = new Label("Depth of Recursion");
    30. layout.setConstraints(text1, constraint);
    31. add(text1);
    32. Choice choice1 = new Choice(); //Depth of Recursion
    33. choice1.addItemListener(application);
    34. for(int i=1; i<10; i++)
    35. choice1.add("depth "+i);
    36. constraint.gridy++;
    37. layout.setConstraints(choice1, constraint);
    38. add(choice1);
    39. Label text2 = new Label("Polygon");
    40. constraint.gridy++;
    41. layout.setConstraints(text2, constraint);
    42. add(text2);
    43. Choice choice2 = new Choice(); //Polygon
    44. choice2.addItemListener(application);
    45. for(int i=3; i<10; i++)
    46. choice2.add(i+"-sided");
    47. constraint.gridy++;
    48. layout.setConstraints(choice2, constraint);
    49. add(choice2);
    50. //Orientierung
    51. Label text3 = new Label("Orientation");
    52. constraint.gridy++;
    53. layout.setConstraints(text3, constraint);
    54. add(text3);
    55. final Choice choice3 = new Choice();
    56. choice3.addItemListener(application);
    57. choice3.add("clockwise");
    58. choice3.add("counterclockwise");
    59. constraint.gridy++;
    60. layout.setConstraints(choice3, constraint);
    61. add(choice3);
    62. Button button = new Button("draw");
    63. constraint.gridy++;
    64. constraint.ipady = 200;
    65. //constraint.fill = constraint.BOTH;
    66. layout.setConstraints(button, constraint);
    67. button.addActionListener(new ActionListener() {
    68. public void actionPerformed(ActionEvent e) {
    69. content.repaint();
    70. choice3.add("asd");
    71. //choice3.repaint();
    72. }
    73. });
    74. add(button);
    75. setSize(600,600);
    76. setLocation(150,100);
    77. // setResizable(false);
    78. pack();
    79. addWindowListener(application);
    80. setVisible(true);
    81. }
    82. }
    Alles anzeigen



    Kochkurve.java (eigentlicher Algorithmus)

    Quellcode

    1. import java.awt.*;
    2. /**
    3. * Klasse zur Berechnung des Kochpolygons
    4. * @author tbr
    5. *
    6. */
    7. public class Kochkurve {
    8. /**
    9. * Zeichnet das Polygon
    10. * Konstruktor
    11. * @param g
    12. * @param width
    13. * @param level
    14. * @param polygons
    15. * @param clockwise
    16. */
    17. public Kochkurve(Graphics g, int width, int height, int level, int polygons, boolean clockwise) {
    18. int r = width/2, paddingx=r, paddingy=height/2;
    19. int multiplikant = clockwise ? 1 : -1;
    20. Node tmp=null;
    21. for(int i=0; i<polygons+1; i++) {
    22. double phi = i*2*Math.PI/polygons;
    23. double x = Math.sin(phi) * -r * 0.85; //Fuelle nur 85% der Flaeche
    24. double y = Math.cos(phi) * -r * 0.85;
    25. Node calc = new Node(Math.round(x+paddingx), Math.round(y+paddingy));
    26. if(tmp != null)
    27. KochRek(g, tmp, calc, level, multiplikant);
    28. tmp = calc;
    29. }
    30. }
    31. /**
    32. * rekursive Funktion um aus einer Linie eine Kochkurve zu machen
    33. * @param g -> Grafikobjekt auf dem gezeichnet werden soll
    34. * @param p -> Knotenpunkt der Linie
    35. * @param q -> Knotenpunkt der Linie
    36. * @param level -> Rekursionstiefe
    37. * @param multiplikant -> um die Richtung der Operation zu beeinflussen
    38. */
    39. public void KochRek(Graphics g, Node p, Node q, int level, int multiplikant) {
    40. if(level == 1) {
    41. g.drawLine((int)Math.round(p.x),(int)Math.round(p.y),
    42. (int)Math.round(q.x), (int)Math.round(q.y));
    43. return;
    44. }
    45. Node R = new Node(p.x*2/3 + q.x/3, p.y*2/3 + q.y/3);
    46. Node T = new Node(p.x/3 + q.x*2/3, p.y/3 + q.y*2/3);
    47. Node S = new Node((int)((R.x+T.x)/2+ multiplikant*((R.y-T.y)*Math.sqrt(3)/2)),
    48. (int)((R.y+T.y)/2+ multiplikant*((T.x-R.x)*Math.sqrt (3)/2)));
    49. --level;
    50. KochRek(g, p, R, level, multiplikant);
    51. KochRek(g, R, S, level, multiplikant);
    52. KochRek(g, S, T, level, multiplikant);
    53. KochRek(g, T, q, level, multiplikant);
    54. }
    55. }
    56. /**
    57. * Abbildung eines Punktes im 2 Dimensionalen Koordinatensystem
    58. * @author Torben Brodt
    59. *
    60. */
    61. class Node {
    62. public double x, y;
    63. public Node(double x, double y) {
    64. this.x = x;
    65. this.y = y;
    66. }
    67. }
    Alles anzeigen



    Kochvis.java

    Quellcode

    1. /**
    2. * Ruft das Koch-Programm auf
    3. * @author tbr
    4. *
    5. * Der schwedische Mathematiker Helge von Koch stellte 1904 eines der ersten
    6. * formal beschriebenen fraktalen Objekte vor, welches inzwischen als Kochsche
    7. * Schneeflocke bekannt ist. Die Kochsche Schneeflocke ist ein Beispiel für eine stetige
    8. * Kurve, die an keiner Stelle eine Tangente besitzt. Außerdem handelt es sich bei
    9. * ihr um eine unendlich lange Kurve, die eine endliche Fläche einschließt.
    10. */
    11. public class Kochvis {
    12. public static void main(String[] args) {
    13. KochApplication application = new KochApplication();
    14. new KochGUI(application);
    15. }
    16. }
    Alles anzeigen
    Dateien
  • Das Zeichnen hab ich auch schon... meine GUI ist auch fertig... leider bekomm ich die verbindung von DropDown und dem Draw (repaint();) nicht wirlich hin... Wenn ich eine System.out ausgabe bei den Events mache, funktoniert das richtig, aber die wenn jetzt die KochKurve neu mit den anderen Werten gezeichnet werden soll, zeichnet er immer noch das Standard Dreieck. grml :)
  • "Sw00sh!" schrieb:

    leider bekomm ich die verbindung von DropDown und dem Draw (repaint();) nicht wirlich hin... Wenn ich eine System.out ausgabe bei den Events mache, funktoniert das richtig, aber die wenn jetzt die KochKurve neu mit den anderen Werten gezeichnet werden soll, zeichnet er immer noch das Standard Dreieck.


    Ich habe ein ähnliches Problem: System.out.println() funktioniert beim Button-Drücken und wenn ich das Fenster repainte, indem ich es minimiere und wiederherstelle, sehe ich auch die Veränderungen, aber der Button löst einfach kein repaint aus. :-/
  • Probleme beim Neuzeichnen

    Hallo,
    Ich habe auch ein kleines Problem mit dem Programm. Ganz ähnlich wie oben beschrieben, bekomme ich immer nur das Standard-Dreieck angezeigt. Selbst minimieren/canvas.repaint() helfen nicht. Ich habe ein Canvas als Attribut in meiner KochGUI angelegt. Sobald der Button gedrueckt wird, wir dem KochGUI ein neues Canvas mit den aktuellen Parametern übergeben (this.canvas = ...) Dieses soll dann mit this.canvas.repaint() neu gezeichnet werden, aber es funzt einfach nett. sobald ich allerdings noch add(canvas) dazuschreibe, sehe ich das Vieleck. Jedoch geht hierbei natürlich das gesamte Layout flöten.

    Hat jemand eine Ahnung???
    >: 4 8 15 16 23 42
  • ergänzung zu oben...

    Ach ja,

    erstens habe ich keine Paint in der KochGUi - Klasse. Weiß nicht, ob das vieleich nötig wäre...?

    Zweitens ergibt das toString() meines neuen Canvas, dass es invalid ist,... :
    kochscheSchneeflocke.KochCanvas[canvas0,4,30,600x900]
    kochscheSchneeflocke.KochCanvas[canvas1,0,0,600x900,invalid]
    kochscheSchneeflocke.KochCanvas[canvas2,0,0,600x900,invalid]
    kochscheSchneeflocke.KochCanvas[canvas3,0,0,600x900,invalid]
    kochscheSchneeflocke.KochCanvas[canvas4,0,0,600x900,invalid]
    (ergebniss nach 4 mal auf button-drücken)
    Auf den ersten Blick scheint das etwas mit den Parametern zu tun zu haben, die 0 sind. Wenn ich nur wüßte, was die bedeuten...

    nur das erste, erzeugte ist gültig, dabei werden alle auf die gleiche Art und Weise erzeugt, mit dem Unterschied, dass das erste in das Grid_Layout geaddet wird. Aber da es ja ein Attribut der klasse ist, dessen referenz sich lediglich ändert, dürfte das ja eigentlich nicht das Problem sein...
    >: 4 8 15 16 23 42
  • zu dem Invalid kann ich dir Leider nichts sagen??
    aber in der GUI erstelle ich das objekt nicht. Der button löst nur das repaint aus.

    Die Variablen sind bei mir in der KochApplication - da liegt ja auch die itemStateChanged()

    hier mein button:

    Quellcode

    1. GridBagConstraints constraint = new GridBagConstraints();
    2. Canvas content = new KochCanvas();
    3. [...]
    4. Button button = new Button("draw");
    5. layout.setConstraints(button, constraint);
    6. button.addActionListener(new ActionListener() {
    7. public void actionPerformed(ActionEvent e) {
    8. if (e.getActionCommand().equals("draw"))
    9. content.repaint();
    10. }
    11. });
    Alles anzeigen