1
\$\begingroup\$

You can see two points in this picture. Points are surrounded by collider which is set to trigger. Points can either be Vector3 or Vector2, shouldn't make any difference.

I need to get the coords on gray line if mouse enters the trigger, at the exact point where mouse and gray line form 90 degree angle. Gray line is just an straight line between 2 points.

All the data:

  • left point coords
  • right point coords
  • mouse coords

Is it possible with the data I have and how?


enter image description here

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

It is possible with the data you have. Let's call the line segment vw and the point p:

vec2 projection_point(vec2 v, vec2 w, vec2 p) {
  const float l2 = length_squared(v, w);  // i.e. |w-v|^2 -  avoid a sqrt
  // Consider the line extending the segment, parameterized as v + t (w - v).
  // We find projection of point p onto the line. 
  // It falls where t = [(p-v) . (w-v)] / |w-v|^2
  // We clamp t from [0,1] to handle points outside the segment vw.
  const float t = max(0, min(1, dot(p - v, w - v) / l2));
  return v + t * (w - v);  // Projection point that falls on the segment
}

This function returns the nearest point on the line segment.

The above code is derived from here: https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment

\$\endgroup\$
3
  • \$\begingroup\$ Thanks, BTW, it returns a position, not the distance. \$\endgroup\$ Commented Sep 10, 2018 at 9:45
  • \$\begingroup\$ Ah, never code when you're tired I guess. I'll accept it. \$\endgroup\$
    – Sir
    Commented Sep 10, 2018 at 9:55
  • \$\begingroup\$ Worth mentioning, the operation on assigning t a value is a simple clamping; most libraries provide a ready-made implementation of it. \$\endgroup\$
    – liggiorgio
    Commented Sep 10, 2018 at 13:38
0
\$\begingroup\$

Here's an answer in C#.

public Vector3 NearestPointOnSegment(Vector3 start, Vector3 end, Vector3 point) {
    Vector3 dir = (end - start);
    dir.Normalize();

    Vector3 v = point - start;
    float dist = Vector3.Dot(v, dir);
    return start + dir * dist;
}

This can be unsafe if there's a chance point could be off the segment. If that's the case and you need to return the closest point on segment anyway, use clamp to either return start or end:

public Vector3 NearestPointOnSegment(Vector3 start, Vector3 end, Vector3 point) {
    Vector3 dir = (end - start);
    dir.Normalize();

    Vector3 v = point - start;
    float dist = Vector3.Dot(v, dir);

    // magnitude takes square root which could be expensive
    // use previous method if your usecase allows
    float length = dir.magnitude;
    dist = Mathf.Clamp(dist, 0f, length);

    pointOnLine = start + dir * dist;
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .