Home > OS >  Detect point on wide line
Detect point on wide line

Time:06-13

I would like to be able to detect click on a wide line. I've got a function taken from there which manages to detect if a point is exactly on it, but I'd like to add some tolerance to detect click on all the rendered line.

Here is my current function, (taken from there Determine if a point is between 2 other points on a line) :

    public bool PointIsOnLine(Vector2 currPoint, UILineRenderer line)
{
    Vector2 point1 = line.points[0];
    Vector2 point2 = line.points[1];

    float dxc = currPoint.x - point1.x;
    float dyc = currPoint.y - point1.y;

    float dxl = point2.x - point1.x;
    float dyl = point2.y - point1.y;

    float cross = dxc * dyl - dyc * dxl;

    if (cross != 0)
        return false;


    if (Mathf.Abs(dxl) >= Mathf.Abs(dyl))
        return dxl > 0 ?
          point1.x <= currPoint.x && currPoint.x <= point2.x :
          point2.x <= currPoint.x && currPoint.x <= point1.x;
    else
        return dyl > 0 ?
          point1.y <= currPoint.y && currPoint.y <= point2.y :
          point2.y <= currPoint.y && currPoint.y <= point1.y;
}

You can access the line's thickness using line.thickness

CodePudding user response:

To check if a point is near a line segment you would first find the projection of the point on the line:

var dirNorm = (point2 - point1).Normalized;
var t = Vector2.Dot(currPoint - point1, dirNorm );

Next step is to clamp the t value. If you have a line segment the limits should be [0, Length]. You can then convert it back to a point by

var closestPoint = point1   dirNorm  * tClamped;

And you can then get the distance by

var dist = Vector2.Distance(currPoint, closestPoint);

Add a check to see if the distance is smaller than some value and you get your answer.

Note that you would want to keep things as vectors as much as possible. Don't go down to individual x/y values unless you absolutely have to. Unity3D have a fairly good selection of vector functions, use them! Also note that this could probably be optimized a bit, but it may be useful to divide this in individual functions, i.e. one function get the t-value, one to get the closest point, another to get the distance etc. These functions can probably be reused for other things.

CodePudding user response:

It looks like I have found a solution. Here is my function now:

public bool PointIsOnLine(Vector2 currPoint, UILineRenderer line)
    {
        Vector2 point1 = line.points[0];
        Vector2 point2 = line.points[1];

        float dxc = currPoint.x - point1.x;
        float dyc = currPoint.y - point1.y;

        float dxl = point2.x - point1.x;
        float dyl = point2.y - point1.y;

        float cross = dxc * dyl - dyc * dxl;

        if (currPoint.y >= point1.y - line.thickness / 2 && currPoint.y <= point2.y   line.thickness / 2)
        {
            if (cross >= -(line.thickness / 2) * 100 && cross <= (line.thickness / 2) * 100)
            {
                return true;
            }
        }

    return false;
}

I don't really understand why I need to multiply by 100 though... but still works well

  • Related