使用仿射变换将形状缩放/平移至给定矩形

3
我正在尝试使用AffineTransform来缩放/平移java.awt.Shape,以便将其绘制在一个定义好的边界矩形内。此外,我希望能够在具有“缩放”参数的绘图区域中进行绘制。
我尝试过多种AffineTransform的组合,但是我无法找到正确的顺序。例如,下面的解决方案是错误的:
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);

请问正确的AffineTransform是什么?

非常感谢!

Pierre

2个回答

8
请注意,AffineTransform 变换以“最常用的方式”连接,这可以被视为后进先出的顺序。该效果可以在此 示例 中看到。给定以下序列,生成的 Shape 首先旋转,然后缩放,最后平移。
at.translate(SIZE/2, SIZE/2);
at.scale(60, 60);
at.rotate(Math.PI/4);
return at.createTransformedShape(...);

1
我会验证您的答案,因为您的表达“后进先出”启发了解决方案。 - Pierre
这是一个有用的概念,用于推理结果;但是,当然,并没有“队列”,只有一个包含一系列操作的单个转换。 - trashgod

1
受trashgod答案的启发,正确的顺序是:
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]);
 }

+1 可能值得添加原始代码以进行_before_和_after_比较。 - trashgod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接