# Rotating a Polygon (Manually)

• 09-22-2013, 10:54 PM
driiper
Rotating a Polygon (Manually)
Hello!

I have a homework task where i'm supposed to rotate a Polygon (which i create myself with free drawing in my application).
I have gotten the Polygon to rotate, but something is messing up after a while.

I'm not completly sure why its happening, but i think it has to be somthing with the double --> integer casting, slowly changing some of the points in negative and positive direction.
After a while the displacement of the points stop and it rotates like it should (with that wierd new shape).

Attachment 5595 Transforms into (after x rotations at 90 deg) Attachment 5596, but it doesnt change from here.

Code for rotating the Polygon ( a point in the polygon, i have for loop which calls this method for all points) is:
Code:

```public Point rotatePoint(Point pt, Point center, double angleDeg) {         // http://en.wikipedia.org/wiki/Rotation_matrix                 double angleRad = Math.toRadians(angleDeg);         double cosThetha = Math.cos(angleRad); //The angle COS         double sinThetha = Math.sin(angleRad); //The angle SIN         double dx = (pt.x - center.x); //Difference (Point in transformed to origo)         double dy = (pt.y - center.y); //Difference -- || --         int ptX = center.x + (int) (dx * cosThetha - dy * sinThetha);         int ptY = center.y + (int) (dx * sinThetha + dy * cosThetha);         return new Point(ptX, ptY);     }```
Have a nice day/evening!
Driiper
• 09-22-2013, 11:17 PM
jim829
Re: Rotating a Polygon (Manually)
Your rotation method looks ok. Can you include the rest of your code?

Regards,
Jim
• 09-22-2013, 11:32 PM
driiper
Re: Rotating a Polygon (Manually)
Hello!

Sure can
Code:

```    public void rotation() {         Point panelSize = new Point(this.getWidth()/2, this.getHeight()/2);         for (int i = 0; i < this.xPoly.length; i++) {             Point p = this.rotatePoint(new Point(xPoly[i], yPoly[i]) , panelSize, 90);             xPoly[i] = p.x;             yPoly[i] = p.y;         }         System.out.println("\r\n");         this.repaint();     }```
the xPoly and yPoly array is just locations i clicked on the screen.
Code:

``` @Override     public void mousePressed(MouseEvent e) {         /* Record points */         if (e.getButton() == MouseEvent.BUTTON1) {             this.pointList.add(new Point(e.getX(), e.getY()));         }         /* Construct the polygon */         if (e.getButton() == MouseEvent.BUTTON3) {             xPoly = new int[this.pointList.size()];             yPoly = new int[this.pointList.size()];             for (int i = 0; i < this.pointList.size(); i++) {                 xPoly[i] = this.pointList.get(i).x;                 yPoly[i] = this.pointList.get(i).y;             }             this.pointList.clear();         }         this.repaint();     }```

Thanks!

Driiper
• 09-22-2013, 11:37 PM
jim829
Re: Rotating a Polygon (Manually)
This can't be all your code! You need to provide the minimum required to allow compilation an execution.

Regards,
Jim
• 09-22-2013, 11:39 PM
driiper
Re: Rotating a Polygon (Manually)
You are correct :) Sorry

Code:

```import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.ConcurrentModificationException; import javax.swing.JFrame; import javax.swing.JPanel; public class GUISkeleton {     public static void main(String[] args) {         new Frame();     } } class Frame extends JFrame {     public Frame() {         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         this.setBounds(0, 0, 500, 500);         this.setLocationRelativeTo(null);         this.add(new Panel());         this.setVisible(true);     } } class Panel extends JPanel implements MouseListener, KeyListener {         String legend = "|Translation: Arrow keys | Rotation: ,(-) and .(+) | Scale: k (-) and l (+) |";     ArrayList<Point> pointList = new ArrayList<Point>();     /* For drawing the polygon, will be null by default. this makes sure it wont be drawed until its set. */     int[] xPoly = null;     int[] yPoly = null;     public Panel() {         this.setFocusable(true);         this.addMouseListener(this);         this.addKeyListener(this);     }     public void paintComponent(Graphics g) {         super.paintComponent(g);         /* Draw Cosmetics */         g.drawString(this.legend, 60, 20);         g.setColor(new Color(255, 250, 205));         g.fillRect(0, 0, this.getWidth(), this.getHeight());         g.setColor(Color.GRAY);         /* X lines */         g.drawLine(0, (this.getHeight() / 2) + this.getHeight() / 4, this.getWidth(), (this.getHeight() / 2) + this.getHeight() / 4);         g.drawLine(0, this.getHeight() / 2, this.getWidth(), this.getHeight() / 2);         g.drawLine(0, this.getHeight() / 4, this.getWidth(), this.getHeight() / 4);         /* Y lines */         g.drawLine(this.getWidth() / 2, 0, this.getWidth() / 2, this.getHeight());         g.drawLine(this.getWidth() / 4, 0, this.getWidth() / 4, this.getHeight());         g.drawLine((this.getWidth() / 2) + (this.getWidth() / 4), 0, (this.getWidth() / 2) + (this.getWidth() / 4), this.getHeight());         /* Draw "ORIGO" Point */         g.fillOval((this.getWidth()/2)-5, (this.getHeight()/2)-5, 10, 10);                 g.setColor(Color.BLACK);         /* Draw points which is clicked on the screen, also draws a line between them to mimic a polygon */         Point lastPt = null;         for (Point pt : this.pointList) {             g.fillOval(pt.x - 5, pt.y - 5, 10, 10);             /* Draws a line between current and the last Point */             if (lastPt != null) {                 g.drawLine(lastPt.x, lastPt.y, pt.x, pt.y);             }             lastPt = pt;             /* Draw Line between First and last, (like we do in a polygon) */             g.drawLine(this.pointList.get(0).x, this.pointList.get(0).y, this.pointList.get(this.pointList.size() - 1).x, this.pointList.get(this.pointList.size() - 1).y);         }         /* Whenever the polygon arrays are not null, we can draw it */         if (xPoly != null && yPoly != null) {             g.drawPolygon(xPoly, yPoly, xPoly.length);         }         // g.dispose();     }     @Override     public void mouseClicked(MouseEvent e) {         //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.     }     @Override     public void mousePressed(MouseEvent e) {         /* Record points */         if (e.getButton() == MouseEvent.BUTTON1) {             this.pointList.add(new Point(e.getX(), e.getY()));         }         /* Construct the polygon */         if (e.getButton() == MouseEvent.BUTTON3) {             xPoly = new int[this.pointList.size()];             yPoly = new int[this.pointList.size()];             for (int i = 0; i < this.pointList.size(); i++) {                 xPoly[i] = this.pointList.get(i).x;                 yPoly[i] = this.pointList.get(i).y;             }             this.pointList.clear();         }         this.repaint();     }     @Override     public void mouseReleased(MouseEvent e) {         //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.     }     @Override     public void mouseEntered(MouseEvent e) {         //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.     }     @Override     public void mouseExited(MouseEvent e) {         //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.     }     @Override     public void keyTyped(KeyEvent e) {         //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.     }     @Override     public void keyPressed(KeyEvent e) {         if (xPoly != null && yPoly != null) {             /* Translation */             if (e.getKeyCode() == KeyEvent.VK_UP) {                 this.translation(-1, true);             }             if (e.getKeyCode() == KeyEvent.VK_DOWN) {                 this.translation(1, true);             }             if (e.getKeyCode() == KeyEvent.VK_LEFT) {                 this.translation(-1, false);             }             if (e.getKeyCode() == KeyEvent.VK_RIGHT) {                 this.translation(1, false);             }             if (e.getKeyCode() == KeyEvent.VK_0) {                 this.rotation(true);             }         }     }     @Override     public void keyReleased(KeyEvent e) {         //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.     }     public void translation(int sign, boolean top) {         if (xPoly.length != yPoly.length) {             throw new ConcurrentModificationException("Xpoly and Ypoly should be the same lenght!");         }         for (int i = 0; i < this.xPoly.length; i++) {             if (top) {                 this.yPoly[i] = this.yPoly[i] + (1 * sign);             } else {                 this.xPoly[i] = this.xPoly[i] + (1 * sign);             }         }         this.repaint();     }     public void rotation(boolean positive) {         Point panelSize = new Point(this.getWidth()/2, this.getHeight()/2);         for (int i = 0; i < this.xPoly.length; i++) {             Point p = this.rotatePoint(new Point(xPoly[i], yPoly[i]) , panelSize, 90);             xPoly[i] = p.x;             yPoly[i] = p.y;         }         System.out.println("\r\n");         this.repaint();     }     public Point rotatePoint(Point pt, Point center, double angleDeg) {         // http://en.wikipedia.org/wiki/Rotation_matrix                 double angleRad = Math.toRadians(angleDeg);         double cosThetha = Math.cos(angleRad); //The angle COS         double sinThetha = Math.sin(angleRad); //The angle SIN         double dx = (pt.x - center.x); //Difference (Point in transformed to origo)         double dy = (pt.y - center.y); //Difference -- || --         int ptX = center.x + (int) (dx * cosThetha - dy * sinThetha);         int ptY = center.y + (int) (dx * sinThetha + dy * cosThetha);         return new Point(ptX, ptY);     } }```
Should be able to run it now. (Rotate with the 0 key).

Thanks
Driiper
• 09-23-2013, 12:05 AM
jim829
Re: Rotating a Polygon (Manually)
Okay, I figured out your problem. If you change the rotation increment from 90 to 10 and hold down 0 after drawing the polygon you can see the image slowly shrinking toward the center. This is due to induced error from your calculations. You are storing the values as ints which is okay for plotting. But then you use those same ints again to recalculate then next set of points. Each time you do that you loose precision. I suggest you maintain a separate list of points just for plotting and keep the original polygon around for computing purposes. And instead of rotating 10 or 20 or 90 each time. Rotate an additive amount. That is rotating a set of points by 10 over and over for a 10 degree rotation is the same as rotating the original points first by 10, then by 20, then by 30 and so on. That way you wont loose precision.

Regards,
Jim
• 09-23-2013, 12:13 AM
driiper
Re: Rotating a Polygon (Manually)
Hey,

First, thanks ALOT for your help. Amazing!

If i understand correctly i could just have a integer called, lets say angle. And lets say i then press my 0 key 10 times it the rotation angle would be 90 * 10?, And then never change the plot Array from the one i draw on the screen, making it computation wise only a single rotation on my points?

(Dont know if that made sense :P hopefully it did)

Again, thanks alot! Ill try it out!

EDIT:
Got it to work with the way you described!
Thanks alot and have a nice Day/Evening !

Driiper
• 09-23-2013, 12:29 AM
jim829
Re: Rotating a Polygon (Manually)
You are correct! Rotating a set of integral coordinates each time for a fixed angle introduces error. But if you rotate the same set over and over again, changing the angle instead, you pretty much eliminate the error.

And you're very welcome!
Regards
Jim