7

我正在使用 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)
   }

预期行为

蓝色矩形(手动计算)覆盖了红色矩形(通过变换计算)。

有经验的行为

蓝色矩形的偏移量为 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。

4

4 回答 4

6

您的转换基本上只是(520.55, 182.55). 而且因为它具有小数像素值,它实际上对舍入的选择很敏感。如果您启用了抗锯齿,您实际上会得到一个 4 像素的红色斑点,覆盖重叠的像素。否则,鉴于舍入为整数和截断为整数之间的歧义,您看到的行为(分歧)是合理的。

于 2012-07-09T20:57:05.123 回答
5

好吧,你正在做两件不同的事情。

在 (1) 中,您正在对一个形状(它是Rectangle与否无关Rectangle2D.Double)进行产生分数坐标的变换。它只是绘制了别名,因为您没有设置特定的渲染提示(RenderingHints.KEY_ANTIALIASING->RenderingHints.VALUE_ANTIALIAS_ONRenderingHints.KEY_STROKE_CONTROL-> RenderingHints.VALUE_STROKE_PURE)。

在 (2) 中,您正在对一个点进行变换,并将其强制转换为别名坐标(Point而不是Point2D.Double)。然后从该点依次构造一个矩形。

显然,幕后可能会发生非常不同的事情,我根本不希望转换为整数点与在混叠图形上下文中绘制浮点形状会产生相同的结果。

(未经测试)我猜想(1)的有效等效语句是

g.fill(transformationMatrix.createTransformedShape(new Rectangle(0, 0, 1, 1)))
于 2012-07-18T00:00:30.313 回答
2

当您执行第一步 g.transform(transformationMatrix) 时,图形将其与已经存在的转换组合在一起。在第二步中,您将使用 g.setTransform(new AffineTransform) 覆盖它,从而丢失之前的转换(如果有)。你假设你回到了起点,但它可能不是真的。

在第 1 步之前创建一个 getTransform(),在第 2 步之后创建另一个以验证它们是否相同。

于 2012-07-16T16:18:22.737 回答
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));
于 2012-07-17T07:03:55.060 回答