經營類遊戲:由軸對齊矩形相交斷定到斷定菱形構成的平行四邊形相交斷定(一)

普通多邊形之間的相交測試是個複雜的問題,咱們只考慮 軸對齊的 菱形問題即菱形的對角線和座標軸平行的相交問題。測試

和座標軸平行的矩形的相交問題:get

矩形A B由左上角定點和右下角定點描述, x軸正方向右, y正方向 向下。import

             圖1
原理

設:A的左上定點 x0y0, 右下 x1 y1    B 左上 x2 y2  右下 x3 y3im

二維問題通常降維度處理:di

有 若是兩個矩形 在 x軸y軸投影都相交, 則兩個矩形相交math

即: x0 < x3  &&  x2 < x1 && y0 < y3 && y2 < y1分割

由於兩個座標軸上的相交區域惟一肯定一個 矩形return

具體的矩形 範圍受 座標的實際大小關係肯定ab


如今咱們須要考慮菱形的問題:

菱形的軸是傾斜的, 那麼如何求軸上的投影範圍, 來進行相交測試呢?

                            圖2

好吧,這樣計算的確有些困難, 咱們參見圖1, 能夠有個思路, 首先肯定一個菱形的包圍盒, 任意一個菱形都有惟一的軸對稱包圍盒。

設一個菱形的座標軸x方向寬度 2* sizeX,  座標軸y方向  2* sizeY

考慮:如下三種狀況

咱們須要求得這些菱形組合的包圍盒的大小:

設從左上到右下的爲菱形的 軸x方向, 從 右上到坐下 爲 菱形軸y方向, sx 爲x向 菱形的個數, sy 爲y方向個數

狀況1:

除了第一個菱形塊以外, 其它菱形塊每增長一個寬度增長一個sizeX 高度增長 一個 sizeY


寬度 = (2+sy-1)*sizeX (sizeX是單個菱形寬度的一半)  

高度=(2+sy-1)*sizeY (sizeY 是單個菱形高度的一半)

狀況2:(最下面的那個)

寬度 = (2+sx-1)*sizeX

高度=(2+sx-1) *sizeY

最後的複雜狀況:

先考慮 沿x 方向的 值, 再加上 y方向的值

寬度 = (2+sx-1 + sy-1)*sizeX

高度 = (2+sx-1 + sy-1)*sizeY


實際上簡化以後:

寬度 = (sx+sy)*sizeX

高度 = (sx+sy)*sizeY


這些拼接圖形的中點 , 就是他們 包圍盒的中點?

能夠作上輔助線。 咱們根據平線線的分割原理就能夠證實


下一個問題是求得這個拼接圖形的四個定點的位置; 首先咱們須要假定 座標軸的 0,0點在包圍盒的左上角, x向右 ,y向下

上圖就是四個頂點的所在位置的值。


最後如何斷定相交?

考慮傾斜的軸構成的座標系:

求一個點在這兩個軸上的投影長度 , 能夠採用內積:

x軸向: (sizeX, sizeY)

y軸向:(-sizeX, sizeY)

t1 = (x, y) *(sizeX, sizeY)/ ( |(x, y)|)

t2 = (x, y)*(-sizeX,  sizeY) /|(x, y)|



因此向判斷 矩形同樣判斷 t1 t2的範圍就能夠了



下面是pyhon代碼:

import math
sizeX = 135/4
sizeY = 67/4

#菱形拼圖的x y 長度 和 中心位置
ab = sx1, sy1, x1, y1 = 2, 2, 0, 0
bb = sx2, sy2, x2, y2 = 2, 2, -40, 20

#求得一個拼圖的左上角點和右下角點
def getBoundary(arg):
    sx, sy, x, y = arg
    x0 = x - (sx+sy)/2*sizeX
    y0 = y - (sx+sy)/2*sizeY
    x1 = x0 + sy*sizeX
    y1 = y0
    x2 = x0 + sx*sizeX
    y2 = y0 + (sx+sy)*sizeY
    print [x0, y0, x1, y1, x2, y2, sizeX, sizeY]
    return [x1, y1, x2, y2]

#求得一個點在x方向的投影
def getT1(x, y):
    if x == 0 and y == 0:
        return 0
    return (x*sizeX+y*-sizeY)/math.sqrt(x*x+y*y)/math.sqrt(sizeX*sizeX+sizeY*sizeY)
#求得一個點在y方向的投影
def getT2(x, y):
    if x == 0 and y == 0:
        return 0
    return (x*-sizeX+y*-sizeY)/math.sqrt(x*x+y*y)/math.sqrt(sizeX*sizeX+sizeY*sizeY)
def getABound(a):
    a = getBoundary(a)
    t1 = getT1(a[0], a[1])
    t2 = getT2(a[0], a[1])
    t11 = getT1(a[2], a[3])
    t22 = getT2(a[2], a[3])
    print [a, t1, t2, t11, t22]
    return [t1, t2, t11, t22]
def main():
    aBound = getABound(ab)
    bBound = getABound(bb)
    print aBound
    print bBound
main()


錯了:

不能經過 求內積來求 點在菱形邊上的投影, 只有當菱形的邊互相垂直的時候才成立;

這是由於 非直角 不是 普通的幾何。


那麼該怎麼辦呢? 如何計算相交?

這個我 再想一想



若是咱們約束 全部的菱形拼圖都是 n*n的話, 存在一種解法:

能夠計算兩個拼圖中心的 x y 差值

再根據 拼圖的 邊的寬度 = sx*sizeX,  sx*sizeY    

只要保證兩個拼圖的 x , y 差值 不 小於 邊的寬度 就能夠了


拼圖中心相差的 x y 方向的格子數目, abs(difx)+abs(dify) >= boundA + boundB  則不相交

相關文章
相關標籤/搜索