Search code examples
androidandroid-canvasandroid-graphics

how to find the biggest possible Y point given X in Region in Android?


enter image description here

I have a virtual ruler being drawn on the screen. I want to be able to draw a straight line like the blue line above when touch event happen within the grown rectangle. but because touch can't be 100% straight, the movement might be like the red line. that's why I set a rectangle to listen to all the nearby touch events then draw a blue line.

I currently have

mRulerRect.set(mRulerCenter.x - mRulerBitmap.getWidth() / 2,
                mRulerCenter.y - mRulerBitmap.getHeight()),
                mRulerCenter.x + mRulerBitmap.getWidth() / 2,
                mRulerCenter.y);
mPath.addRect(mRulerRect, Path.Direction.CCW);
mRulerMatrix.setRotate(mRulerAngle, mRulerCenter.x, mRulerCenter.y);
mPath.transform(mRulerMatrix);
mRegions.setPath(mPath, new Region(mRulerRect));

then I check if the touch even happen within brown rectangle by mRegions.contains(x,y). works perfect so far for touch detection, but the problem I have now is how to draw a straight line. I tried to fix X point then calculate Y. it works fine when ruler is horizontal then starts to behave very weird when turning from horizontal to vertical. I'm out of idea how to accomplish this. Please help! thank you.


Solution

  • Things that you know:

    • The center of that brown rect is mRulerCenter.x, mRulerCenter.y
    • The line that you want to draw pass through that point
    • The angle of the line is mRulerAngle

    We're missing just one element, which is, the length of the line we want to draw. That's probably going to be a portion of the ruler's width and it should be very easy to compute mRulerRect.width() * someFactor

    Now, we want to know what are the start and the end of the line, we can compute that with trigonometry functions

    float halfLineLength = mRulerRect.width() * someFactor;
    float startAngle = (float) Math.toRadians(mRulerAngle);
    float endAngle = (float) Math.toRadians(mRulerAngle + 180);
    
    float startX = mRulerCenter.x + (float) Math.cos(startAngle) * halfLineLength;
    float startY = mRulerCenter.y + (float) Math.sin(startAngle) * halfLineLength;
    
    float endX = mRulerCenter.x + (float) Math.cos(endAngle) * halfLineLength;
    float endY = mRulerCenter.y + (float) Math.sin(endAngle) * halfLineLength;
    

    and then draw your line from (startX, startY) to (endX, endY), actually doesn't really matter which is start and which is end