2016-07-08 41 views
3

私は画面座標からイメージ座標への変換を管理するクラスを持っています。
しかし、私は「1つのエラーでオフ」です。スケーリングとズーム後の画面座標とイメージ座標の変換

次のではなく、319、199の、198、318を与える:

@Test 
public void test6rightScreenCornerToImageCoOrdAfterZoomingAndScaling() { 
    PointTranslation pointTranslation = new PointTranslation(); 
    pointTranslation.setOriginalSize(0, 0, 320, 200); // original image 
    pointTranslation.zoomIn(9, 9, 310, 190); // zoomed image starting at 9,9 
    pointTranslation.scale(0, 0, 800, 800); 

    Point translatedPoint = pointTranslation.transformPoint(799,799); 
    System.out.println(testName.getMethodName() + " : " + translatedPoint.toString()); 
    assertTrue(translatedPoint.x == 319); 
    assertTrue(translatedPoint.y == 199); 
} 

========================== ===================================

全リスト:

package gtx; 
import org.eclipse.swt.graphics.Point; 
import org.eclipse.swt.internal.gdip.PointF; 
import org.eclipse.swt.internal.gdip.RectF; 

@SuppressWarnings("restriction") 
public class PointTranslation { 
RectF originalSize = null; 
RectF currentSize = null; 
RectF scaledSize = null; 

public void setOriginalSize(int originX, int originY, int width, int height) { 
    originalSize = getRectangle(originX, originY, width, height); 
    currentSize = originalSize; 
} 

public void zoomIn(int originX, int originY, int width, int height) { 
    // System.out.println("addTranslation: " + originX + " " + originY + " " 
    // + width + " " + height); 
    currentSize = getRectangle(originX, originY, width, height); 
} 

public void scale(int originX, int originY, int width, int height) { 
    // System.out.println("addTranslation: " + originX + " " + originY + " " 
    // + width + " " + height); 
    scaledSize = getRectangle(originX, originY, width, height); 
} 

public boolean isPointWithinBounds(Point point) { 
    return isPointWithinBounds(point.x, point.y); 
} 

public boolean isPointWithinBounds(int xPos, int yPos) { 
    boolean ret = false; 

    if (scaledSize != null) { 
     RectF sourceRec = scaledSize; 
     int xBounds = (int) (sourceRec.Width + sourceRec.X); 
     int yBounds = (int) (sourceRec.Height + sourceRec.Y); 
     ret = (xPos < xBounds) && (yPos < yBounds) && (xPos > sourceRec.X) && (yPos > sourceRec.Y); 
    } 

    return ret; 
} 

public Point transformPoint(Point point) { 
    return transformPoint(point.x, point.y); 
} 

public Point transformPoint(int xPos, int yPos) { 
    Point sourcePoint = new Point((int) xPos, (int) yPos); 
    Point retPoint = sourcePoint; 

    if (this.scaledSize != null) { 
     retPoint = transformPoint(this.scaledSize, this.currentSize, sourcePoint); 
    } 
    return retPoint; 
} 

/* 
* Rectangle 1 has (x1, y1) origin and (w1, h1) for width and height, and 
* Rectangle 2 has (x2, y2) origin and (w2, h2) for width and height, then 
* 
* Given point (x, y) in terms of Rectangle 1 co-ords, to convert it to 
* Rectangle 2 co-ords: xNew = ((x-x1)/w1)*w2 + x2; yNew = ((y-y1)/h1)*h2 + 
* y2; 
*/ 
private Point transformPoint(RectF source, RectF destination, Point intPoint) { 
    PointF point = new PointF(); 
    point.X = intPoint.x; 
    point.Y = intPoint.y; 
    return transformPoint(source, destination, point); 
} 

private Point transformPoint(RectF source, RectF destination, PointF point) { 
    return new Point((int) ((((point.X - source.X)/source.Width) * destination.Width + destination.X)), 
      (int) ((((point.Y - source.Y)/source.Height) * destination.Height + destination.Y))); 
} 

private RectF getRectangle(int x, int y, int width, int height) { 
    RectF rect = new RectF(); 
    rect.X = x; 
    rect.Y = y; 
    rect.Height = height; 
    rect.Width = width; 
    return rect; 
} 

private PointF getPoint(int x, int y) { 
    PointF retPoint = new PointF(); 
    retPoint.X = x; 
    retPoint.Y = y; 
    return retPoint; 
} 

public void reset() { 
    this.originalSize = null; 
    this.currentSize = null; 
    this.scaledSize = null; 
} 
} 

更新:

私の問題は間違いなく丸められているようです。その奇妙な、いくつかのテストケースのために、私はRound Pointを使って正しいPointを取得する必要があり、時にはUpを丸める必要があります。私は倍率などの何かを見逃しています。 2つの四角形の間の翻訳へのどのような提案?

アップデート2:

私は、次の方法を試してみましたが、まだ喜びで:

private Point transformPoint(RectF source, RectF destination, PointF point) { 
     float xPercent = normalize(point.X,source.X,source.Width); 
     float destX = xPercent*(Math.abs(destination.Width - destination.X)) + destination.X; 

     float yPercent = normalize(point.Y,source.Y,source.Height); 
     float destY = yPercent*(Math.abs(destination.Height - destination.Y)) + destination.Y; 

     System.out.println("Float x,y: " + destX + ", " + destY); 
     System.out.println("Ceil Float x,y: " + Math.floor(destX) + ", " + Math.floor(destY)); 

     return new Point((int)Math.floor(destX), (int)Math.floor(destY)); 
    } 

    private float normalize(float value, float min, float max) { 
     return Math.abs((value - min)/(max - min)); 
    } 
+0

あなたはどのようなポイントを使用しているtest6' 'は? –

+0

@LorisSecuro - 今更新しました - ありがとう –

+0

あなたの質問のコードは完全ではありません。 [mcve]を入力してください。 – Roman

答えて

0

それはあなたがポイントを整数に各翻訳後に中間結果を変換することは可能ですか?

は、intとしてorg.eclipse.swt.graphics.Point店舗xyを覚えておいてくださいので、あなたの計算で端数はを落としています。

次のとおりです。)まず翻訳

1:

x1 = ((799 - 0)/800) * 301 + 9 = 309.62375 
y1 = ((799 - 0)/800) * 181 + 9 = 189.77375 

あなたは次の翻訳に入る前にPointオブジェクトでそれらを格納していた場合、彼らは(309、189に切り捨てられます)とあなたは

2)第2の翻訳になるだろう

x2 = ((309 - 9)/301) * 320 + 0 = 318.93... 
y2 = ((189 - 9)/181) * 200 + 0 = 198.89... 

これは(318、198)に切り捨てられます。

+0

私は間違いなく丸め問題だと思います。私はどこでどのように修正するか正確にはわかりません。私は今質問を簡素化しましたが –

+0

2番目の翻訳(元のサイズに戻って)がコード内でどのように起こっていますか?あなたが投稿したバグは表示されないので、問題がどこにあるのか推測しています。つまり、あなたの(799,799)ポイントをあなたの(9,9,310,190)座標系に変換し、その結果を 'PointF'の代わりに' Point'として保存し、あなたの(0,0,320,200)座標に変換していますシステム。それは誤りでしょう。 –

+0

私は今質問を更新しました。基本的に0,0,800,800から9,9,310,190 –

2

テストケースを実行し、コードのステップでは、私のデバッグは、以下の置換を示し...

transformPoint(RectF source, RectF destination, PointF point) { 
    return new Point (
     (int) ((((799 - 0)/800) * 310) + 9)), 
     (int) ((((799 - 0)/800) * 190) + 9)) 
    ); 
} 

式の前半は318.6125を返します。方程式の後半は198.7625を返します。

あなたはint変換が 所望の値に切り捨てるようにいずれか

  1. int
  2. 生とに
  3. ラウンドアップコンバージョンの前に(例えば、端部で+ 1として)の式を変更する必要が結果

Mathewが指摘したように、行d平均を平均化するのと同じように問題を拡大する。

1

Reenactorで述べたように、あなたはintに変換する前にポイントを丸めるする必要があります。

private Point transformPoint(RectF source, RectF destination, PointF point) { 
    final int ptx = Math.round((((point.X - source.X)/source.Width) * destination.Width + destination.X)); 
    final int pty = Math.round((((point.Y - source.Y)/source.Height) * destination.Height + destination.Y)); 
    return new Point(ptx, pty);  
} 
+0

私はそれが少し複雑だと思っています。時には必要な出力が私にラウンドダウンを必要とすることもありますが、ときどきラウンドアップする必要があります。 –

関連する問題