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

さて、あなたは2つの異なることをしています。

(1) では、形状を分数座標を生成する変換にかけています(それがそうであるかどうかは関係Rectangleありません)。特定のレンダリング ヒント ( -> 、および-> )Rectangle2D.Doubleを設定していないため、エイリアスのみがペイントされます。RenderingHints.KEY_ANTIALIASINGRenderingHints.VALUE_ANTIALIAS_ONRenderingHints.KEY_STROKE_CONTROLRenderingHints.VALUE_STROKE_PURE

(2)では、ポイントを変換にかけ、それをエイリアス座標(の代わりに)に強制します。次に、その点から連続して長方形を作成します。PointPoint2D.Double

明らかに内部で非常に異なることが起こっている可能性があり、整数ポイントへの変換とエイリアシング グラフィックス コンテキストでの浮動小数点形状のペイントが同じ結果をもたらすとはまったく期待できません。

(テストなし)(1)の有効な同等のステートメントは次のようになると思います

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

最初のステップである g.transform(transformationMatrix) を実行しているとき、Graphics はそれを既存の変換で構成します。2 番目のステップでは、g.setTransform(new AffineTransform) でオーバーライドしているため、前の変換があれば失われます。あなたは最初に戻ったと思い込んでいますが、そうではないかもしれません。

ステップ 1 の前に getTransform() を作成し、ステップ 2 の後に別の getTransform() を作成して、それらが同じであることを確認します。

于 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 に答える