2

i have following problem. I have a bitmap and on this bitmap certain draw operations can be done. Like drawing a line, arrwow, etc.

This works pretty well, but the bitmap can be zoomed, dragged and rotated. For this a drawMatrix is used. Everything this works pretty good but, for drawing i need the original coordinates so that the drawings come in the right size, etc.

I can get this original coordinates with the following function. But it doesn't work with rotations. Does anybody have an idea, how to solve this?

    /**
     * When we have moved or zoomed we need the original image coordinates calculated from
     * the screen coordinates. This function gives that back
     */
    private Point translateScreenCoordsToOriginalImageCoords(MotionEvent e) {
        float[] m = new float[9];
        drawMatrix.getValues(m);

        float transX = m[Matrix.MTRANS_X] * -1;
        float transY = m[Matrix.MTRANS_Y] * -1;
        float scaleX = m[Matrix.MSCALE_X];
        float scaleY = m[Matrix.MSCALE_Y];

        // TODO function does not work when rotated by 90 degree
        if (scaleX == 0.0) {
            scaleX = -1.0f;
            scaleY = -1.0f;
        }

        int lastTouchX = (int) ((e.getX() + transX) / scaleX);
        int lastTouchY = (int) ((e.getY() + transY) / scaleY);
        lastTouchX = Math.abs(lastTouchX);
        lastTouchY = Math.abs(lastTouchY);

        return new Point(lastTouchX, lastTouchY);
    }

This is how scaling is performed

/**
 * Scale the canvas by
 *
 * @param scaleFactor e.g 2 is double
 * @param focusX      the center x point
 * @param focusY      the center y point
 *
 * @return true if scaling is performed
 */
private boolean doScale(float scaleFactor, int focusX, int focusY) {
    if (this.scaleBoundaries(scaleFactor))
        return false;

    Matrix transformationMatrix = new Matrix();

    // Zoom focus is where the fingers are centered
    transformationMatrix.postTranslate(-focusX, -focusY);
    transformationMatrix.postScale(scaleFactor, scaleFactor);

    transformationMatrix.postTranslate(focusX, focusY);
    drawMatrix.postConcat(transformationMatrix);

    invalidate();

    return true;
}

e.g. This is the draw function of a Line

@Override
public void draw(Canvas c, Matrix drawMatrix, boolean translateCoordiantes) {
    float pts[] = new float[] {this.start.x, this.start.y, this.end.x, this.end.y};

    if (translateCoordiantes)
        drawMatrix.mapPoints(pts);

    c.drawLine(pts[0], pts[1], pts[2], pts[3], this.paint);
}
  • 1
    just use `mapPoints`, call this method on original `Matrix` and/or on `invert()`ed one – pskink Oct 13 '15 at 14:43
  • see [here](http://stackoverflow.com/a/21657145/2252830) the implementation of `Layer#contains` method – pskink Oct 13 '15 at 14:58
  • BTW you don't need a `Bitmap` to draw with scale/rotation/translation, you can draw directly on the `Canvas` – pskink Oct 14 '15 at 08:39
  • You mean to use mapPoints to calculate the original Coordinates? How exactly would that be done? Moving rotating, etc of the image works, just the drawings on the canvas (you're right not on the bitmap) get wrong when rotated, because I think this translateScreenCoordsToOriginalImageCoords function is only correct, if the matrix doesn't describe a rotation. – Manuel Kaspar Oct 15 '15 at 08:24
  • have you seen `Layer#contains` method? – pskink Oct 15 '15 at 08:29

1 Answers1

0

Wow pskink thanks a lot! That was the answer! To get the orignal coordinates back, use:

private Point translateCoordinatesBack(MotionEvent event) {
        Matrix inverse = new Matrix();

        drawMatrix.invert(inverse);

        float[] pts = {event.getX(), event.getY()};
        inverse.mapPoints(pts);

        return new Point((int) pts[0], (int) pts[1]);
}