Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Graphics2D transformation result does not match manual transformation

I am using Java's Graphics2D to draw on a component using AffineTransform's to manipulate my drawing. Graphics2D offers an method transform for this, which takes an AffineTransform.

Sometimes I need to manipulate a point manually without using the builtin-transformation. But when I try to transform a point using the same transformation I gave to Graphics2D.transform sometimes the resulting point is not the same.

The following code reproduces the problem (It's Scala code, but I think you can imagine the Java code.):

   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)
   }

Expected behaviour

The blue rectangle (manually calculated) overdraws the red one (calculated by transform).

Experienced behaviour

The blue rectangle has an offset of 1

I admit that my transformationMatrix is not really integer, but that should'nt be the problem, should it?

   affineTransform = 1.1, 0.0, 520.55
                     0.0, 1.1, 182.54999999999995
                     0.0, 0.0,    1.0

Is this a bug or am I missing some deep insight?

Edit: You can reproduce the bug, if you set transformationMatrix to

transformationMatrix = new AffineTransform(1.1, 0.0, 0.0, 1.1, 521.55, 183.54999999999995)

at the beginning of paintComponent. Please note, that g is of type Graphics2D.

like image 454
knub Avatar asked Jul 09 '12 20:07

knub


Video Answer


1 Answers

Your transform is basically just a translation by (520.55, 182.55). And because it has fractional pixel values it is in fact sensitive to choice of roundoff. If you have anti-aliasing on, you'll actually get a 4-pixel red blob covering the pixels that are overlapped. Otherwise, the behavior (disagreement) you're seeing is reasonable given the ambiguity between rounding to integer and truncating to integer.

like image 157
Rex Kerr Avatar answered Oct 05 '22 22:10

Rex Kerr