Android: How to check if a path contains touched p

2019-01-10 13:28发布

问题:

i would try to develop an application in which i can draw a planimetry. So, each room has got its own ID or name and, if i touch a room, i want to show a Toast Message with that ID or name. The problem is how check if and which path is touched!!

I saw a lot of topic discussions that talked about this problem. Someone says to use getBounds method and, after, contains method for checking if touched point is in Rect. But, i guess getBounds method returns the smallest Rect that contains path, right?

So, rooms have different custom geometric forms and, for this reason, if i get bounds about 2 close rooms, method could return a shared set of points. Bad! Each room has got only their area points. How can i solve this problem ?

In iOS i could use PathContainsPoint method, but, unfortunally, Android Path doesn't have something similar.

I hope someone can help me Thx in advance

回答1:

Ok i solved my problem. I post the example code:

Path p;
Region r;

@Override
public void onDraw(Canvas canvas) {

    p = new Path();

    p.moveTo(50, 50);
    p.lineTo(100, 50);
    p.lineTo(100, 100);
    p.lineTo(80, 100);
    p.close();      

    canvas.drawPath(p, paint);

    RectF rectF = new RectF();
    p.computeBounds(rectF, true);
    r = new Region();
    r.setPath(p, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom));

}   

public boolean onTouch(View view, MotionEvent event) {

    Point point = new Point();
    point.x = event.getX();
    point.y = event.getY();
    points.add(point);
    invalidate();
    Log.d(TAG, "point: " + point);

    if(r.contains((int)point.x,(int) point.y))
        Log.d(TAG, "Touch IN");
    else
        Log.d(TAG, "Touch OUT");

    return true;
}


回答2:

Here's a thought: create a new path which is a tiny square around the point that was touched, and then intersect that path with your path to be tested using path.op() and see if the result is empty.



回答3:

As Edward Falk say, best way is to use path.op() becouse Region is square. And one point can be in 2 or 3 Regions. For example: enter image description here All regions will contain blue point, but on fact only path4 contains this point.

int x, y;
Path tempPath = new Path(); // Create temp Path
tempPath.moveTo(x,y); // Move cursor to point
RectF rectangle = new RectF(x-1, y-1, x+1, y+1); // create rectangle with size 2xp
tempPath.addRect(rectangle, Path.Direction.CW); // add rect to temp path
tempPath.op(pathToDetect, Path.Op.DIFFERENCE); // get difference with our PathToCheck
if (tempPath.isEmpty()) // if out path cover temp path we get empty path in result
{ 
    Log.d(TAG, "Path contains this point");
    return true;
}
else
{
    Log.d(TAG, "Path don't contains this point");
    return false;
}