Rotate SVG Image

Hi,



I am trying to rotate SVGImage, I do not need a resizehandle since i am rotating through the code by calling rotateUp() and rotateDown() methods. Below is what i came up with but could not get it to work.



Also is there a repaint method which i can call? Or i should go about by declaring a new event with LastChangedHint+1.





public class SVGImageRot extends SVGImage {

boolean rotate = false;

boolean clockwise = true;

int currentRotateAngle = 0;

public static final int ROTATE_ANGLE_OFFSET = 5;



public void paint(Graphics2D g, JGoView view) {

super.paint(g, view);

if (getImage() != null && rotate) {

System.out.println(“rotate is true”);

Rectangle rect = getBoundingRect();

AffineTransform xform = new AffineTransform();

xform.rotate(Math.toRadians(currentRotateAngle), rect.width/2, rect.height/2);



g.drawImage(getImage(), xform, this);

rotate = false;

}

}



/**

* This method changes the rotation angle depending

* upon the selected rotation direction and repaints

* the ImagePanel

*/

public void rotate()

{



if(clockwise)

{

//if clockwise then increment the rotation angle

//by the offset till the angle is 360

//then again set to 0

currentRotateAngle += ROTATE_ANGLE_OFFSET;

//mod takes care of setting the angle to 0 if it is 360

currentRotateAngle %= 360;

}

else

{

//if anti-clockwise then decrement the rotation angle

//by the offset till the angle is equal to 0

//then again set to 360

currentRotateAngle -= ROTATE_ANGLE_OFFSET;

if(currentRotateAngle <= 0)

{

currentRotateAngle = 360;

}

}

//repaint the image panel

rotate=true;

update();

}



public void rotateUp(){

setClockwise(true);

rotate();

}



public void rotateDown(){

setClockwise(false);

rotate();

}



public void setClockwise(boolean clockwise) {

this.clockwise = clockwise;

}



public boolean isClockwise() {

return clockwise;

}

}



thanks

Arun

Try replacing your paint method with something like the following:

public void paint(Graphics2D g, JGoView view) {
super.paint(g, view);
if (getImage() != null) {
Rectangle rect = getBoundingRect();
AffineTransform xform = new AffineTransform();
xform.translate(rect.x, rect.y);
xform.rotate(Math.toRadians(currentRotateAngle), rect.width/2, rect.height/2);
g.drawImage(getImage(), xform, this);
}
}
I've removed the rotate boolean because I think we always want to apply this transformation when painting. I've also added a translation to the transformation so that it paints the image where the bounding rectangle is.
Note that this simple code does not take into consideration zooming (scale), nor does it consider the fact rotations of the image are likely to cause painting to take place out of the bounding rectangle (which will cause pieces of the image to leave "tracks" when moving the object). As my math books used to say, this is left as an "exercise for the reader". However, assuming your scale factor is 1 and your SVGImageRot has a square bounding rectangle, this code should allow you to rotate the image in multiples of 90 degrees.

Thank you, I got it working if the image is a perfect square for any angle. I think that the super.paint(g, view) paints the image normally and i get another image overlapped with the angled rotation, which i can comment out the g.drawImage in the super class.



I am trying to get this to work even if the image is not a perfect square. I am rotating the image based on the center and calculating the varying bounding box co-ordinates and the dimension and setting it. I am facing two problems.



1. when i drag the image, the mouse pointer and the image position co-ordination is not correct.



2. when i rotate, the image size keeps increasing and i get an out of memory exception.



Can anyone look at my code and point me in the right direction. I am sure the formula i used to calculate is right, but during the rotation i may be missing out something that is causing this.



private void setTransform() {



//get image height and width

Image image = getImage();

int iw = image.getHeight(null);

int ih = image.getHeight(null);



//get the x, y of the image

Point p = getLocation();

int ix = p.x;

int iy = p.y;



//based on ix,iy and iw&ih calculate the center x, y

int cx = ix + iw/2;

int cy = ix + ih/2;



//declare the new bounding rectangle w&h

int bw,bh;



double radians = Math.toRadians(currentRotateAngle);





//first, calculate the width and height of the bounding rectangle.

if(currentRotateAngle == 0.0 || currentRotateAngle == 180.0) {

bw=iw;

bh=ih;

}

// if 90 or 270 (quarter or 3-quarter rotations) the width becomes

// the height, and vice versa

else if(currentRotateAngle == 90.0 || currentRotateAngle == 270.0) {

bw=ih;

bh=iw;

}

// for any other rotation, we need to do some trigonometry

else {

bw = (int)Math.ceil(Math.abs(Math.cos(radians) * iw) + Math.abs(Math.cos(radians) * ih));

bh = (int)Math.ceil(Math.abs(Math.sin(radians) * iw) + Math.abs(Math.sin(radians) * ih));

}



//second, compute the XY(bx, by) of the new bounding rect

int bx = cx - bw/2;

int by = cy - bh/2;





setBoundingRect(bx, by, bw, bh);





xform.translate(cx, cy);

xform.rotate(Math.toRadians(currentRotateAngle), iw/2.0, ih/2.0);



System.out.println("Image wxh = "+iw+“x”+ih);

System.out.println(“Image Center x , y = “+cx+”,”+cy);

System.out.println("Bounding wxh = "+bw+“x”+bh);

System.out.println(“Bounding Rect x, y = “+bx+”,”+by);

System.out.println("current angle = "+currentRotateAngle);

}



public void paint(Graphics2D g, JGoView view) {

super.paint(g, view);

if (getImage() != null) {

setTransform();

g.drawImage(getImage(), xform, this);

}

}

I think you might find instructive the implementations of RotImage.java and RotText.java in the Demo1 example.