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