How to find absolute position of click while zoomed in

无人久伴 提交于 2019-11-27 11:14:42

So, after redrawing the problem I've found the solution I was looking for. It's gone through a few iteration's but here's how I worked it out:

B - Point, Center of the scale operation

A1, A2, A3 - Points, equal in user-space but different in canvas-space.

You know the values for Bx and By because they are always constant no matter what the scale factor (You know this value in both canvas-space and in user-space).

You know Ax & Ay in user-space so you can find the distance between Ax to Bx and Ay to By. This measurement is in user-space, to convert it to a canvas-space measurement simply divide it by the scale factor. (Once converted to canvas-space, you can see these lines in red, orange and yellow).

As point B is constant, the distance between it and the edges are constant (These are represented by Blue Lines). This value is equal in user-space and canvas-space.

You know the width of the Canvas in canvas-space so by subtracting these two canvas space measurements (Ax to Bx and Bx to Edge) from the total width you are left with the coordinates for point A in canvas-space:

public float[] getAbsolutePosition(float Ax, float Ay) {

    float fromAxToBxInCanvasSpace = (mCenterScaleX - Ax) / mScaleFactor;
    float fromBxToCanvasEdge = mCanvasWidth - Bx;
    float x = mCanvasWidth - fromAxToBxInCanvasSpace - fromBxToCanvasEdge;

    float fromAyToByInCanvasSpace = (mCenterScaleY - Ay) / mScaleFactor;
    float fromByToCanvasEdge = mCanvasHeight - By;
    float y = mCanvasHeight - fromAyToByInCanvasSpace - fromByToCanvasEdge;

    return new float[] { x, y };
}

The above code and image describe when you're clicking to the top left of the original centre. I used the same logic to find A no matter which quadrant it was located in and refactored to the following:

public float[] getAbsolutePosition(float Ax, float Ay) {

    float x = getAbsolutePosition(mBx, Ax);
    float y = getAbsolutePosition(mBy, Ay); 

    return new float[] { x, y };
}

private float getAbsolutePosition(float oldCenter, float newCenter, float mScaleFactor) {
    if(newCenter > oldCenter) {
        return oldCenter + ((newCenter - oldCenter) / mScaleFactor);
    } else {
        return oldCenter - ((oldCenter - newCenter) / mScaleFactor);
    }
}

Here is my solution based on Graeme's answer:

public float[] getAbsolutePosition(float Ax, float Ay) {
    MatrixContext.drawMatrix.getValues(mMatrixValues);

    float x = mWidth - ((mMatrixValues[Matrix.MTRANS_X] - Ax) / mMatrixValues[Matrix.MSCALE_X])
            - (mWidth - getTranslationX());

    float y = mHeight - ((mMatrixValues[Matrix.MTRANS_Y] - Ay) / mMatrixValues[Matrix.MSCALE_X])
            - (mHeight - getTranslationY());

    return new float[] { x, y };
}

the parameters Ax and Ay are the points which user touch via onTouch(), I owned my static matrix instance in MatrixContext class to hold the previous scaled/translated values.

Really sorry this is a brief answer, in a rush. But I've been looking at this recently too - I found http://code.google.com/p/android-multitouch-controller/ to do what you want (I think - I had to skim read your post). Hope this helps. I'll have a proper look tonight if this doesn't help and see if I can help further.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!