🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Getting correct coordinates after pinch zoom (drawing line) Android Canvas

Started by
0 comments, last by AmbitiousCoder98 4 years, 4 months ago

I am trying to draw the line following by the users finger(touch). It is quite easy task to implement if there is no scaling.
Drawing without scaling works perfectly here is an screenshot

SMciL.png

Works well. As you can see.

But if I scale an canvas it begins to draw points with some margin/measurement error/tolerance. It seems that I have not taken some value in advance while calculating scaled touch points, I have tried a lot of different formulas, but nothing helped.

Here is the result of zooming the canvas.
Cd05G.png

It seems that the problem in some delta value that I have to take into consideration

Because if I use this version of scale function it works well but scales only to the left top corner.


    canvas.scale(mScaleFactor, mScaleFactor); 



With this scaling


    canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);


Multitouch zoom (pinch) works well but coordinates are not correct.

Please help to solve the problem, it seems that I have to take these `scalePointX, scalePointY` variables when calculating scaled x and y.

Here is my code. Any help will be highly appreciated.



    private void initWorkSpace(Context context) {
            mPaint = new Paint();
            mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
            mRect = new Rect();
            mPath = new Path();
            mPaint.setAntiAlias(true);
            mPaint.setColor(Color.BLACK);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeJoin(Paint.Join.ROUND);
            mPaint.setStrokeWidth(10f);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.getClipBounds(mRect);
            canvas.save();
            canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);
            canvas.translate(mRect.top,mRect.left);
            canvas.drawPath(mPath, mPaint);
            canvas.restore();
    
        }
        // when ACTION_DOWN start touch according to the x,y values
        private void startTouch(float x, float y) {
            mPath.moveTo(x, y);
            mX = x;
            mY = y;
        }
    
        // when ACTION_MOVE move touch according to the x,y values
        private void moveTouch(float x, float y) {
            float dx = Math.abs(x - mX);
            float dy = Math.abs(y - mY);
            if (dx >= TOLERANCE || dy >= TOLERANCE) {
                mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
                mX = x;
                mY = y;
            }
        }
    
        public void clearCanvas() {
            mPath.reset();
            invalidate();
        }
    
        // when ACTION_UP stop touch
        private void upTouch() {
            mPath.lineTo(mX, mY);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            // Let the ScaleGestureDetector inspect all events.
            mScaleDetector.onTouchEvent(ev);
    
            final int action = ev.getAction();
            Log.e("TOUCH","REAL X :" + ev.getX() + " REAL Y : " + ev.getY());
            Log.e("TOUCH","RECT TOP :" + mRect.top + " RECT LEFT : " + mRect.left + " RECT RIGHT : " + mRect.right + " RECT BOTTOM :" + mRect.bottom);
            final float scaledX = ev.getX()/mScaleFactor+mRect.left*mScaleFactor;
            final float scaledY = ev.getY()/mScaleFactor+mRect.top*mScaleFactor;
            switch (action & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN: {
    
                    /*final float x = (ev.getX() - scalePointX) / mScaleFactor;
                    final float y = (ev.getY() - scalePointY) / mScaleFactor;
                    cX = x - mPosX + scalePointX; // canvas X
                    cY = y - mPosY + scalePointY; // canvas Y*/
    
                    // Remember where we started
                    mLastTouchX = scaledX;
                    mLastTouchY = scaledY;
                    Log.e("DOWN","Scale FACTOR : " + mScaleFactor);
                    Log.e("DOWN","X : " +mLastTouchX + " Y :" + mLastTouchY + " scalePointX : " + scalePointX + " scalePointY : " + scalePointY );
    
                    Log.e("DOWN","Last X : " + mLastTouchY + " Last Y :" + mLastTouchY);
                    startTouch(mLastTouchX, mLastTouchY);
                    invalidate();
                    break;
                }
                case MotionEvent.ACTION_MOVE: {
                   /* final float x = (ev.getX() - scalePointX) / mScaleFactor;
                    final float y = (ev.getY() - scalePointY) / mScaleFactor;
                    cX = x - mPosX + scalePointX; // canvas X
                    cY = y - mPosY + scalePointY; // canvas Y
    
                    // Only move if the ScaleGestureDetector isn't processing a gesture.
                    if (!mScaleDetector.isInProgress()) {
                        final float dx = x - mLastTouchX; // change in X
                        final float dy = y - mLastTouchY; // change in Y
    
                        mPosX += dx;
                        mPosY += dy;
    
                        invalidate();
                    }*/
                    Log.e("ACTION_MOVE","Scale FACTOR : " + mScaleFactor);
                    Log.e("ACTION_MOVE","X : " + scaledX + " Y :" + scaledY + " cX : " + cX + " cY : " + cY );
                    Log.e("ACTION_MOVE","Last X : " + mLastTouchX + " Last Y :" + mLastTouchY);
                    mLastTouchX = scaledX;
                    mLastTouchY = scaledY;
                    moveTouch(scaledX, scaledY);
                    invalidate();
                    break;
    
                }
                case MotionEvent.ACTION_UP: {
                    mLastTouchX = 0;
                    mLastTouchY = 0;
                    upTouch();
                    invalidate();
                }
            }
            return true;
        }
    
        private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                mScaleFactor *= detector.getScaleFactor();
                scalePointX = detector.getFocusX();
                scalePointY = detector.getFocusY();
                // Don't let the object get too small or too large.
                mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));
                mScaleFactor = (mScaleFactor < 1 ? 1 : mScaleFactor);
                invalidate();
                return true;
            }
        }
Advertisement

This topic is closed to new replies.

Advertisement