如何找到一条直线上距离最近的点?

14

我有一个点(A)和一个向量(V)(假设它无限长),我想找到离我的原始点(A)最近的线上的点(B)。使用Unity Vector2或Vector3,最简单的表达式是什么?

5个回答

33

无限长度:

如果你有一条有无限长度的线段,有一个起点方向,那么计算该线段方向的点积,然后乘以该方向并加上起点。

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;
}

有限长度:

如果你有一条有限长度的线段,其起始和结束位置为startend,获取方向并从起点进行投影。同时,使用Mathf.Clamp来确保线段不会超出范围。

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;
}

11
// 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);
}

3

对于无限行:

最初的回答:

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

该方法适用于输入为Vector3的情况,并且如果参数为Vector2,则会自动转换为Vector2。如果需要,输出将隐式转换为Vector2。"最初的回答"

我喜欢这个解决方案的简洁性,但我不介意再多一点解释。这是针对无限还是有限线?查找文档时,Vector2没有Project方法,可能需要提到这仅适用于Vector3(除非您费心制作z = 0的Vector3值)。对性能有何评论?与其他答案相比,这个解决方案的性能更好还是更差?除了明显的简洁性之外,这个答案与其他答案相比有什么优缺点? - Semimono
1
@Semimono,我在这个答案中添加了一些细节。无法评论性能。 - Ruzihm

0
对于无限直线
private Vector3 GetPointOnLine(Vector3 lineOrigin, Vector3 lineDirection, Vector3 point) 
    => lineOrigin - point - Vector3.Dot(lineOrigin - point, lineDirection) * lineDirection;

输入你的线的起点和方向,以及你想找到最接近的点,然后就大功告成了...

-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未找到


目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接