1. 程式人生 > >Unity 數學知識——數學公式彙總

Unity 數學知識——數學公式彙總

在做智慧家居設計軟體的時候用到的常規數學公式,彙總在這裡給大家作參考。

 

 

插入排序

 /// <summary>
    /// 插入排序_列表
    /// </summary>
    public List<float> Sort_List(List<float> list)
    {
        for (int i = 1; i < list.Count; ++i)
        {
            float t = list[i];
            int j = i;
            while ((j > 0) && (list[j - 1] > t))
            {
                list[j] = list[j - 1];
                --j;
            }
            list[j] = t;
        }
        return list;
    }

 

 /// <summary>
    /// 插入排序_陣列
    /// </summary>
    public float[] Sort_Array(float[] array)
    {
        for (int i = 1; i < array.Length; ++i)
        {
            float t = array[i];
            int j = i;
            while ((j > 0) && (array[j - 1] > t))
            {
                array[j] = array[j - 1];
                --j;
            }
            array[j] = t;
        }
        return array;
    }

 

取三位小數

 public float GetRound(float value)
    {
        return float.Parse(value.ToString("f3")); 
    }

 

聯立兩個一般式方程組求解

 /// <summary>
    /// 聯立兩個一般式方程組求解
    /// </summary>
    /// <param name="A">左側平行線</param>
    /// <param name="B">右側平行線</param>
    /// <returns></returns>

public Vector2 GetResultFromCommonEquation(Vector3 A, Vector3 B)
    {
        float r1 = 0;
        float r2 = 0;

        //0 = X * A.x + Y * A.y + A.z;
        //0 = X * B.x + Y * B.y + B.z;

        //Y = -(X * A.x + A.z) / A.y;
        //Y = -(X * B.x + B.z) / B.y;

        // X * A.x/ A.y + A.z / A.y = X * B.x/ B.y + B.z / B.y
        // X * A.x/ A.y - X * B.x/ B.y = B.z / B.y - A.z / A.y
        // X= (B.z / B.y - A.z / A.y)/( A.x/ A.y -B.x/ B.y)
        // Y = -(X * A.x + A.z) / A.y;

        //幾種相交牆體互相垂直或在一條直線上的情況

        if (A.x == 0 && B.y == 0)
        {
            r1 = -B.z / B.x;
            r2 = -A.z / A.y;
            Vector2 v = new Vector2(r1, r2);
            // Debug.Log("rp=" + rp.name + "   rp.position=" + rp.transform.position + "   A=" + A + "   B=" + B + "   v=" + v);
            return v;
        }
        //A平行於Y軸,B平行於X軸
        else if (A.y == 0 && B.x == 0)
        {
            r1 = -A.z / A.x;
            r2 = -B.z / B.y;
            Vector2 v = new Vector2(r1, r2);
            //  Debug.Log("rp=" + rp.name + "   rp.position=" + rp.transform.position + "   A=" + A + "   B=" + B + "   v=" + v);
            return v;
        }
        else if (A.x == 0)
        {
            r1 = (A.z * B.y) / (A.y * B.x) - B.z / B.x;
            r2 = -A.z / A.y;
            Vector2 v = new Vector2(r1, r2);
            //  Debug.Log("rp=" + rp.name + "   rp.position=" + rp.transform.position + "   A=" + A + "   B=" + B + "   v=" + v);
            return v;
        }
        else if (A.y == 0)
        {
            r1 = -A.z / A.x;
            r2 = (A.z * B.x) / (A.x * B.y) - B.z / B.y;
            Vector2 v = new Vector2(r1, r2);
            // Debug.Log("rp=" + rp.name + "   rp.position=" + rp.transform.position + "   A=" + A + "   B=" + B + "   v=" + v);
            return v;
        }
        else if (B.x == 0)
        {
            r1 = (B.z * A.y) / (B.y * A.x) - A.z / A.x;
            r2 = -B.z / B.y;
            Vector2 v = new Vector2(r1, r2);
            // Debug.Log("rp=" + rp.name + "   rp.position=" + rp.transform.position + "   A=" + A + "   B=" + B + "   v=" + v);
            return v;
        }
        else if (B.y == 0)
        {
            r1 = -B.z / B.x;
            r2 = (B.z * A.x) / (B.x * A.y) - A.z / A.y;
            Vector2 v = new Vector2(r1, r2);
            //  Debug.Log("rp=" + rp.name + "   rp.position=" + rp.transform.position + "   A=" + A + "   B=" + B + "   v=" + v);
            return v;
        }
        else
        {
            r1 = (B.z / B.y - A.z / A.y) / (A.x / A.y - B.x / B.y);
            r2 = -((B.z / B.y - A.z / A.y) / (A.x / A.y - B.x / B.y) * A.x + A.z) / A.y;
            Vector2 v = new Vector2(r1, r2);
            return v;
        }


    }

 

計算兩點形成的向量和X軸正方向之間的夾角和點積

 

 public float DotVector(GameObject ThePoint, Vector3 start, Vector3 end)
    {
        float dotvec = 0;
        float c = 0;

        Vector2 start_v2 = new Vector2(start.x, start.z);
        Vector2 end_v2 = new Vector2(end.x, end.z);
        //Debug.Log("wallname=" + wallname);
        //Debug.Log("start=" + start);
        //Debug.Log("end=" + end);
        //Debug.Log(" this.transform.position=" + this.transform.position);
        if (Vector2.Distance(start_v2, ThePoint.transform.position) < Vector2.Distance(end_v2, ThePoint.transform.position))
        {
            c = Vector2.Dot((end_v2.normalized - start_v2.normalized), new Vector2(1, 0));
            dotvec = Mathf.Acos(c) * Mathf.Rad2Deg;
            //  Debug.Log("點積為:" + c);
            //  Debug.Log(this.name + "的夾角弧度為:" + Mathf.Acos(c));
            //Debug.Log(wallname + "與" + this.name + "的夾角角度為:" + dotvec);
        }
        else if (Vector2.Distance(start_v2, ThePoint.transform.position) > Vector2.Distance(end_v2, ThePoint.transform.position))
        {
            c = Vector2.Dot((start_v2.normalized - end_v2.normalized), new Vector2(1, 0));
            dotvec = Mathf.Acos(c) * Mathf.Rad2Deg;
            //  Debug.Log("點積為:" + c);
            //  Debug.Log(this.name + "的夾角弧度為:" + Mathf.Acos(c));
            //Debug.Log(wallname + "與" + this.name + "的夾角角度為:" + dotvec);
        }
        return dotvec;
    }

計算兩向量與X軸正方向角度

 public float angle_360(GameObject ThePoint, Vector3 start, Vector3 end)
    {
        Vector3 from_ = new Vector3(1, 0, 0);
        Vector3 to_ = new Vector3();
        if (Vector3.Distance(start, ThePoint.transform.position) < Vector3.Distance(end, ThePoint.transform.position))
        {
            to_ = end - start;
        }
        else if (Vector3.Distance(start, ThePoint.transform.position) > Vector3.Distance(end, ThePoint.transform.position))
        {
            to_ = start - end;
        }
        Vector3 v3 = Vector3.Cross(from_.normalized, to_.normalized);
        if (v3.y <= 0)
        {

           //  Debug.Log(ThePoint.name + "與直線的夾角角度為:" + Vector3.Angle(from_.normalized, to_.normalized));
            return Vector3.Angle(from_.normalized, to_.normalized);
        }
        else
        {
          
             if (Vector3.Angle(from_.normalized, to_.normalized) == 0)
             {
             //    Debug.Log(ThePoint.name + "與直線的夾角角度為:" + Vector3.Angle(from_.normalized, to_.normalized));
                 return 0;
             }
             else
             {
             //    Debug.Log(ThePoint.name + "與直線的夾角角度為:" + (360 - Vector3.Angle(from_.normalized, to_.normalized)));
                 return 360 - Vector3.Angle(from_.normalized, to_.normalized);
             }
           
        }
    }

 

獲取兩點形成向量距X/Y軸方向夾角

  public float angle_360_X(Vector3 start, Vector3 end)
    {
        Vector3 from_ = new Vector3(1, 0, 0);
        Vector3 to_ = end - start;
        Vector3 v3 = Vector3.Cross(from_.normalized, to_.normalized);
        if (v3.y <= 0)
        {
            //  Debug.Log(ThePoint.name + "與直線的夾角角度為:" + Vector3.Angle(from_.normalized, to_.normalized));
            return Vector3.Angle(from_.normalized, to_.normalized);
        }
        else
        {
            if (Vector3.Angle(from_.normalized, to_.normalized) == 0)
            {
                //    Debug.Log(ThePoint.name + "與直線的夾角角度為:" + Vector3.Angle(from_.normalized, to_.normalized));
                return 0;
            }
            else
            {
                //    Debug.Log(ThePoint.name + "與直線的夾角角度為:" + (360 - Vector3.Angle(from_.normalized, to_.normalized)));
                return 360 - Vector3.Angle(from_.normalized, to_.normalized);
            }
        }
    }

求平面上一點到兩個點形成的直線的距離

 public float pointToLine(Vector3 point1, Vector3 point2, Vector3 position)
    {

        float space = 0;
        float a, b, c;
        a = Vector2.Distance(new Vector2(point1.x, point1.z), new Vector2(point2.x, point2.z));// 線段的長度      
        b = Vector2.Distance(new Vector2(point1.x, point1.z), new Vector2(position.x, position.z));// position到點point1的距離      
        c = Vector2.Distance(new Vector2(point2.x, point2.z), new Vector2(position.x, position.z));// position到point2點的距離 
        if (c <= 0.01f || b <= 0.01f)
        {
            space = 0;
            return space;
        }
        if (a <= 0.01f)
        {
            space = b;
            return space;
        }
        if (c * c >= a * a + b * b)
        {
            space = b;
            return space;
        }
        if (b * b >= a * a + c * c)
        {
            space = c;
            return space;
        }
        float p = (a + b + c) / 2;// 半周長      
        float s = Mathf.Sqrt(p * (p - a) * (p - b) * (p - c));// 海倫公式求面積      
        space = 2 * s / a;// 返回點到線的距離(利用三角形面積公式求高)      
        return space;
    }

點到線段距離

 public float PointToSegDist(Vector2 start,Vector2 end,Vector2 position)
    {
        float cross = (end.x - start.x) * (position.x - start.x) + (end.y - start.y) * (position.y - start.y);
        if (cross <= 0)
        {
            return Mathf.Sqrt((position.x - start.x) * (position.x - start.x) + (position.y - start.y) * (position.y - start.y));
        }

        float d2 = (end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y);
        if (cross >= d2)
        {
            return Mathf.Sqrt((position.x - end.x) * (position.x - end.x) + (position.y - end.y) * (position.y - end.y));
        }

        float r = cross / d2;
        float px = start.x + (end.x - start.x) * r;
        float py = start.y + (end.y - start.y) * r;
        return Mathf.Sqrt((position.x - px) * (position.x - px) + (py - start.y) * (py - start.y));
    }

求兩個線段的交點

 public Dictionary<bool, Vector2> get_line_intersection(Vector3 line0_start, Vector3 line0_end, Vector3 line1_strat, Vector3 line1_end)
    {
        Dictionary<bool, Vector2> intersection = new Dictionary<bool, Vector2>();
        intersection.Add(false, new Vector2(0, 0));
        float s02_x, s02_y, s10_x, s10_y, s32_x, s32_y, s_numer, t_numer, denom, t;
        s10_x = line0_end.x - line0_start.x;
        s10_y = line0_end.z - line0_start.z;
        s32_x = line1_end.x - line1_strat.x;
        s32_y = line1_end.z - line1_strat.z;

        denom = s10_x * s32_y - s32_x * s10_y;
        if (denom == 0)//平行或共線
            return intersection; // Collinear
        bool denomPositive = denom > 0;
        s02_x = line0_start.x - line1_strat.x;
        s02_y = line0_start.z - line1_strat.z;
        s_numer = s10_x * s02_y - s10_y * s02_x;
        if ((s_numer < 0) == denomPositive)//引數是大於等於0且小於等於1的,分子分母必須同號且分子小於等於分母
            return intersection; // No collision
        t_numer = s32_x * s02_y - s32_y * s02_x;
        if ((t_numer < 0) == denomPositive)
            return intersection; // No collision
        if (((s_numer > denom) == denomPositive) || ((t_numer > denom) == denomPositive))
            return intersection; // No collision
        // Collision detected
        intersection.Clear();
        intersection.Add(true, new Vector2(0, 0));
        t = t_numer / denom;
        intersection[true] = new Vector2(line0_start.x + (t * s10_x), line0_start.z + (t * s10_y));
        return intersection;
    }

點到線段最短距離的那條直線與線段的交點

  public Vector3 PointForPointToABLine(Vector3 position,Vector3 start,Vector3 end)
    {
        Vector3 reVal = new Vector3();
        // 直線方程的兩點式轉換成一般式
        // A = Y2 - Y1
        // B = X1 - X2
        // C = X2*Y1 - X1*Y2
        float a1 = end.z - start.z;
        float b1 = start.x - end.x;
        float c1 = end.x * start.z - start.x * end.z;
        float x3, y3;
        if (a1 == 0)
        {
            // 線段與x軸平行
            reVal = new Vector3(position.x, 0, start.z);
            x3 = position.x;
            y3 = start.z;
        }
        else if (b1 == 0)
        {
            // 線段與y軸平行
            reVal = new Vector3(start.x, 0, position.z);
            x3 = start.x;
            y3 = position.z;
        }
        else
        {
            // 普通線段
            float k1 = -a1 / b1;
            float k2 = -1 / k1;
            float a2 = k2;
            float b2 = -1;
            float c2 = position.z - k2 * position.x;
            // 直線一般式和二元一次方程的一般式轉換
            // 直線的一般式為 Ax+By+C=0
            // 二元一次方程的一般式為 Ax+By=C
            c1 = -c1;
            c2 = -c2;

            // 二元一次方程求解(Ax+By=C)
            // a=a1,b=b1,c=c1,d=a2,e=b2,f=c2;
            // X=(ce-bf)/(ae-bd)
            // Y=(af-cd)/(ae-bd)
            x3 = (c1 * b2 - b1 * c2) / (a1 * b2 - b1 * a2);
            y3 = (a1 * c2 - c1 * a2) / (a1 * b2 - b1 * a2);
        }
        // 點(x3,y3)作為點(x,y)到(x1,y1)和(x2,y2)組成的直線距離最近的點,那(x3,y3)是否在(x1,y1)和(x2,y2)的線段之內(包含(x1,y1)和(x2,y2))
        if (((x3 > start.x) != (x3 > end.x) || x3 == start.x || x3 == end.x) && ((y3 > start.z) != (y3 > end.z) || y3 == start.z || y3 == end.z))
        {
            // (x3,y3)線上段上
            reVal = new Vector3(x3,0, y3);
        }
        else
        {
            // (x3,y3)線上段外
            float d1_quadratic = (position.x - start.x) * (position.x - start.x) + (position.z - start.z) * (position.z - start.z);
            float d2_quadratic = (position.x - end.x) * (position.x - end.x) + (position.z - end.z) * (position.z - end.z);
            if (d1_quadratic <= d2_quadratic)
            {
                reVal = new Vector3(start.x, 0, start.z);
            }
            else
            {
                reVal = new Vector3(end.x, 0, end.z);
            }
        }
        return reVal;
    }

判斷點position是否在positionlist內(不包含線上段上)

 public bool PositionPnpoly(List<Vector3> positionlist, Vector3 position)
    {
        int i, j, c = 0;
        for (i = 0, j = positionlist.Count - 1; i < positionlist.Count; j = i++)
        {
            if (((positionlist[i].z > position.z) != (positionlist[j].z > position.z)) && (position.x < (positionlist[j].x - positionlist[i].x) * (position.z - positionlist[i].z) / (positionlist[j].z - positionlist[i].z) + positionlist[i].x))
            {
                c = 1 + c; 
            }
        }
        if (c % 2 == 0)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

 

判斷點pnt是否在region內(包含點線上段上)

 public bool isInRegion(List<Vector3> region, Vector3 pnt)
    {
        int wn = 0, j = 0; //wn 計數器 j第二個點指標
        for (int i = 0; i < region.Count; i++)
        {
            //開始迴圈
            if (i == region.Count - 1)
            {
                j = 0;//如果 迴圈到最後一點 第二個指標指向第一點
            }
            else
            {
                j = j + 1; //如果不是 ,則找下一點
            }

            if (region[i].z <= pnt.z) // 如果多邊形的點 小於等於 選定點的 Y 座標
            {
                if (region[j].z >= pnt.z) // 如果多邊形的下一點 大於於 選定點的 Y 座標
                {
                    if (isLeft(region[i], region[j], pnt) >= 0)
                    {
                        wn++;
                    }
                }
            }
            else
            {
                if (region[j].z <= pnt.z)
                {
                    if (isLeft(region[i], region[j], pnt) <= 0)
                    {
                        wn--;
                    }
                }
            }
        }
        if (wn == 0)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

 public int isLeft(Vector3 P0, Vector3 P1, Vector3 P2)
    {
        int abc = (int)((P1.x - P0.x) * (P2.z - P0.z) - (P2.x - P0.x) * (P1.z - P0.z));
        return abc;

    }

 

獲取中心點座標

 public Vector3 GetCenterPoint(List<Vector3> p)
    {
        Vector3 ptCenter = new Vector3(0, 0, 0);
        int i, j;
        double ai, atmp = 0, xtmp = 0, ytmp = 0;
        if (p == null)
            throw new ArgumentNullException("獲取多邊形中心點座標時傳入的引數為空。");
        if (p.Count == 1)
            return p[0];
        if ((p.Count == 2) || (p.Count == 3 && p[0] == p[2]))
            return new Vector3((p[1].x + p[0].x) / 2, 0, (p[1].z + p[0].z) / 2);

        int n = p.Count;
        for (i = n - 1, j = 0; j < n; i = j, j++)
        {
            ai = p[i].x * p[j].z - p[j].x * p[i].z;
            atmp += ai;
            xtmp += (p[j].x + p[i].x) * ai;
            ytmp += (p[j].z + p[i].z) * ai;
        }

        if (atmp != 0)
        {
            ptCenter.x = Convert.ToInt32(xtmp / (3 * atmp));
            ptCenter.z = Convert.ToInt32(ytmp / (3 * atmp));
        }
        return ptCenter;
    }

定比分點公式

 public Vector3 SetScorePoint(Vector3 A, Vector3 B, float i)
    {
        //P1=(X1,Y1),P2=(X2,Y2),P=(X,Y)
        //P1P=A*PP2  //P1是P2的A倍
        //X=(X1+A*X2)/(1+A),Y=(Y1+A*Y2)/(1+A)
        Vector3 P = new Vector3();
        P = new Vector3((A.x + i * B.x) / (1 + i), 0, (A.y + i * B.y) / (1 + i));
        return P;
    }

 

求一點在直線的左側還是右側還是線上

   public float GetDirectionFromLine(Vector3 start,Vector3 end,Vector3 point)
    {
        Vector3 v1 = end - start;
        Vector3 v2 = start - point;
        if ((v1.x * v2.z - v2.x * v1.z) > 0)//在右側
        {
            return 1;
        }
        else if ((v1.x * v2.z - v2.x * v1.z) < 0)//在左側
        {
            return -1;
        }
        else //等於0時在線上
        {
            return 0;
        }
    }

求一點在向量的左側還是右側還是線上

 public float GetDirectionFromVec(Vector3 start, Vector3 end, Vector3 point)
    {
        float f = (start.z - end.z) * point.x + (end.x - start.x) * point.z + start.x * end.z - end.x * start.z;
        if (f > 0)//左側
        {
            return -1;
        }
        else if (f < 0)//右側
        {
            return 1;
        }
        else//線上
        {
            return 0;
        }
    }

 

Hexnumber轉變成color

 public Color32 HexToColor(string hex)
    {
        hex = hex.Replace("0x", "");//in case the string is formatted 0xFFFFFF
        hex = hex.Replace("#", "");//in case the string is formatted #FFFFFF
        byte a = 255;//assume fully visible unless specified in hex
        byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
        byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
        byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
        //Only use alpha if the string has enough characters
        if (hex.Length == 8)
        {
            a = byte.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber);
        }

        return new Color32(r, g, b, a);

    }