十字連結串列的AOI演算法

工程師WWW發表於2014-06-11

看了雲風寫的AOI演算法文章,自己也照著寫了一下,感覺不容易理解,裡面提到了十字連結串列的演算法,在某同學提示下寫了個實現.

演算法的大概思想如下.每個場景維護兩個連結串列,分別為X軸和Y軸的座標按序排列好的連結串列,也就是比如在X軸連結串列上,越在前的物件,X座標越小,Y軸連結串列同理.這樣,每次需要更新狀態的時候,只需要在這個連結串列上向前或者向後遍歷結點就知道該通知誰了.

這裡假設有三個API:Add(向場景中新增一個物件),Leave(某物件離開場景),Move(某物件在場景中移動).

來一個一個看.

Add:根據新增物件的X,Y座標,依次遍歷X,Y軸座標連結串列,這裡有兩個目的,一個是獲得這個新增物件的座標在X,Y軸座標的位置,另一方面獲得該通知哪些結點.通知的範圍,每個物件可以自己定製自己的通知範圍.但是為了簡單起見,在這裡我們假設每個結點X,Y座標相差1,而通知的範圍是2.比如原有的X軸座標為:
a->b->c->d->e->f->g->h
假設新增一個物件z,它最終所在的位置是c和d之間,根據前面的假設,它只需要通知b,c,e,f四個結點就好了.所以,新增一個結點的時候,並不需要遍歷完連結串列的.
但是這裡還需要注意的是,一個結點,必須X,Y座標同時都在通知範圍內才可以進入通知集合.

Leave:在新增了物件之後,物件身上掛了兩個結點,分別存放在X,Y軸座標連結串列上的位置,那麼在這個物件要離開場景時,也只需要向前向後探索一定的範圍,就可以得到需要通知該物件要離開的集合了.

Move:移動操作比較麻煩,但是也可以比較漂亮的解決.在更新位置之前,同樣根據前面的演算法得到要通知的結點集合,稱為old_set;更新位置之後,再獲取另一個通知集合,稱為new_set;然後,old_set和new_set的交集,稱為move_set,在此集合中的結點,在移動前後都在通知範圍,因此要向這個集合的結點傳送該物件移動的訊息;而old_set-move_set的集合,在移動之後已經離開了視野,因此要向它們傳送該物件離開的訊息;最後,new_set-move_set是移動之後才看見該結點的結點集合,這個集合的結點,要傳送該結點進入場景的訊息.

我把這個演算法的實現放在了這裡.

相關文章