Jump to content
  • Advertisement
AndroidNewbie

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

This topic is 1120 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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;
            }
        }
Edited by AndroidNewbie

Share this post


Link to post
Share on other sites
Advertisement

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!