十字鏈表的AOI算法

http://www.codedump.info/?p=388


看了雲風寫的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是移動之後纔看見該結點的結點集合,這個集合的結點,要發送該結點進入場景的消息.

我把這個算法的實現放在了這裏


發佈了67 篇原創文章 · 獲贊 19 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章