三維點數據快速索引

  12.1 三維點數據快速索引

class 

class Vector3{ public double X,Y,Z;}
class Vector3Ex{ public Vector3 Vect;public int Index;}
class Vector3ExList{
    public List<Vector3Ex> Items=new List<Vector3Ex>();
    public void Add(Vector3 v,int index){
       Items.Add(new Vector3Ex(){vect=v,Index=index};);
    }
}
class Vector3XCollection{
    public Vector3ExList[] Items=new Vector3ExList[100];
    
    public void Add(int key,Vector3 v,int index){
      Items[key].Add(new Vector3Ex(v,index));
    }
}

public class Vector3IndexHelper{
  private List<Vector3XCollection> m_keys=new List<Vector3XCollection>();
  public Vector3IndexHelper(List<Vector3> items){
    for(var i=0;i<3;i++){
        m_keys[i]=new Vector3XCollection();
     }
     int index=0;
     foreach(var item in items){
       var keys=BuildKeys(item);
        for(var i=0;i<keys.length;i++){
           m_keys[i].Add(keys[i],item,index);
         }
     }
    index++;0
  }
  public int GetIndex(Vector3 v){
    var keys=BuildKeys(v);
    int minCount=int.MaxValue;
    int selIndex=0;
     for(var i=0;i<3;i++){
      if(minCount>m_keys[keys[i].Items.Count){
        selIndex=i;
       }
    }
    for(var j=0;j<m_keys[i].Items.Count;j++){
     if(m_keys[i].Items[j].Vect==v){
return j;
      }
    }
  return 0;
  }


   private int[] BuildKeys(Vector3 v){
      var tx=Math.Floor(v.x);
       var ty=Math.Floor(v.y);
       var tz=Math.Floor(v.z);
       var k1=(int)(tx+ty+tz)%100;
       var k2=(int)(tx*tx+ty*ty+tz*tz)%100;
       var k3=(int)(tx*ty+*tz)%100;
       return new int[]{k1,k2,k3};
   }
  
}

 

 

 

12.2 矩陣計算

        無論是大數據計算,還是空間計算。矩陣是這些計算最好的表達方式。矩陣將複雜的世界劃分爲多個維度(雖然會有同學認爲,世界是可以理解一點的,而矩陣不是)。我經常面對的是基於一個點,然後構建一個局部座標系。如下面代碼所示:

 /// <summary>
        /// 構建基於空間位置position所在的點的局部座標系,不包含位置偏移
        /// <para>Z軸Position向上</para>
        /// <para>Y軸指向正北</para>
        /// <para>X軸指向東方</para>
        /// </summary>
        /// <param name="position"></param>
        /// <returns></returns>
        public static Matrix BuildPositionRelatedMatrix(CoordinatePosition position)
        {
            Vector3 zAxis = position.Vector3;
            zAxis.Normalize();
            Vector3 yAxis = new Vector3(-zAxis.X, -zAxis.Y, 0);
            yAxis.Normalize();
            Vector3 xAxis = Vector3.Cross(yAxis, zAxis);
            xAxis.Normalize();
            yAxis = Vector3.Cross(zAxis, xAxis);
            yAxis.Normalize();

            Matrix m = new Matrix();
            m.M11 = xAxis.X; m.M12 = xAxis.Y; m.M13 = xAxis.Z; m.M14 = 0;
            m.M21 = yAxis.X; m.M22 = yAxis.Y; m.M23 = yAxis.Z; m.M24 = 0;
            m.M31 = zAxis.X; m.M32 = zAxis.Y; m.M33 = zAxis.Z; m.M34 = 0;
            m.M41 = 0; m.M42 = 0; m.M43 = 0; m.M44 = 1;

            return m;
        }

     上面的代碼很簡潔,一不小心就看完了。它的作用是虛構一個局部座標系,基於局部座標系的計算比基於原來的座標系更容易。如果你沒有學過四元數,那麼這個矩陣計算可以間接的計算四元數的旋轉方法。

     矩陣運算的難度不在於計算的過程,而在於理解如何使用矩陣計算和什麼時候可以可以使用矩陣。有些同學或許可以通過普通函數等方式來做一些矩陣計算(比如向量旋轉,既可以通過三角函數計算,也可以使用矩陣的方式)。但是使用普通的方式一般需要繞一個長長的思維轉換,有時候不得不把不能實現的過程刪除。

     12.2 概率思維

   概率計算我用的少,但是概率思維確實幫助很大。一些同學沒有量化的概念,只有可能發生就認爲就值得的去努力。現在有很多軟件,滿滿的鋪滿的按鈕,提供各式各樣的功能,但它知道多少功能普通人會用到。

    概率函數大家用的也多,我有時候會根據一些對象構建它的hash值,hash值是存在重複的,但是重複率很低很低。即使重複了,對系統的基本要求也是不影響的。但是一些同學會揪着這個“可能”不放,從而影響開發思想的統一。

     使用概率思想的地方,可能需要給系統打一些“補丁”,比如上面可能出現的重複,這些補丁是輕量級的。

     12.3 平滑計算

    我們都知道,計算機對數值存在精度問題,所以計算過程中很容易出現精度誤差。應該避免的是很大的數或者很小的數進行乘除等運算。還有避免判斷小數的數值是否相同。比如,我們通常判斷兩個線段是否相交的過程是:

  1. 分別建立線段A和線段B的直線方程
  2. 計算直線相交的點P。
  3. 判斷P是否在線段A內部,判斷P是否在線段B內部

     上述的方法存在的問題是最後一點。因爲存在數值等於判斷,如果步驟1,2存在精度截斷,那麼3的判斷很可能不準確。

     而我推薦的方法是判斷兩點是否在一條直線的同一邊的方式,也就是線段A的兩個點都在直線B的同一邊,同時線段B的兩個點都在直線B的同一邊。

  1. 構建線段A的直線
  2. 對B的兩個頂點,判斷是否在直線A的同一側,如果不是,退出
  3. 同理對A的兩個頂點進行處理。

       部分代碼如下:

           double A, B, C, value1, value2;
            A = line1EP.Y - line1SP.Y;
            B = line1SP.X - line1EP.X;
            C = -line1SP.X * A - line1SP.Y * B;
            value1 = A * line2SP.X + B * line2SP.Y + C;
            value2 = A * line2EP.X + B * line2EP.Y + C;
            if (value1 > 0 && value2 > 0)
            {
                return false;
            }
            if (value1 < 0 && value2 < 0)
            {
                return false;
            }

    上面計算雖然可能會有截斷,但是A,B的值相對會很小,從而整體截斷誤差小,從而保證更高的準確率。

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