views:

20

answers:

2

Hi all,

I'm trying to scale/translate a java.awt.Shape with AffineTransform in order to draw it in a defined bounding Rectangle.

Moreover, I want to paint it in a drawing Area having a 'zoom' parameter.

I tried various concatenations of AffineTransform but I couldn't find the correct sequence. For example, the following solution was wrong:

double zoom=(...);/* current zoom */
Rectangle2D viewRect=(...)/** the rectangle where we want to paint the shape */
Shape shape=(...)/* the original shape that should fit in the rectangle viewRect */
Rectangle2D bounds=shape.getBounds2D();

double ratioW=(viewRect.getWidth()/bounds.getWidth());
double ratioH=(viewRect.getHeight()/bounds.getHeight());


AffineTransform transforms[]=
    {
    AffineTransform.getScaleInstance(zoom, zoom),
    AffineTransform.getTranslateInstance(-bounds.getX(),-bounds.getY()),
    AffineTransform.getTranslateInstance(viewRect.getX(),viewRect.getY()),
    AffineTransform.getScaleInstance(ratioW, ratioH)
    };


AffineTransform tr=new AffineTransform();
for(int i=0;i< transforms.length;++i)
    {
    tr.concatenate(transforms[i]);
    }

Shape shape2=tr.createTransformedShape(shape);
graphics2D.draw(shape2);

Any idea about the correct AffineTransform ?

Many thanks

Pierre

+1  A: 

Note that AffineTransform transformations are concatenated "in the most commonly useful way", which may be regarded as last in, first-out order. The effect can be seen in this example. Given the sequence below, the resulting Shape is first rotated, then scaled and finally translated.

at.translate(SIZE/2, SIZE/2);
at.scale(60, 60);
at.rotate(Math.PI/4);
return at.createTransformedShape(...);
trashgod
I'll validate your answer as your expression "Last-In , First Out" inspired the solution
Pierre
It's a useful notion for reasoning about the result; but, of course, there is no _queue_, only a single transform that subsumes the series of operations.
trashgod
+1  A: 

Inspired by trashgod's answer, the correct sequence was:

AffineTransform transforms[]=
{
AffineTransform.getScaleInstance(zoom, zoom),
AffineTransform.getTranslateInstance(viewRect.getX(),viewRect.getY()),
AffineTransform.getScaleInstance(ratioW, ratioH),
AffineTransform.getTranslateInstance(-bounds.getX(),-bounds.getY())
};



AffineTransform tr=new AffineTransform();
for(int i=0;i< transforms.length;++i)
 {
 tr.concatenate(transforms[i]);
 }
Pierre
+1 It might be worth adding the original code for a _before_ and _after_ comparison.
trashgod