# rotation eines würfels



## Gast (13. Feb 2009)

moin,
will in java2D einen würfel rotieren lassen.
klingt relativ einfach, allerdings will ich dabei nicht auf den rotationsbefehl von java2d zugreifen; das ganze soll 'mathematisch' geschehen!
zu dem zweck habe ich den würfel aus eckpunkten aufgebaut, die um den ursprung rotieren sollen.
die methode, in der rotiert wird, ist folgende:

```
public void rotation(){
   double dir = .017453293;

   for(int i=0; i!=object.length; i++){

    int object_temp[][];
    object_temp = object;

    object_temp[i][0] = (int)Math.round(object[i][0]*Math.cos(dir)-object[i][1]*Math.sin(dir));
    object_temp[i][1] = (int)Math.round(object[i][0]*Math.sin(dir)+object[i][1]*Math.cos(dir));

    object = object_temp;
  }
 }
```
die for-schleife kümmert sich darum, dass alle punkte nacheinander rotiert werden, 'object_temp' wurde verwendet, um berechnungsfehler zu vermeiden.
die rotationsformeln hab ich internetseiten entnommen, bezweifle nicht, dass sie richtig sind.
im programm findet die rotation auch statt, allerdings wird das objekt durch das 'rotieren' verzerrt.
danke schonmal so im vorraus


----------



## Illuvatar (13. Feb 2009)

Die Rotationsmatrix sieht eigentlich richtig aus. Ich finde es gerade etwas befremdlich, dass der Winkel in der Methode fest reincodiert ist, aber das sollte nichts daran ändern, dass es rotiert.
Ich würde jetzt eher vermuten, dass der Fehler woanders liegt.

Edit: Arg, nein die Methode ist falsch. 

Das Problem liegt in Zeilen 6 und 7. Ich hab mich auch kurz verwirren lassen, aber so erstellst du kein neues Objekt. Nach "object_temp = object" ist das ja beides die selbe Variable  Also bringt dir dein temp-Objekt so gar nichts.
Bevor du da jetzt dein ganzes Array in jedem Schleifendurchlauf dublizierst, würde ich dir raten, nur eine einfache temporäre int-Variable zu machen. In die kannst du dann immer object_[0] speichern._


----------



## Gast (13. Feb 2009)

bin schon gespannt


----------



## Gast (13. Feb 2009)

das mit dem temp war nur, weil die x-variable durch die berechnung verändert wird und im nachhinein die berechnung der y-variablen beeinflusst hätte...
klar, sieht seltsam aus, eine variable hätte für das 'x' gereicht, hab das allerdings ziemlich fix erstellt, wollte das feintunig später machen


----------



## Gast (13. Feb 2009)

hm, sieht nu so aus:

```
public void phys_rotation(){
   double dir = .017453293;

   for(int i=0; i!=object.length; i++){

    int temp = object[i][0];

    object[i][0] = (int)Math.round(object[i][0]*Math.cos(dir)-object[i][1]*Math.sin(dir));
    object[i][1] = (int)Math.round(temp*Math.sin(dir)+object[i][1]*Math.cos(dir));

   }
  }
```
funktioniert aber trotzdem nicht...


----------



## Illuvatar (13. Feb 2009)

Tja, ich bin erstaunt, aber es funktioniert tatsächlich nicht :autsch: 
Entweder das sind sehr arge Rundungsfehler, oder ich hab ein Brett vorm Kopf - ich hoffe letzteres.
Falls sich jemand anderes noch versuchen will - kompilierbarer Code:


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

public class TestRotation extends JFrame
{
  public static void main (String... args)
  {
    new TestRotation();
  }
  
  public TestRotation()
  {
    super("Test Rotation");
    
    final RotableObject obj = new RotableObject(
                        new double[]{100,100},
                        new double[]{200,100},
                        new double[]{200,200},
                        new double[]{100,200});
                        
    final JComponent drawing = new JComponent(){
      @Override
      public void paintComponent(Graphics g)
      {
        g.translate(getSize().width / 2, getSize().height / 2);
        g.fillPolygon (obj.getPolygon());
      }
    };
    JButton rotationButton = new JButton("Rotate");
    rotationButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed (ActionEvent e)
      {
        obj.phys_rotation();
        drawing.repaint();
      }
    });
    
    setLayout(new BorderLayout());
    add (drawing, BorderLayout.CENTER);
    add (rotationButton, BorderLayout.SOUTH);
    setSize (800, 600);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
  }
}

class RotableObject
{
  public double[][] object;
  
  public RotableObject(double[]... object)
  {
    this.object = object;
  }
  
  public Polygon getPolygon()
  {
    Polygon ret = new Polygon();
    for (double[] point : object) {
      ret.addPoint((int)point[0], (int)point[1]);
    }
    return ret;
  }
  
  public void phys_rotation(){
    double dir = .017453293;
    for(int i=0; i!=object.length; i++){
      double temp = object[i][0];
      object[i][0] = (double)Math.round(object[i][0]*Math.cos(dir)-object[i][1]*Math.sin(dir));
      object[i][1] = (double)Math.round(temp*Math.sin(dir)+object[i][1]*Math.cos(dir));
    }
  }
}
```


----------



## Developer_X (13. Feb 2009)

```
import java.awt.*;
import java.applet.*;

public class Wuerfel extends Applet {

    // 8 Eckpunkte 1-8
    // mit je 3 Koordinaten 1,2,3
    double p[][] = new double[9][4];

    int x=1, y=2, z=3;

    public void init() {
        setBackground(new Color(255,255,255));

        // 8 Eckpunkte im lokalen Würfel-Koordinatensystem
        // Nullpunkt = Mittelpunkt
        p[1][x] = -100; p[1][y] = -100; p[1][z] = -100;
        p[2][x] = +100; p[2][y] = -100; p[2][z] = -100;
        p[3][x] = +100; p[3][y] = -100; p[3][z] = +100;
        p[4][x] = -100; p[4][y] = -100; p[4][z] = +100;
        p[5][x] = -100; p[5][y] = +100; p[5][z] = -100;
        p[6][x] = +100; p[6][y] = +100; p[6][z] = -100;
        p[7][x] = +100; p[7][y] = +100; p[7][z] = +100;
        p[8][x] = -100; p[8][y] = +100; p[8][z] = +100;

        //       8 - - - - - 7
        //     / |         / |
        //    5 - - - - - 6  |
        //    |  |        |  |
        //    |  4 - - - -|- 3
        //    | /         | /
        //    1 - - - - - 2
    }

    // Rotationswinkel in rad
    double angle_x = 0.01;
    double angle_y = 0.0075;
    double angle_z = 0.005;

    Image buffer;
    Graphics2D gBuffer;

    public void paint(Graphics g) {

        // Double-Buffering
        if (buffer==null) {
            buffer=createImage(this.getSize().width, this.getSize().height);
            gBuffer=(Graphics2D)buffer.getGraphics();
        }
        gBuffer.clearRect(0,0,this.getSize().width, this.getSize().height);

        // Antialiasing
        gBuffer.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

        // Lokale Würfel-Koordinaten
        // in Welt-Koordinaten: +200
        gBuffer.drawLine((int)(p[1][x])+200,(int)(p[1][y])+200,
                         (int)(p[2][x])+200,(int)(p[2][y])+200);
        gBuffer.drawLine((int)(p[2][x])+200,(int)(p[2][y])+200,
                         (int)(p[3][x])+200,(int)(p[3][y])+200);
        gBuffer.drawLine((int)(p[3][x])+200,(int)(p[3][y])+200,
                         (int)(p[4][x])+200,(int)(p[4][y])+200);
        gBuffer.drawLine((int)(p[4][x])+200,(int)(p[4][y])+200,
                         (int)(p[1][x])+200,(int)(p[1][y])+200);
        gBuffer.drawLine((int)(p[5][x])+200,(int)(p[5][y])+200,
                         (int)(p[6][x])+200,(int)(p[6][y])+200);
        gBuffer.drawLine((int)(p[6][x])+200,(int)(p[6][y])+200,
                         (int)(p[7][x])+200,(int)(p[7][y])+200);
        gBuffer.drawLine((int)(p[7][x])+200,(int)(p[7][y])+200,
                         (int)(p[8][x])+200,(int)(p[8][y])+200);
        gBuffer.drawLine((int)(p[8][x])+200,(int)(p[8][y])+200,
                         (int)(p[5][x])+200,(int)(p[5][y])+200);
        gBuffer.drawLine((int)(p[1][x])+200,(int)(p[1][y])+200,
                         (int)(p[5][x])+200,(int)(p[5][y])+200);
        gBuffer.drawLine((int)(p[2][x])+200,(int)(p[2][y])+200,
                         (int)(p[6][x])+200,(int)(p[6][y])+200);
        gBuffer.drawLine((int)(p[3][x])+200,(int)(p[3][y])+200,
                         (int)(p[7][x])+200,(int)(p[7][y])+200);
        gBuffer.drawLine((int)(p[4][x])+200,(int)(p[4][y])+200,
                         (int)(p[8][x])+200,(int)(p[8][y])+200);

        g.drawImage (buffer, 0, 0, this);

        // Verzögerung
        try {Thread.sleep(10);}
        catch (InterruptedException e) {}

        double px, py, pz;

        for (int i=1;i<9;i++) {

            px = p[i][x];
            py = p[i][y];
            pz = p[i][z];

            // Rotation um x-Achse
            p[i][y] = py*Math.cos(angle_x)-pz*Math.sin(angle_x);
            p[i][z] = py*Math.sin(angle_x)+pz*Math.cos(angle_x);

            py = p[i][y];
            pz = p[i][z];

            // Rotation um y-Achse
            p[i][x] = px*Math.cos(angle_y)+pz*Math.sin(angle_y);
            p[i][z] =-px*Math.sin(angle_y)+pz*Math.cos(angle_y);

            px = p[i][x];

            // Rotation um z-Achse
            p[i][x] = px*Math.cos(angle_z)-py*Math.sin(angle_z);
            p[i][y] = py*Math.cos(angle_z)+px*Math.sin(angle_z);
        }

        repaint();
    }

    public void update(Graphics g) {paint(g);}
}
```


----------



## Fancy (13. Feb 2009)

Moin,

@Illuvatar und Gast:

warum macht ihr das (double)Math.round() darein? Ohne geht euer Beispiel problemlos...


```
object[i][0] = object[i][0]*Math.cos(dir)-object[i][1]*Math.sin(dir);
object[i][1] = temp*Math.sin(dir)+object[i][1]*Math.cos(dir);
```

Gruß,
Michael


----------



## Illuvatar (13. Feb 2009)

Gnarf. Ich dachte mir doch, dass es an der Rundung in Integer liegt, deshalb hab ich die ints in doubles geändert.

Die round-Methode jetzt noch rauszunehmen, wäre natürlich irgendwie clever gewesen *kopf->tisch*


----------



## Gast (13. Feb 2009)

autsch, round()-methode!
jetze gehts bei mir auch
vielen dank leute, ihr habt mir sehr geholfen


----------

