# Rollkurven (zykloide) darstellen



## lachzb9be (7. Dez 2010)

Hallo,

ich brauch dringend Hilfe. Undzwar möchte ich ein Javaprogramm coden, dass eine Zykloide zeichnen kann. (Zykloide ? Wikipedia) Das Zeichnen ansich geht schonmal . nun möchte ich das animieren das der graph quasi stück für stück entsteht (aber nicht als javascript). wäre nett wenn mir wer helfen kann.
VIelen Dank schonmal

```
import java.awt.*;
import java.awt.event.ActionListener;

import javax.swing.JPanel;



public class Cycloid extends JPanel {

    int r1;
    int r2;
    Polygon p;
    Point pu;
    int centerx = 50;
    int centery= 100;
    final int numPoints = 100;




      
	public Cycloid (int inner , int outer) {
		r1 = inner;
		r2 = outer;
		p = new Polygon ( );
		for (int t = 0; t <  numPoints; t++) {
			double theta = 2.0 * Math.PI * t / numPoints;
			double x = (r1 + r2) * Math.cos (theta) + r2 * Math.cos (theta * r1 / r2);
			double y = (r1 + r2) * Math.sin  (theta) + r2 * Math.sin  (theta * r1 / r2);
			p.addPoint ( centerx + (int)x,  centery +(int) y);
		}
	}
	public Cycloid (int rad) {
		r1 = rad;
		p = new Polygon ();
		for (double t = 0; t <  numPoints;) {
			double x = (r1) * (t - Math.sin (t));
			double y = (r1) *(1- Math.cos  (t));
			p.addPoint ( centerx + (int)x,  centery -(int) y);
			t=t+0.01;
		}
	}


	public void paintComponent (Graphics g) {
		   super.paintComponent (g);
		   g.setColor (Color.blue);
		   g.drawPolygon (p);
		   repaint();
		   }
		   
		
}
```

und hier die testklasse


```
import javax.swing.*;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class testCycloid  extends JFrame implements ActionListener{
	private JTextField eingabe;
	private JButton uebernehmen;
	int radius;
	public testCycloid () {
		eingabe = new JTextField(10);
		uebernehmen = new JButton("Übernehmen");
		uebernehmen.addActionListener(this);
		getContentPane ().setLayout (new GridLayout ());
		getContentPane ().add (eingabe);
		getContentPane ().add (uebernehmen);
		pack();
		};
		public void actionPerformed(ActionEvent e) {
			if (e.getActionCommand() == "Übernehmen")
				radius = Integer.parseInt (eingabe.getText());
				getContentPane ().add  (new Cycloid (radius));
				repaint();
		  }
	public static void main(String[ ] args) {
				testCycloid pict = new testCycloid();
				pict.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
				//pict.setSize (1024, 300);
				pict.setVisible (true);
		
	}
}
```

des weiteren wäre es gut wenn der rollkreis auch mit dargestellt werden würde in der animation


----------



## SlaterB (8. Dez 2010)

'wäre es gut wenn der rollkreis auch mit dargestellt werden'
da du den bisher gewiss noch gar nicht hast ist das eine kühne Formulierung, komplizierter als das komplette Restprogramm ,

was du brauchst ist ein Thread mit einer Schleife, der alle 50ms ein oder ein paar Punkte ins Polygon hinzufügt und repaint() aufruft
schau dir z.B.
Animation: Swing and thread : Swing ThreadThreadsJava
an

den Kreis musst du auch modellieren, zu jedem Zeitpunkt vor dem repaint nicht nur das Polygon aktuell halten, sondern irgendwo
auch den ausgerechneten Mittelpunkt des Kreises speichern und in paint dann den Kreis malen + eine Kante vom letzten Punkt des Polygons zum Mittelpunkt des Kreises oder was auch immer nötig ist


----------



## lachzb9be (8. Dez 2010)

hey danke für deine schnelle antwort. leider bin ich recht neu was das ganze java coden angeht. mit diesem buffered kram kann ich nicht viel anfangen. gibts nicht ne möglichtkeit das polygon einfach stückweise auszugeben?

habs mal mit nem thread sleep versucht beim points adden. problem nun ist dass das fenster erst aufgeht wenn alles fertig ist 


```
import java.awt.*;
import java.awt.event.ActionListener;

import javax.swing.JPanel;



public class Cycloid extends JPanel {

    int r1;
    int r2;
    Polygon p;
    Point pu;
    int centerx = 50;
    int centery= 100;
    final int numPoints = 100;




      
	public Cycloid (int inner , int outer) {
		r1 = inner;
		r2 = outer;
		p = new Polygon ( );
		for (int t = 0; t <  numPoints; t++) {
			double theta = 2.0 * Math.PI * t / numPoints;
			double x = (r1 + r2) * Math.cos (theta) + r2 * Math.cos (theta * r1 / r2);
			double y = (r1 + r2) * Math.sin  (theta) + r2 * Math.sin  (theta * r1 / r2);
			p.addPoint ( centerx + (int)x,  centery +(int) y);
		}
	}
	public Cycloid (int rad) {
		r1 = rad;
		p = new Polygon ();
		for (double t = 0; t <  numPoints;) {
			double x = (r1) * (t - Math.sin (t));
			double y = (r1) *(1- Math.cos  (t));
			p.addPoint ( centerx + (int)x,  centery -(int) y);
			t=t+0.01;
			try {
				Thread.sleep(1);
				
				} catch (InterruptedException e){}	
				
		}
	}


	public void paintComponent (Graphics g) {
		   super.paintComponent (g);
		   g.setColor (Color.blue);
		   g.drawPolygon (p);
		   repaint();
		   }
		   
		
}
```



Hab dann noch was anderes probiert. Hier animiert er das ganze nur es sieht aus als wenn er nen fill polygon macht sieht total komisch aus.


```
import java.awt.*;
import java.awt.event.*;

public class Example2404
extends Frame
implements Runnable
{

   public static void main(String[] args)
   {
      Example2404 wnd = new Example2404();
      wnd.setSize(550,550);
      wnd.setVisible(true);

   }

   public Example2404()
   {
      super("Example2404");
      setBackground(Color.lightGray);
      //WindowListener
      addWindowListener(
         new WindowAdapter() {
            public void windowClosing(WindowEvent event)
            {
               System.exit(0);
            }
         }
      );
   }




   public void paint(Graphics g)
   {	
	    g.setColor (Color.blue);
		int r1 = 10;
		Polygon p = new Polygon ();
		for (double t = 0; t <  50;) {
			double x = (r1) * (t - Math.sin (t));
			double y = (r1) *(1- Math.cos  (t));
			p.addPoint ( 10 + (int)x,  50 -(int) y);
			t=t+0.02;	
			try {
	            Thread.sleep(10);
	            repaint();
	         } catch (InterruptedException e) {
	            //nichts
	         }
	        repaint();
			g.drawPolygon (p);
   }
   }
}
```


----------



## SlaterB (8. Dez 2010)

die Struktur vom Link ist schon unumgänglich,
du brauchst ein Thread, in etwa so mit Runnable + run()-Methode, wie dort zu sehen,
was ein Thread ist usw. kannst du in Lehrbüchern/ Internet nachlesen,
ich empfehle auch dieses Tutorial:
http://www.ralf-bauer.org/java/tutorial/Tutorial.zip

nur 'irgendwo anders' eine Schleife einzufügen, das bringt nix,
eine sleep-Zeit von 1 ms ist auch etwas knapp, unter 30 ist eher Zufall ob Java überhaupt ne Pause macht, 
und 30ms wären immer noch 33x pro Sekunde, das sollte doch reichen


----------



## lachzb9be (8. Dez 2010)

aber wieso sieht der untere versuch so aus als wenn er ein fillpolygon macht anstatt ein draw?


----------



## SlaterB (8. Dez 2010)

draw malt hier anscheindend ein geschlossenes Polygon,

verwende nur einmal
> g.drawPolygon (p);
am Ende nach der Schleife und teste verschiedene t,
und jetzt stell dir vor wie die alle übereinander gemalt werden,

auch dein Programm mit
>  t = t + 1;
statt
> t=t+0.02;   
zeigt etwas genauer was passiert, dazu dann besser 
> Thread.sleep(100);

generell ist aber schwer verboten, in paint sleep() oder repaint() aufzurufen

------

das Problem mit den geschlossenen Polygon wirst du allerdings mit Thread genauso haben,
da muss man einen besseren Befehl suchen, oder alle Punkte in entgegensetzter Reihenfolge nochmal einfügen, 
damit das Polygon in Kurve zurücktapselt statt eine glatte Linie zum Ursprung zu ziehen


----------



## lachzb9be (8. Dez 2010)

```
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Polygon;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;

public class SwingWithThread extends JComponent {
  private Image[] frameList;

  private long msPerFrame;

  private volatile int currFrame;

  private Thread internalThread;
  int r1;
  Polygon p;
  double t= 0;
  private volatile boolean noStopRequested;

  public SwingWithThread(int width, int height, long msPerCycle, int framesPerSec,
      Color fgColor) {

    setPreferredSize(new Dimension(width, height));

    int framesPerCycle = (int) ((framesPerSec * msPerCycle) / 1000);
    msPerFrame = 1000L / framesPerSec;

    frameList = buildImages(width, height, fgColor, framesPerCycle);
    currFrame = 0;

    noStopRequested = true;
    Runnable r = new Runnable() {
      public void run() {
        try {
          runWork();
        } catch (Exception x) {
          // in case ANY exception slips through
          x.printStackTrace();
        }
      }
    };

    internalThread = new Thread(r);
    internalThread.start();
  }

  private Image[] buildImages(int width, int height, Color color, int count) {

    BufferedImage[] im = new BufferedImage[200];

    for (int i = 0; i < 200; i++) {
      im[i] = new BufferedImage(width, height,
          BufferedImage.TYPE_INT_ARGB);

		r1 = 10;
		p = new Polygon ();
			double x = (r1) * (t - Math.sin (t));
			double y = (r1) *(1- Math.cos  (t));
			p.addPoint ( 50 + (int)x,  50 -(int) y);
			t=t+0.01;
      
      
      
      Graphics2D g2 = im[i].createGraphics();
      g2.setColor(color);
      g2.draw(p);
      g2.dispose();
    }

    return im;
  }

  private void runWork() {
    while (noStopRequested) {
      currFrame = (currFrame + 1) % frameList.length;
      repaint();

      try {
        Thread.sleep(msPerFrame);
      } catch (InterruptedException x) {
        Thread.currentThread().interrupt();
      }
    }
  }

  public void stopRequest() {
    noStopRequested = false;
    internalThread.interrupt();
  }

  public boolean isAlive() {
    return internalThread.isAlive();
  }

  public void paint(Graphics g) {
    g.drawImage(frameList[currFrame], 0, 0, this);
  }

  public static void main(String[] args) {
    SwingWithThread redSquish = new SwingWithThread(500, 500, 2500L, 5, Color.blue);
    JFrame f = new JFrame();
    f.setLayout(new FlowLayout());
    f.add(redSquish);
    f.setSize(450, 250);
    f.setVisible(true);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
```


----------



## SlaterB (8. Dez 2010)

nur weil der Link komplizierte Sachen enthält wie die BufferedImages oder komplizierte Berechnung der FramesPerSecond, muss man die nicht alle auch verwenden,
wenn man ungefähr ne Ahnung hat, was ein Thread ist, dann kann man dort die Verwendung erkennen,
aber das magst du wohl nicht vorher lernen..

naja, damit es mal voran geht:

```
public class Test {
    public static void main(String[] args)    throws Exception  {
        SwingWithThread redSquish = new SwingWithThread();
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(redSquish);
        f.setSize(450, 250);
        f.setVisible(true);
    }
}

class SwingWithThread  extends JPanel {
    int r1 = 10;
    Polygon p = new Polygon();
    double t = 0;

    public SwingWithThread()  {
        Runnable r = new Runnable()  { // viel blah blah-Code, nur damit runWort() nebenläufig läuft
                public void run()  {
                    try  {
                        runWork();
                    }  catch (Exception x)  {
                        x.printStackTrace();
                    }
                }
            };
        new Thread(r).start();
    }

    private void runWork()  throws Exception {
        while (true)  { // in einer Schleife den Zustand alle x ms ändern
            double x = (r1) * (t - Math.sin(t)); 
            double y = (r1) * (1 - Math.cos(t));
            p.addPoint(50 + (int)x, 50 - (int)y);
            t = t + 1;
            repaint(); // Zeichnen veranlassen
            Thread.sleep(300);
        }
    }

    public void paintComponent(Graphics g) { // besser als paint
        super.paintComponent(g);
        g.drawPolygon(p); // einfach nur aktuellen Zustand malen
    }
}
```


----------



## lachzb9be (8. Dez 2010)

wow super ich danke dir dann versuch ich nun mal da durchzusteigen und den kreis einzufügen und vllt das polygon durch ne polyline zu ersetzen das man dieses geschlossene nicht hat


----------



## SlaterB (8. Dez 2010)

ach ja, PolyLine war das


----------



## Marco13 (8. Dez 2010)

Statt Polygon bietet sich Path2D (Java Platform SE 6) an, damit kann man einfacher Linienzüge erstellen....


----------



## lachzb9be (8. Dez 2010)

problem bei der polyline ist er erwartet 2 int arrays mit den punkten für x und y und n für anzahl der punkte wenn ich das einbaue und dann unten die polyline zeichnen lasse macht er wieder nüscht


----------



## SlaterB (8. Dez 2010)

Path2D also besser, siehe Marco13

wollte noch erwähnen dass ich die t-Ändeung und sleep() modifiziert habe, kannst du auch wieder erhöhen damit nicht so keine Krakelkurve rauskommt


----------



## lachzb9be (8. Dez 2010)

jo hab ich schon gesehn vielen dank euch 2 ich guck mit mal das path2d an ob ich das hinebkomme und nochmals danke


Path2D klappt super vielen dank!


----------

