Semimono
Semimono

Reputation: 724

How to find closest point on line?

I have a point (A) and a vector (V) (suppose it's infinite length), and I want to find the closest point (B) on the line to my original point (A). What's the simplest expression using Unity Vector2's or Vector3's to get this?

Upvotes: 15

Views: 21909

Answers (5)

asj
asj

Reputation: 346

For infinite lines

private Vector3 GetPointOnLine(Vector3 lineOrigin, Vector3 lineDirection, Vector3 point) 
    => lineOrigin - point - Vector3.Dot(lineOrigin - point, lineDirection) * lineDirection;

Put in the origin and direction of your line as well as the point you want to find the closest point to and voilá...

Upvotes: 0

SENTHILVELKUMAR M.
SENTHILVELKUMAR M.

Reputation: 1

public Vector2 FindNearestPointOnLine(Vector2 origin, Vector2 end, Vector2 point)
{
    //Get heading
          
    Vector2 heading = (end - origin);
    float magnitudeMax = heading.magnitude();
    heading = Vector2.Normalize(heading);
        
    //Do projection from the point but clamp it
    Vector2 lhs = point - origin;
    float dotP = Vector2.Dot(lhs, heading);
    dotP = UnityEngine.Mathf.Clamp(dotP, 0f, magnitudeMax);
    return origin + heading * dotP;
}

vector2.magnitude not found

Upvotes: -1

Mr. For Example
Mr. For Example

Reputation: 4313

// For finite lines:
Vector3 GetClosestPointOnFiniteLine(Vector3 point, Vector3 line_start, Vector3 line_end)
{
    Vector3 line_direction = line_end - line_start;
    float line_length = line_direction.magnitude;
    line_direction.Normalize();
    float project_length = Mathf.Clamp(Vector3.Dot(point - line_start, line_direction), 0f, line_length);
    return line_start + line_direction * project_length;
}

// For infinite lines:
Vector3 GetClosestPointOnInfiniteLine(Vector3 point, Vector3 line_start, Vector3 line_end)
{
    return line_start + Vector3.Project(point - line_start, line_end - line_start);
}

Upvotes: 11

Rex Chen
Rex Chen

Reputation: 41

For infinite lines:

Vector3 GetPoint(Vector3 p, Vector3 a, Vector3 b)
{
    return a + Vector3.Project(p - a, b - a);
}

This method will work with Vector3 inputs, and will also work if the arguments are Vector2 and are automatically converted to Vector2. The output will implicitly convert to a Vector2 if needed.

Upvotes: 3

Programmer
Programmer

Reputation: 125455

Infinite length:

If you have line with infinite length with start and direction, calculate the dot product of the line direction then multiply it by the direction and add the starting point to it.

public Vector2 FindNearestPointOnLine(Vector2 origin, Vector2 direction, Vector2 point)
{
    direction.Normalize();
    Vector2 lhs = point - origin;

    float dotP = Vector2.Dot(lhs, direction);
    return origin + direction * dotP;
}

Finite length:

If you have line with finite length with start to end positions, get the heading the perform a projection from the starting point to the. Also, use Mathf.Clamp to clap it just in case the line is off.

public Vector2 FindNearestPointOnLine(Vector2 origin, Vector2 end, Vector2 point)
{
    //Get heading
    Vector2 heading = (end - origin);
    float magnitudeMax = heading.magnitude;
    heading.Normalize();

    //Do projection from the point but clamp it
    Vector2 lhs = point - origin;
    float dotP = Vector2.Dot(lhs, heading);
    dotP = Mathf.Clamp(dotP, 0f, magnitudeMax);
    return origin + heading * dotP;
}

Upvotes: 34

Related Questions