egret判斷兩個多邊形是否相交 分離軸定律

2021-09-24 05:28:57 字數 3844 閱讀 1221

預備知識:向量的點積:

關於向量的知識這裡不再贅述 

概念:通過判斷任意兩個凸多邊形在任意角度下的投影是否均存在重疊,來判斷是否發生碰撞。若在某一角度光源下,兩物體的投影存在間隙,則為不碰撞,否則為發生碰撞。

圖例:

在程式中,遍歷所有角度是不現實的。那如何確定投影軸呢?其實投影軸的數量與多邊形的邊數相等即可。

上述**有幾個需要解決的地方:

投影軸如下圖所示,我們使用一條從 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這兩個陣列用來存放座標,計算兩個向量,然後讓計算它們的叉積,如果叉積小於零,說明後乙個向量在前乙個向量的右側,即順時針方向,只要有乙個是這樣的情況,則不符合條件。然後就是...