預備知識:向量的點積:
關於向量的知識這裡不再贅述
概念:通過判斷任意兩個凸多邊形
在任意角度下的投影是否均存在重疊,來判斷是否發生碰撞。若在某一角度光源下,兩物體的投影存在間隙,則為不碰撞,否則為發生碰撞。
圖例:
在程式中,遍歷所有角度是不現實的。那如何確定投影軸
呢?其實投影軸的數量與多邊形的邊數相等即可。
上述**有幾個需要解決的地方:
投影軸如下圖所示,我們使用一條從 p1 指向 p2 的向量來表示多邊形的某條邊,我們稱之為邊緣向量。在分離軸定理中,還需要確定一條垂直於邊緣向量的法向量,我們稱之為「邊緣法向量」。
投影軸平行於邊緣法向量。投影軸的位置不限,因為其長度是無限的,故而多邊形在該軸上的投影是一樣的。該軸的方向才是關鍵的。
投影投影的大小:通過將乙個多邊形上的每個頂點與原點(0,0)組成的向量,投影在某一投影軸上,然後保留該多邊形在該投影軸上所有投影中的最大值和最小值,這樣即可表示乙個多邊形在某投影軸上的投影了。
判斷兩多邊形的投影是否重合:projection1.max > projection2.min && project2.max > projection.min
碰撞工具類:
inte***ce ipoint
class collisionuitls ;
const p2 = ;
const p3 = ;
const p4 = ;
return [p1, p2, p3, p4];
}/**
* 檢測圓和多邊形
* @param obj1
* @param obj2
*/public static testcircleandpolygon(circlex: number, circley: number,r:number, polygonvertexpoints: ipoint): boolean else
sidenorvec = collisionuitls.get2pointvec(startpoint, endpoint, false);
//這個邊的法相量方向(標準化過的)
let dotnorvec = collisionuitls.getsidenorml(sidenorvec, false);
const data1 = collisionuitls.calcproj(dotnorvec, polygonvertexpoints);
const dot = collisionuitls.dot([circlex, circley], collisionuitls.normalize(dotnorvec));
const value = collisionuitls.segdist(data1.min, data1.max, dot-r, dot+r);
if (!value)
}return true;
}/**
* 檢測兩個矩形是否相交
* @param r1pointlist 矩形頂點陣列
* @param r2pointlist
*/public static checkpolygon(r1pointlist: ipoint, r2pointlist: ipoint): boolean else
sidenorvec = collisionuitls.get2pointvec(startpoint, endpoint, false);
//這個邊的法相量方向(標準化過的)
let dotnorvec = collisionuitls.getsidenorml(sidenorvec, false);
const data1 = collisionuitls.calcproj(dotnorvec, vertexpoints1);
const data2 = collisionuitls.calcproj(dotnorvec, vertexpoints2);
const value = collisionuitls.segdist(data1.min, data1.max, data2.min, data2.max);
if (!value)
}return true;
}if (!fun1(r1pointlist, r1pointlist, r2pointlist))
if (!fun1(r2pointlist, r1pointlist, r2pointlist))
return true;
}/**
* 計算某個圖形座標點到當前軸上的投影最小點
* @param axis
* @param objpoints
*/public static calcproj(axis: number, objpoints: ipoint): else
}return
}/**
* 計算同乙個軸上線段的距離s1(min1,max1),s2(min2,max2),如果距離小於0則表示兩線段有相交;
* @param min1
* @param max1
* @param min2
* @param max2
* @returns true: 相交 false: 不相交
*/public static segdist(min1: number, max1: number, min2: number, max2: number): boolean
else
}/**
* 計算兩點向量方向
* @param p1
* @param p2
*/public static get2pointvec(p1: ipoint, p2: ipoint, isnormlize = true): number
return [x, y];
}/**
* 根據當前多邊形邊長獲取對應邊長的 法線向量
* @param vec2
*/public static getsidenorml(vec2: number, isnormlize = true): number
return [-y, x];
}public static normalize(vec2: number): number
const x = vec2[0];
const y = vec2[1];
const model = math.sqrt(x * x + y * y);
return [x / model, y / model];
}/**
* 計算兩個向量的點積
* @param vec2a
* @param vec2b
*/public static dot(vec2a: number, vec2b: number): number
return vec2a[0] * vec2b[0] + vec2a[1] * vec2b[1];}}
判斷兩個凸多邊形是否相交 SAT
最近在看recast detour原始碼的時候有遇到許多數學上的演算法問題,特此記錄,以便以後檢視。介紹 應用分離軸定理 sat 看是否能找到分離軸,如果能找到那麼就是不相交。否則相交。利用點積的幾何意義 投影 判斷 polya 和 polyb 兩個多邊形是否相交 all vertices are ...
判斷點是否在兩個多邊形之間
inline bool in range float t1,float t2,float x 判斷點是否在圈內 採用水平填充演算法 1.count 0 2.以p為端點,作從右向左的射線l 3,for 多邊形的每條邊s 4.do if p在邊s上 5.then return true 6.if s不是...
判斷乙個多邊形是否是凸多邊形
乙個很簡單的問題看了好久,但就是提交不過,也看不出是哪齣了問題 問題為 判斷乙個多邊形是否是凸多邊形 我的思路是這樣的 建立x,y這兩個陣列用來存放座標,計算兩個向量,然後讓計算它們的叉積,如果叉積小於零,說明後乙個向量在前乙個向量的右側,即順時針方向,只要有乙個是這樣的情況,則不符合條件。然後就是...