我正在使用Java的Graphics2D在一个组件上使用AffineTransform来操作我的绘图。 Graphics2D为此提供了一个方法转换,它采用了AffineTransform。
有时我需要手动操作一个点而不使用内置转换。 但是当我尝试使用相同的变换转换一个点时,我给了Graphics2D.transform有时结果点不一样。
以下代码重现了该问题(它是Scala代码,但我认为您可以想象Java代码。):
var transformationMatrix = new AffineTransform()
/*
* transformationMatrix is modified throughout the program
* ...
*/
override def paintComponent(g: Graphics2D) = {
super.paintComponent(g)
/* 1. transform using graphics transform */
g.transform(transformationMatrix)
g.setColor(Color.RED)
g.fill(new Rectangle(0, 0, 1, 1))
/* 2. transform point manually */
g.setTransform(new AffineTransform) // reset transformation to standard
val p0 = new Point(0, 0)
val pDest = new Point()
transformationMatrix.transform(p0, pDest)
g.setColor(Color.BLUE)
g.fill(new Rectangle(pDest.x, pDest.y, 1, 1)
}
预期行为
蓝色矩形(手动计算)透过红色矩形(通过变换计算)。
有经验的行为
我承认我的transformationMatrix并不是真正的整数,但那不应该是问题,是吗?
affineTransform = 1.1, 0.0, 520.55
0.0, 1.1, 182.54999999999995
0.0, 0.0, 1.0
这是一个错误还是我错过了一些深刻见解?
修改:如果您将transformationMatrix设置为
,则可以重现该错误transformationMatrix = new AffineTransform(1.1, 0.0, 0.0, 1.1, 521.55, 183.54999999999995)
在paintComponent的开头。请注意,g是Graphics2D类型。
答案 0 :(得分:6)
您的转换基本上只是(520.55, 182.55)
的翻译。并且因为它具有小数像素值,所以实际上对于舍入选择很敏感。如果你有抗锯齿功能,你实际上会得到一个4像素的红色斑点,覆盖重叠的像素。否则,考虑到舍入到整数和截断为整数之间的模糊性,您看到的行为(不一致)是合理的。
答案 1 :(得分:5)
嗯,你做了两件不同的事情。
在(1)中,您正在对产生分数坐标的变换进行形状(与Rectangle
而不是Rectangle2D.Double
无关)。它只是涂有别名,因为您没有设置特定的渲染提示(RenderingHints.KEY_ANTIALIASING
- > RenderingHints.VALUE_ANTIALIAS_ON
和RenderingHints.KEY_STROKE_CONTROL
- > RenderingHints.VALUE_STROKE_PURE
)。
在(2)中,您将点置于变换中,将其强制变为别名坐标(Point
而不是Point2D.Double
) 。然后从那一点开始连续构造一个矩形。
很明显,幕后可能会发生非常不同的事情,我完全不希望转换为整数点,而在混叠图形上下文中绘制浮点形状会产生相同的结果。
(没有测试)我猜想(1)的有效等效语句是
g.fill(transformationMatrix.createTransformedShape(new Rectangle(0, 0, 1, 1)))
答案 2 :(得分:2)
当您执行第一步g.transform(transformationMatrix)时,Graphics会使用已存在的转换组成该步骤。在第二步,你用g.setTransform(新的AffineTransform)重写它,从而失去了先前的转换(如果有的话)。你假设你回到了开始,但可能不是真的。
在步骤1之前创建一个getTransform(),在步骤2之后创建另一个,以验证它们是否相同。
答案 3 :(得分:1)
每当使用浮点坐标时,如果想要正确的结果,应使用“2D”版本的图形对象。我没有从“书”中读到这些内容,所以我无法引用,只是用它来体验。
这是我丑陋的java代码,它会产生您期望的结果。
AffineTransform transformationMatrix = AffineTransform.getTranslateInstance(520.55, 182.54999999999995);
transformationMatrix.scale(1.1, 1.1);
((Graphics2D) previewGraphics).transform(transformationMatrix);
previewGraphics.setColor(Color.RED);
((Graphics2D) previewGraphics).fill(new Rectangle(0,0,1,1));
((Graphics2D) previewGraphics).setTransform(new AffineTransform());
Point2D p0 = new Point2D.Double(0, 0);
Point2D pDest = new Point2D.Double();
transformationMatrix.transform(p0, pDest);
previewGraphics.setColor(Color.BLUE);
((Graphics2D) previewGraphics).fill((Shape) new Rectangle2D.Double(pDest.getX(), pDest.getY(), 1, 1));