0

正如问题所解释的,如何在一条线(线渲染器)的两个点(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;
     }

任何建议和帮助将不胜感激。

4

1 回答 1

1

对你的问题

例如,您可以使用在给定之间和位置Vector2.Lerp之间的因素的情况下获得起点和终点之间的任何点01

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

对于中心,例如

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

如果您宁愿需要从起点开始一定的旅行距离,您可以Vector2.MoveTowards使用

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

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

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

但是,这并不能保护您免于超出端点。


吨你的实际问题

您知道 Unity 社区很久以前就已经在Wiki 下实现了一些函数 -已经提供了例如的数学函数

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

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

于 2021-02-28T13:26:41.560 回答