关于四叉树的原理我想应该不需要多说啦,大家都懂得,实在不晓得的话,百度吧~
由于四叉树索引效率还可以并且非常简单,因此在Gis中广泛的应用也是毋庸置疑的。
本次就自己实现一个地图四叉树索引,但是还有一些问题也希望各位路过的大神能指点一下。
首先,结合一下应用场景(我们需要用四叉树来索引地图数据),考虑一下使用四叉树索引地图数据存在的一些问题。
1.什么时候建立四叉树索引,四叉树索引如何存储(序列化还是自己写算法来存储四叉树)?第一次加载数据的时候建立四叉树,当对地图数据操作的时候动态的维护四叉树,关闭地图的时候,保存内存中的四叉树实例,以避免每次建立四叉树耗时。目前我直接使用四叉树序列化。
2.什么东西可能会影响到四叉树索引地图数据的效率?树的深度,空节点每次还要被搜索,使用不平衡四叉树来避免无意义的搜索;每个节点上所关联的地图数据个数。子节点已经包含了地图数据的实例,则父节点不包含,减少数据的冗余。
为了可以在四叉树节点上关联地图数据,设计如下结构来表示地图数据。
/// <summary>
/// 包含有包络线的对象接口定义
/// </summary>
public interface IHasBoundingBox
{
/// <summary>
/// 几何对象的包络线
/// </summary>
BoundingBox Box
{
get;
set;
}
}
/// <summary>
/// 几何对象的的ID和包络线构成索引对象
/// </summary>
public class GeoBox:IHasBoundingBox
{
BoundingBox _box;
/// <summary>
/// 几何对象的Id
/// </summary>
public uint ID;
#region IHasBoundingBox 成员
public BoundingBox Box
{
get
{
return _box;
}
set
{
_box = value;
}
}
#endregion
}
用一个矩形范围和几何对象的Id来表示地图上需要索引的几何对象,当请求地图数据的时候,首先根据地图范围来遍历四叉树,找到对应四叉树的节点后,遍历该自树获取所有数据,即Id,根据Id去读取物理文件的数据。
四叉树节点的定义:
/// <summary>
/// 四叉树节点
/// </summary>
/// <typeparam name="T">节点中所包含的数据类型</typeparam>
public class QuadNode<T>
{
private int _depth;
private List<T> _datas;
private BoundingBox _rect;
private QuadNode<T> _lt;
private QuadNode<T> _rt;
private QuadNode<T> _lb;
private QuadNode<T> _rb;
private bool _isLeaf;
private QuadNodeLimit _limit;
public QuadNodeLimit Limit
{
get { return _limit; }
}
public bool IsLeaf
{
get { return _isLeaf; }
set { _isLeaf = value; }
}
public int Depth
{
get { return _depth; }
set { _depth = value; }
}
public List<T> Datas
{
get { return _datas; }
set { _datas = value; }
}
public BoundingBox Rect
{
get { return _rect; }
set