如何在一条线(线渲染器)的两点(Vector2)之间找到一个点(vector2)

how to find a point(vector2) between two points(Vector2) of a line (line renderer)

正如问题所解释的,如何在一条线(线渲染器)的两点(Vector2)之间找到一个点(vector2),

我正在使用线条渲染器绘制带有两个点的线条(从矢量和端点开始),我想要的是线条中的点 A,如图中所示。

从理论上讲,我想为我的用例缩短线的原始长度,我正在对重叠的两条线进行线相交检查,但问题是在某些情况下线从同一点开始,并且在那些情况下,如果点相遇,它仍然算作线相交。所以理论上我想缩短线相交检查的线,这样如果点相遇它就不会与另一条线相交。

这是我的线相交检查脚本!

  public bool isIntersecting = false;
  LineRenderer lineRenderer;
 
     private void Start()
     {
         lineRenderer = this.GetComponent<LineRenderer>();
     }
 
     private void Update()
     {
         LineRenderer recievedLine;
         if (FindObjectOfType<LineDynamics>().ropeRenderer != null)
         {
             recievedLine = FindObjectOfType<LineDynamics>().ropeRenderer;
         }
         else
         {
             return;
         }
 
         AreLineSegmentsIntersectingDotProduct(lineRenderer.GetPosition(0), lineRenderer.GetPosition(lineRenderer.positionCount - 1), recievedLine.GetPosition(0), recievedLine.GetPosition(recievedLine.positionCount - 1));
     }
 
     //Line segment-line segment intersection in 2d space by using the dot product
     //p1 and p2 belongs to line 1, and p3 and p4 belongs to line 2 
     public bool AreLineSegmentsIntersectingDotProduct(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4)
     {
 
         if (IsPointsOnDifferentSides(p1, p2, p3, p4) && IsPointsOnDifferentSides(p3, p4, p1, p2))
         {
             isIntersecting = true;
         }
         else
         {
             isIntersecting = false;
         }
 
         return isIntersecting;
     }
 
     //Are the points on different sides of a line?
     private bool IsPointsOnDifferentSides(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4)
     {
         bool isOnDifferentSides = false;
 
         //The direction of the line
         Vector2 lineDir = p2 - p1;
 
         //The normal to a line is just flipping x and z and making z negative
         Vector2 lineNormal = new Vector2(-lineDir.y, lineDir.x);
 
         //Now we need to take the dot product between the normal and the points on the other line
         float dot1 = Vector2.Dot(lineNormal, p3 - p1);
         float dot2 = Vector2.Dot(lineNormal, p4 - p1);
 
         //If you multiply them and get a negative value then p3 and p4 are on different sides of the line
         if (dot1 * dot2 < 0f)
         {
             isOnDifferentSides = true;
         }
 
         return isOnDifferentSides;
     }

如有任何建议和帮助,我们将不胜感激。

针对你的问题

你可以,例如使用 Vector2.Lerp 以获得起点和终点之间的任何点,给定 01 之间的因数,其中

  • 0:等于起点
  • 1:等于终点
  • {0;1}:等于开始和结束之间的线性插值

对于中心,例如是

var center = Vector2.Lerp(startPosition, endPosition, 0.5f);

如果您更愿意从起点开始一定的行进距离,您可以使用 Vector2.MoveTowards like

var otherPoint = Vector2.MoveTowards(startPoint, endPoint, desiredDistanceFromStartPoint);

基本上你也可以完全手动,基本上做同样的事情

var direction = (endPoint - startPoint).normalized;
var otherPoint = startPoint + direction * desiredDistanceFromStartPoint;

但是,这并不能防止您超过终点。


解决你的实际问题

你知道 Unity 社区早就在 Wiki - Math functions 下实现了功能,它已经提供了例如

//Calculate the intersection point of two lines. Returns true if lines intersect, otherwise false.
//Note that in 3d, two lines do not intersect most of the time. So if the two lines are not in the 
//same plane, use ClosestPointsOnTwoLines() instead.
public static bool LineLineIntersection(out Vector3 intersection, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2){

    Vector3 lineVec3 = linePoint2 - linePoint1;
    Vector3 crossVec1and2 = Vector3.Cross(lineVec1, lineVec2);
    Vector3 crossVec3and2 = Vector3.Cross(lineVec3, lineVec2);

    float planarFactor = Vector3.Dot(lineVec3, crossVec1and2);

    //is coplanar, and not parrallel
    if(Mathf.Abs(planarFactor) < 0.0001f && crossVec1and2.sqrMagnitude > 0.0001f)
    {
        float s = Vector3.Dot(crossVec3and2, crossVec1and2) / crossVec1and2.sqrMagnitude;
        intersection = linePoint1 + (lineVec1 * s);
        return true;
    }
    else
    {
        intersection = Vector3.zero;
        return false;
    }
}

//Two non-parallel lines which may or may not touch each other have a point on each line which are closest
//to each other. This function finds those two points. If the lines are not parallel, the function 
//outputs true, otherwise false.
public static bool ClosestPointsOnTwoLines(out Vector3 closestPointLine1, out Vector3 closestPointLine2, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2){

    closestPointLine1 = Vector3.zero;
    closestPointLine2 = Vector3.zero;

    float a = Vector3.Dot(lineVec1, lineVec1);
    float b = Vector3.Dot(lineVec1, lineVec2);
    float e = Vector3.Dot(lineVec2, lineVec2);

    float d = a*e - b*b;

    //lines are not parallel
    if(d != 0.0f){

        Vector3 r = linePoint1 - linePoint2;
        float c = Vector3.Dot(lineVec1, r);
        float f = Vector3.Dot(lineVec2, r);

        float s = (b*f - c*e) / d;
        float t = (a*f - c*b) / d;

        closestPointLine1 = linePoint1 + lineVec1 * s;
        closestPointLine2 = linePoint2 + lineVec2 * t;

        return true;
    }

    else{
        return false;
    }
}   

如前所述,如果您担心的实际上是两条线的起点相等(非常不可能),那么与您正在进行的其余计算相比,进行 50 Vector3 == 检查非常便宜。