三维点数据快速索引

  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的值相对会很小,从而整体截断误差小,从而保证更高的准确率。

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