簡體   English   中英

快速算法查找矩形內的所有點

[英]Fast algorithm to find all points inside a rectangle

給定2D空間中的一組不同點,以及矩形(所有四個點的坐標,與xy軸平行的邊),如何快速找到矩形內的哪些點?

我對通過所有點並看到哪個點位於矩形內的基本解決方案不感興趣。 我正在尋找的是一種算法,它可以為每個矩形提供快速的查詢時間。

我不在乎我在預處理步驟中花了多少時間。 我所關心的是,在處理完數據之后,我獲得了一個有用的結構,它為每個矩形提供了快速的查詢時間。

我知道例如我可以計算O(logN)中矩形內有多少個點。 這是有效的,因為我在開始時做了很多繁重的處理,然后每次用新的矩形查詢處理過的數據,並在logN時間內得到一個新的計數。 我正在尋找一種類似的算法,用於找到實際的點,而不僅僅是它們的數量。

經典答案是kD樹(在這種情況下是2D樹)。

對於一個簡單的替代方案,如果您的點分布足夠均勻,您可以嘗試網格化。

為方形網格選擇單元格大小(如果問題是各向異性的,請使用矩形網格)。 將每個點分配給包含它的網格單元,存儲在鏈表中。 執行查詢時,查找與矩形重疊的所有單元格並掃描它們以遍歷其列表。 對於部分覆蓋的單元格,您需要執行矩形點測試。

尺寸的選擇很重要:太大可能導致需要測試太多的點; 太小會導致太多空單元格。

您正在尋找kd樹范圍搜索或范圍查詢。

  • 當有一組不斷變化的點時,四叉樹(或八葉樹或十六樹......)會更好,但你希望分布是均勻的。 不需要進一步的平衡步驟,因為樹的結構是固定的。
  • kd-tree在固定的點集上表現更好,即使分布不均勻。 當點集發生變化時,很難(但並非不可能)進行自平衡步驟。
  • AABB樹(或脂肪AABB樹)提供了一種快速測試重疊形狀的方法,而不僅僅是點。 AABB樹偶爾需要一些平衡。 當包含不斷移動的對象時,常見的方法是使用“fat AABB-s”,因此您不必在每個幀中更新樹。
  • 僅按一個軸排序並使用二分搜索(類似abelenky建議,但我認為進行第二次二分搜索沒有意義)是一個簡單而優雅的解決方案,但是當你按X軸排序時會很慢,並且所有點都在與Y平行的一條線上。你必須對二進制搜索與X匹配的點進行線性過濾。時間復雜度最差的情況是O(n) ,但這種最壞的情況經常發生。

所有這些算法以平均O(log n + k)運行查詢,其中k是匹配點的計數。

像Yves建議的那樣,網格化可以在O(k)時間內執行范圍搜索,但僅限於查詢矩形的大小有界時。 這是他們在粒子模擬中經常做的事情。 即使輸入集沒有限制,也可以使用網格化 - 只需根據網格坐標的哈希值對固定數量的桶進行計數。 但是如果查詢矩形可以是任意大小,那么網格化是不行的。

您可以將扇區分組。 如果扇區完全在給定矩形內或外,則其中的所有點也在內或外。 如果扇區部分存在,則必須在O(n)中搜索該扇區中的點以檢查它們是否在矩形中。 尋找kd樹搜索。

除了其他答案,您還可以查看Morton代碼(z順序曲線排序)。

在您的情況下,即靜態數據,您甚至可以將整個點數據表示為數組。

https://en.wikipedia.org/wiki/Z-order_curve

本文還有一個相當復雜的不同“多維訪問方法”的時間表 - http://www.cc.gatech.edu/computing/Database/readinggroup/articles/p170-gaede.pdf

我認為你應該將你的積分存儲在四叉樹中 我沒有弄清楚細節,但它應該允許基本上做類似於二進制搜索的東西,直接產生矩形內的點。

如果您的點是聚類的,即存在在小區域中包含許多點的聚類以及其他不包含或非常少的點的區域,則R樹可能更好。

我認為運行時復雜度應該是O(logN)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM