求3D點集中最近點的一個空間二叉樹實現

                  求3D點集中最近點的一個空間二叉樹實現
                   [email protected]  2010.09.12

 

(2011-03-04  修改節點內存泄漏,漏了一句m_nodePool.push_back(m_cur); )

 

tag:求3D點集中最近點,空間二叉樹,點集最小包圍球

摘要:
    這幾天爲了解決一個顏色空間匹配搜索速度太慢的問題(求3D點集中最近點),寫了一個基於3D空間二叉樹分割的算法的實現,

速度提高了幾十倍;

正文:    

A: 問題簡單描述
   已知3D點集U(較多),求出U中與給定點p最近的點;可能會非常多次 的給定不同的p點,而點集U不變;
 
B: 一些基礎代碼和最簡單的一個實現和其簡要優化
定義3D點:


尋找最近點的算法簡單實現:

該算法遍歷點集U(points[]),找尋點集中距離test_point最近的點,返回其座標,算法複雜度爲O(N);

簡單優化:
前面的程序計算點之間的距離來比較大小,涉及到開方運算,比較慢;而比較的時候,改成比較距離的平方效果也一樣,
函數返回距離的時候,在把最終結果開方就好了;代碼如下:


這個代碼的速度是前面實現的3倍多;
當然該算法還可以繼續優化的;但因爲算法複雜度太高,進一步優化的意義不大;
下面給出一個平均複雜度O(log(N))的算法

C: 基於3D空間二叉樹分割的算法的實現
   對點集U進行預處理,生成一棵3D空間二叉樹:
     將點集U的最長軸按中值劃分成2個新的點集;計算新形成的2個點集的最小包圍球;
     如果新劃分出的點集的點個數比較多,可以進一步劃分,一直到不用劃分;
(劃分方法可以是該軸的中值、均值或平分個數的值等,程序裏選擇用中值劃分;
包圍體也可以爲其它3D幾何包圍體,比如正6面體等,程序裏選擇球型包圍體,算法實現更簡單快速些)

   利用二叉樹尋找離給定點最近的點:
      程序用深度優先順序遍歷二叉樹,遇到有2分支的時候優先處理距離近的分支;
      快速排除一個點集的算法原理: 假設搜尋過程中,當前已經得到的離p點最近的點的距離爲minD,
現在尋找到了點集u(包圍球半徑ur,球心座標up); 如果 (p到up的距離 - ur) > minD ,那麼該點集u和
其子點集都可以立即排除掉了;而且該判斷表達式還可以改進爲 p到up的距離的平方>(minD+ur)的平方
計算起來就更加快速了;
     (如果想用廣度優先算法遍歷二叉樹,可以維持一個隊列,儲存當前沒有被排除的點集,然後展開這些點集,快速排除不可能的點集,直到沒有點集分
支可以展開;這種遍歷方式可以利用的快速排除一個點集的算法原理爲: 假設搜尋過程中,當前已經得
到的離p點最近的點集距離爲minD,該點集包圍球半徑爲ur,現在尋找到了點集v(包圍球半徑vr,球心坐
標vp); 如果 (p到vp的距離 - mr) > (minD+ur),那麼該點集v和其子點集就可以立即排除掉;該判斷表
達式也可以改進爲 p到vp的距離的平方 > (minR+ur+mr)的平方 !    )

代碼實現:



D:完整測試代碼



E:速度對比
   使用的編譯器爲vc2008;測試使用的CPU爲i7 920;
--------------------------------------------
3D點集數量: 64
      遍歷算法0: 每秒處理1134824個點
      遍歷算法1: 每秒處理3564980個點
  空間2叉樹算法: 每秒處理4871770個點
--------------------------------------------
3D點集數量: 256
      遍歷算法0: 每秒處理291841個點
      遍歷算法1: 每秒處理1059374個點
  空間2叉樹算法: 每秒處理3144091個點
--------------------------------------------
3D點集數量: 1000
      遍歷算法0: 每秒處理76064個點
      遍歷算法1: 每秒處理295625個點
  空間2叉樹算法: 每秒處理2068754個點
--------------------------------------------
3D點集數量: 10000
      遍歷算法0: 每秒處理7643個點
      遍歷算法1: 每秒處理30166個點
  空間2叉樹算法: 每秒處理1111412個點
--------------------------------------------
3D點集數量: 100000
      遍歷算法0: 每秒處理772個點
      遍歷算法1: 每秒處理2984個點
  空間2叉樹算法: 每秒處理604217個點
--------------------------------------------
3D點集數量: 1000000
      遍歷算法0: 每秒處理83個點
      遍歷算法1: 每秒處理272個點
  空間2叉樹算法: 每秒處理272924個點

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章