# Dreieck um den Mittelpunkt rotieren lassen



## Deception (8. Mai 2007)

Hey Leute,
Ich habe ein Dreieck in einem Polygon! Das Dreieck ist gleichschenklig, daher hat es eine Spitze C, deren Punkte A und B gleich weit voneinander entfernt sind. Nun möchte ich das Dreieck nach Links oder Rechts drehen lassen. 
Das ganze ist nun vielleicht eine eher mathematische Frage: Wie berechne ich die Koordinaten für A' B' und C'? 
Ich habe mich heute schon den ganzen Tag damit beschäftigt und etwas von AffineTransformation gelesen! Kann man das auch irgendwie auf ein Polygon anwenden? Wie erstelle ich diese AT Matrix, irgendwie hab ich damit leichte denk Probleme! ): 
Code hab ich jetzt direkt noch keinen zur Verfügung, da ich mir erstmal über das WIE Gedanken mache... Hoffe mir kann trotzdem jmd. das ganze erklären und Code Beispiel wäre natürlich noch am aller besten  
Vielen Dank,
Jens


----------



## Marco13 (8. Mai 2007)

Polygon ist ein bißchen "unpraktisch", um es zu rotieren, aber mit einer AffineTransform geht es einigermaßen. Du würdest dann erst den Mittelpunkt ausrechnen 

```
double x = (polygon.xpoints[0] + polygon.xpoints[1] + polygon.xpoints[2])/3.0;
double y = (polygon.ypoints[0] + polygon.ypoints[1] + polygon.ypoints[2])/3.0;
```
dann eine passende AffineTransform erstellen, die um den Mittelpunkt rotiert

```
AffineTransform at = new AffineTransform();
at.setToRotation(Math.toRadians(45), x,y);
```
und die dann (das ist jetzt das "unpraktische") auf das Polygon anwenden

```
for (int i=0; i<polygon.npoints; i++)
{
    Point2D.Double p = new Point2D.Double(polygon.xpoints[i], polygon.ypoints[i]);
    at.transform(p);
    polygon.xpoints[i] = (int)p.x;
    polygon.ypoints[i] = (int)p.y;
}
```

Wenn du das Polygon aber "häufiger" rotieren willst, solltest du das Original speichern, und immer nur eine Kopie mit den Daten des gedrehten Polygons füllen - sonst entstehen (durch das casten nach int) riesige Rundungsfehler.


----------



## Deception (8. Mai 2007)

Vielen Dank schonmal! Also das Dreieck rotiert, das gefällt mir schonmal  
Aber es bewegt sich gleichzeitig in eine richtung nach oben rechts? Woran liegt das? :/ 
Ich hab den Code von dir einfach mal übernommen bzw. ihn ein wenig für mich angepasst:


```
public void rotate()
	{
		Polygon polygon = new Polygon();
		polygon.addPoint((int)xkoordSpitze, (int)ykoordSpitze);
		polygon.addPoint((int)xkoordLinks, (int)ykoordLinks);
		polygon.addPoint((int)xkoordRechts, (int)ykoordRechts);
		

		double x = (polygon.xpoints[0] + polygon.xpoints[1] + polygon.xpoints[2])/3.0;
		double y = (polygon.ypoints[0] + polygon.ypoints[1] + polygon.ypoints[2])/3.0;
		
		AffineTransform at = new AffineTransform();
		at.setToRotation(Math.toRadians(winkel), x,y);
		
		for (int i=0; i<polygon.npoints; i++)	
		{
		    Point2D.Double p = new Point2D.Double(polygon.xpoints[i], polygon.ypoints[i]);
		    at.transform(p,p);
		    polygon.xpoints[i] = (int)p.x;
		    polygon.ypoints[i] = (int)p.y;
		}
		xkoordSpitze = polygon.xpoints[0];
		xkoordLinks = polygon.xpoints[1];
		xkoordRechts = polygon.xpoints[2];
		
		ykoordSpitze = polygon.ypoints[0];
		ykoordLinks = polygon.ypoints[1];
		ykoordRechts = polygon.ypoints[2];
	}
```


----------



## Marco13 (9. Mai 2007)

Kannst du was compilierbares/lauffähiges posten? Sooo langweilig ist mir nun gerade nicht...


----------



## Deception (9. Mai 2007)

Hey,
ist aber nichts schönes, sehr umständlich zum Teil, da es nur zum Ausprobieren war, für nen Spiel  


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Polygon;

import javax.swing.JPanel;

public class MyPanel extends JPanel
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Dreieck d;
	
	public MyPanel()
	{
		super();
		d = new Dreieck(this);
		d.start();
	}
	
	public void paint(Graphics g)
	{
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, 500, 500);
		if(d != null)
		{
			double[] xkoords = d.getXkoords();
			double[] ykoords = d.getYkoords();
			Polygon polygonen = new Polygon();
			
			polygonen.addPoint((int)xkoords[0], (int)ykoords[0]);
			polygonen.addPoint((int)xkoords[1], (int)ykoords[1]);
			polygonen.addPoint((int)xkoords[2], (int)ykoords[2]);
			
			g.setColor(Color.RED);
			g.fillPolygon(polygonen);
		}
	}
}

import java.awt.Polygon;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;

public class Dreieck extends Thread
{
	private double winkel= 90;
	private double xkoordSpitze;
	private double xkoordLinks;
	private double xkoordRechts;
	private double ykoordSpitze;
	
	private double ykoordLinks;
	private double ykoordRechts;
	private int speed = 0;
	
	private MyPanel panel;
	
	public Dreieck(MyPanel panel)
	{
		this.panel = panel;
		xkoordSpitze = 65;
		xkoordLinks = 45;
		xkoordRechts = 85;
		
		ykoordSpitze = 50;
		ykoordLinks = 70;
		ykoordRechts = 70;
	}
	
	/**
	 * Gibt die x-Koordinate des Schiffes zurueck
	 * 
	 * @return xkoord double
	 */
	public double[] getXkoords()
	{
		double[] xkoords = new double[3];
		xkoords[0] = xkoordSpitze;
		xkoords[1] = xkoordLinks;
		xkoords[2] = xkoordRechts;
		return xkoords;
	}
	/**
	 * Gibt die y-Koordinate des Schiffes zurueck
	 * 
	 * @return ykoord double
	 */
	public double[] getYkoords()
	{
		double[] ykoords = new double[3];
		ykoords[0] = ykoordSpitze;
		ykoords[1] = ykoordLinks;
		ykoords[2] = ykoordRechts;
		return ykoords;
	}
	
	public void turnLeft()
	{
		winkel -= 5;
		rotate();
		panel.repaint();
	}
	public void rotate()
	{
		Polygon polygon = new Polygon();
		polygon.addPoint((int)xkoordSpitze, (int)ykoordSpitze);
		polygon.addPoint((int)xkoordLinks, (int)ykoordLinks);
		polygon.addPoint((int)xkoordRechts, (int)ykoordRechts);
		

		double x = (polygon.xpoints[0] + polygon.xpoints[1] + polygon.xpoints[2])/3.0;
		double y = (polygon.ypoints[0] + polygon.ypoints[1] + polygon.ypoints[2])/3.0;
		
		AffineTransform at = new AffineTransform();
		at.setToRotation(Math.toRadians(winkel), x,y);
		
		for (int i=0; i<polygon.npoints; i++)	
		{
		    Point2D.Double p = new Point2D.Double(polygon.xpoints[i], polygon.ypoints[i]);
		    at.transform(p,p);
		    polygon.xpoints[i] = (int)p.x;
		    polygon.ypoints[i] = (int)p.y;
		}
		xkoordSpitze = polygon.xpoints[0];
		xkoordLinks = polygon.xpoints[1];
		xkoordRechts = polygon.xpoints[2];
		
		ykoordSpitze = polygon.ypoints[0];
		ykoordLinks = polygon.ypoints[1];
		ykoordRechts = polygon.ypoints[2];
	}

	public void turnRight()
	{
		winkel += 5;
		rotate();
		panel.repaint();
	}
	
	public void erhoeheSpeed()
	{
		speed += 1;
	}
	
	public void run()
	{
		try
		{
			Thread.sleep(2000);
			for(int i = 0; i < 20; i++)
			{
				turnRight();
				Thread.sleep(200);
			}
			Thread.sleep(3000);
			for(int j = 0; j < 20; j++)
			{
				turnLeft();
				Thread.sleep(200);
			}
		}
		catch(InterruptedException ie)
		{
			
		}
	}
}
import javax.swing.JFrame;

public class MyFrame
{
	public static void main(String[] args)
	{
		JFrame frame = new JFrame("Rotation eines Dreiecks");
		MyPanel panel = new MyPanel();
		frame.getContentPane().add(panel);
		frame.setSize(200,200);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}
```

Sry


----------



## Quickbeam2k1 (9. Mai 2007)

Also ich als mathematiker würde da mal folgendes sagen:

Ich nehme mal an wir sind im R^2, also in der Ebene.

Das heisst die Eckpunkte meines Dreiecks sind jeweils ein Vektor (x_1,x_2).

Nun definiere ich eine Euklidische Bewegung.

f(x)=A*x+b
Hierbei ist x ein Vektor sowas wie (1,2).
b ist dann der Vektor der für die affine Transformation zuständig ist. Der Verschiebt dir also alle deine Punkte entsprechend.

Die Matrix A ist nun die Matrix die für die Drehung zuständig ist.

Hier nimmt man auch direkt eine sogenannte Drehmatrix der Form:

( cos alpha, sin alpha \\ <<- neue Zeile
  -sin alpha, cos alpha)

Wobei alpha halt aus 0 bis 2pi ist.

Diese Abbildugn wenndest du nun auf deine 3 Eckpunkte an. Diese werden also transformiert, so dass du dir nur merken musst welche Punkte du nun miteinander verbinden möchtest.

Also gar keinen Umweg über den Schwerpunkt des Dreiecks


----------



## Marco13 (9. Mai 2007)

Marco13 hat gesagt.:
			
		

> Wenn du das Polygon aber "häufiger" rotieren willst, solltest du das Original speichern, und immer nur eine Kopie mit den Daten des gedrehten Polygons füllen - sonst entstehen (durch das casten nach int) riesige Rundungsfehler.



Das war nicht nur so dahin gesagt :roll: Dein Dreieck verschiebt sich nicht nur, sondern es verformt sich auch. Früher oder später würde es zu einem Punkt (bei 0,0) zusammenschnurren, weil bei jedem casten nach 'int' wichtige Nachkommastellen weggeschnitten werden.

Also: Du mußt einmal dein Original-Dreieck speichern, und dann immer nur die gedrehte Kopie anzeigen. Abgesehen davon, dass du das Dreieck "immer schneller" gedreht hast: Erst um 5 grad, dann um 10 Grad, dann um 15 Grad - das macht NUR Sinn, wenn man immer vom gleichen (ungedrehten) Dreieck ausgeht.

Du solltest dein Dreieck (und jede kompliziertere Objekt) vielleicht etwas "eleganter" speichern - das mit dem "xKoordSpitze" und "yKoordLinks" usw. ist ziemlich unhandlich. Aber ich habe das Programm mal im gleichen Stil (!) sinngemäß abgeändert. Die Relevanten Teile sind mit ========== markiert.


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.Polygon;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import javax.swing.*;

public class MyFrame
{
   public static void main(String[] args)
   {
      JFrame frame = new JFrame("Rotation eines Dreiecks");
      MyPanel panel = new MyPanel();
      frame.getContentPane().add(panel);
      frame.setSize(200,200);
      frame.setVisible(true);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
}

class MyPanel extends JPanel
{
   /**
    *
    */
   private static final long serialVersionUID = 1L;
   private Dreieck d;

   public MyPanel()
   {
      super();
      d = new Dreieck(this);
      d.start();
   }

   public void paint(Graphics g)
   {
      g.setColor(Color.BLACK);
      g.fillRect(0, 0, 500, 500);
      if(d != null)
      {
         double[] xkoords = d.getXkoords();
         double[] ykoords = d.getYkoords();
         Polygon polygonen = new Polygon();

         polygonen.addPoint((int)xkoords[0], (int)ykoords[0]);
         polygonen.addPoint((int)xkoords[1], (int)ykoords[1]);
         polygonen.addPoint((int)xkoords[2], (int)ykoords[2]);

         g.setColor(Color.RED);
         g.fillPolygon(polygonen);
      }
   }
}

class Dreieck extends Thread
{
   private double winkel= 90;
   private double xkoordSpitze;
   private double xkoordLinks;
   private double xkoordRechts;
   private double ykoordSpitze;
   private double ykoordLinks;
   private double ykoordRechts;


   //========================================= Original-Koordinaten
   private double xkoordSpitzeOrig;
   private double xkoordLinksOrig;
   private double xkoordRechtsOrig;
   private double ykoordSpitzeOrig;
   private double ykoordLinksOrig;
   private double ykoordRechtsOrig;


   private int speed = 0;

   private MyPanel panel;


   public Dreieck(MyPanel panel)
   {
      this.panel = panel;

      //========================================= Original-Koordinaten bekommen Werte
      xkoordSpitzeOrig = 65;
      xkoordLinksOrig = 45;
      xkoordRechtsOrig = 85;

      ykoordSpitzeOrig = 50;
      ykoordLinksOrig = 70;
      ykoordRechtsOrig = 70;

      xkoordSpitze = xkoordSpitzeOrig;
      xkoordLinks = xkoordLinksOrig;
      xkoordRechts = xkoordRechtsOrig;

      ykoordSpitze = ykoordSpitzeOrig;
      ykoordLinks = ykoordLinksOrig;
      ykoordRechts = ykoordRechtsOrig;
   }

   /**
    * Gibt die x-Koordinate des Schiffes zurueck
    *
    * @return xkoord double
    */
   public double[] getXkoords()
   {
      double[] xkoords = new double[3];
      xkoords[0] = xkoordSpitze;
      xkoords[1] = xkoordLinks;
      xkoords[2] = xkoordRechts;
      return xkoords;
   }
   /**
    * Gibt die y-Koordinate des Schiffes zurueck
    *
    * @return ykoord double
    */
   public double[] getYkoords()
   {
      double[] ykoords = new double[3];
      ykoords[0] = ykoordSpitze;
      ykoords[1] = ykoordLinks;
      ykoords[2] = ykoordRechts;
      return ykoords;
   }

   public void turnLeft()
   {
      winkel -= 5;
      rotate();
      panel.repaint();
   }
   public void rotate()
   {
      //========================================= Polygon auf Basis der Original-Koordinaten erstellen 
      Polygon polygon = new Polygon();
      polygon.addPoint((int)xkoordSpitzeOrig, (int)ykoordSpitzeOrig);
      polygon.addPoint((int)xkoordLinksOrig, (int)ykoordLinksOrig);
      polygon.addPoint((int)xkoordRechtsOrig, (int)ykoordRechtsOrig);


      double x = (polygon.xpoints[0] + polygon.xpoints[1] + polygon.xpoints[2])/3.0;
      double y = (polygon.ypoints[0] + polygon.ypoints[1] + polygon.ypoints[2])/3.0;

      AffineTransform at = new AffineTransform();
      at.setToRotation(Math.toRadians(winkel), x,y);

      for (int i=0; i<polygon.npoints; i++)
      {
          Point2D.Double p = new Point2D.Double(polygon.xpoints[i], polygon.ypoints[i]);
          at.transform(p,p);
          polygon.xpoints[i] = (int)p.x;
          polygon.ypoints[i] = (int)p.y;
      }

      //========== Das, was gezeichnet wird, sind nach wie vor die xkoordSpitze usw. 
      // Die Original-Koordinaten werden immer nur verwendet, um am Anfang das un-gedrehte Polygon zu erstellen

      xkoordSpitze = polygon.xpoints[0];
      xkoordLinks = polygon.xpoints[1];
      xkoordRechts = polygon.xpoints[2];

      ykoordSpitze = polygon.ypoints[0];
      ykoordLinks = polygon.ypoints[1];
      ykoordRechts = polygon.ypoints[2];
   }

   public void turnRight()
   {
      winkel += 5;
      rotate();
      panel.repaint();
   }

   public void erhoeheSpeed()
   {
      speed += 1;
   }

   public void run()
   {
      try
      {
         Thread.sleep(2000);
         for(int i = 0; i < 20; i++)
         {
            turnRight();
            Thread.sleep(200);
         }
         Thread.sleep(3000);
         for(int j = 0; j < 20; j++)
         {
            turnLeft();
            Thread.sleep(200);
         }
      }
      catch(InterruptedException ie)
      {

      }
   }
}
```


----------



## Marco13 (9. Mai 2007)

@Quickbeam2k1: Wenn man UM den Mittelpunkt rotieren will, bleibt einem fast nichts anderes übrig, als den Mittelpunkt zu bestimmen. Und wenn man dann (wie die AffineTransform-Klasse) so spendabel ist, und für eine Transformation im 2D eine 3x3-Matrix zu verwenden, kann man praktischerweise auch eine Verschiebung (die ja eigentlich affin ist) als Lineare Abbildung beschreiben (weil man dann implizit mit homogenen Koordinaten rechnet, und eine affine Abbildung im im n-dimensionalen (in diesem Fall, aber ich glaube, auch ganz allgemein) durch eine Lineare Abbildung im n+1-dimensionalen beschrieben werden kann)


----------



## Quickbeam2k1 (9. Mai 2007)

@ marco du hast vollkommen recht  
Bei meinem Beispiel dreht man ja nur um den nullpunkt 

ich verkrich mich mal wieder in mein loch


----------



## Deception (9. Mai 2007)

Hey,
Vielen Dank ihr 2  
Also das mit den Koordinaten, wie gesagt, es ist nur zum Testen. In meinem Original Spiel wird es natürlich alles viel schöner gemacht  Auch das casten hab ich der Einfachheit wegen zum Testen weggelassen, weil ich einfach schauen wollte wies so funktioniert  
Sooo ich teste das dann bald mal durch.


----------

