For those who have a better understanding of matrices and 2-D graphics this may sound strange but today I struggeled about 2 hours rotating an image in a PaintListener.
Let me first of explain the exercise I had to solve, then show you my solution and then maybe someone can point out a better one.
Exercise
Draw an Image at Point(50,50) in a Canvas which is rotated a variable angle.
The solution
Solveing this problem one can use a SWT-Transform to adjust the Graphics-Context looks straight forward but it took me like said 2 hours to wrap my head around the problem. The following function is the solution I came up with.
public void paintControl(PaintEvent e) {
GC gc = e.gc;
gc.setAdvanced(true);
Bounds b = image.getBounds();
Transform transform = new Transform(display);
// The rotation point is the center of the image
transform.translate(50 + b.width/2, 50 + b.height/2);
// Rotate
transform.rotate(45);
// Back to the orginal coordinate system
transform.translate(-50 – b.width/2, -50 – b.height/2);
gc.setTransform(transform);
gc.drawImage(image, 50, 50);
transform.dispose();
}
[/sourecode]
Is the solution right? Is there a better solution?
My skills are very very bad when it comes to matrices and 2-D graphics so the above solution to the problem might be completely wrong and only works by chance.
instead of
transform.translate(-50 – b.width/2, -50 – b.height/2);
gc.setTransform(transform);
gc.drawImage(image, 50, 50);
u could do:
gc.drawImage(image, – b.width/2, – b.height/2);
Your solution looks fine, Tom. In college, I did a big project full of affine transforms, and that’s exactly how we would have done it.
The question really is why we dont have an api that does:
gc.rotate(‘center’,45);
So many things are programmed today. I dont know what they are for.
And the basics still lack intelligence.
That’s the way to do it. If you look at the maths there are other ways to do it but it is much more complicated for no real gain. Also this scales up to higher dimensional models (including 3d structures) which can also be handled using the same center – rotate – restore strategy
public static void drawImage(final GC gc, final Image image, final Point center,
final Point offset, final float angle) {
if (image == null || image.isDisposed()) {
return;
}
if (gc == null || gc.isDisposed()) {
return;
}
final Transform t = new Transform(gc.getDevice());
t.translate(center.x, center.y);
t.rotate(angle);
gc.setTransform(t);
gc.drawImage(image, -offset.x, -offset.y);
t.dispose();
gc.setTransform(null);
}