JTS SpatialIndex

空间索引技术的核心是:根据搜索条件,比如一个矩形,迅速找到与该矩形相交的所有空间对象集合。当数据量巨大,矩形框相对于全图很小时,这个集合相对于全图数据集大为缩小,在这个缩小的集合上再处理各种复杂的搜索,效率就会大大提高。

(1)、四叉树索引

四叉树索引的基本思想是将地理空间递归划分为不同层次的树结构。它将已知范围的空间等分成四个相等的子空间,如此递归下去,直至树的层次达到一定深度或者满足某种要求后停止分割。四叉树的结构比较简单,并且当空间数据对象分布比较均匀时,具有比较高的空间数据插入和查询效率,因此四叉树是GIS中常用的空间索引之一。
四叉树对于区域查询,效率比较高。但如果空间对象分布不均匀,随着地理空间对象的不断插入,四叉树的层次会不断地加深,将形成一棵严重不平衡的四叉树,那么每次查询的深度将大大的增多,从而导致查询效率的急剧下降。

(1)四分区域标识

分别定义了一个平面区域的四个子区域索引号,右上为第一象限0,左上为第二象限1,左下为第三象限2,右下为第四象限3

typedef enum

{

      UR = 0,// UR第一象限

      UL = 1, // UL为第二象限

      LL = 2, // LL为第三象限

      LR = 3  // LR为第四象限

}QuadrantEnum;

(2)空间对象数据结构

空间对象数据结构是对地理空间对象的近似,在空间索引中,相当一部分都是采用MBR作为近似。

/*空间对象MBR信息*/

typedef struct SHPMBRInfo

{

      int nID;       //空间对象ID

      MapRect Box;    //空间对象MBR范围坐标

}SHPMBRInfo;

nID是空间对象的标识号,Box是空间对象的最小外包矩形(MBR)。

(3)四叉树节点数据结构

四叉树节点是四叉树结构的主要组成部分,主要用于存储空间对象的标识号和MBR,也是四叉树算法操作的主要部分。

/*四叉树节点类型结构*/

typedef struct QuadNode

{

      MapRect            Box;                   //节点所代表的矩形区域

      int                nShpCount;        //节点所包含的所有空间对象个数

      SHPMBRInfo* pShapeObj;          //空间对象指针数组

      int         nChildCount;            //子节点个数

      QuadNode *children[4];             //指向节点的四个孩子

}QuadNode;

Box 是代表四叉树对应区域的最小外包矩形,上一层的节点的最小外包矩形包含下一层最小外包矩形区域; nShpCount 代表本节点包含的空间对象的个数; pShapeObj 代表指向空间对象存储地址的首地址,同一个节点的空间对象在内存中连续存储; nChildCount 代表节点拥有的子节点的数目; children 是指向孩子节点指针的数组。
JST 四叉树实现原理
com.vividsolutions.jts.index.quadtree.Quadtree
A Quadtree is a spatial index structure for efficient querying of 2D rectangles.  If other kinds of spatial objects need to be indexed they can be represented by their envelopes
quadtree structure is used to provide a primary filter for range rectangle queries.  The query() method returns a list of all objects which may  intersect the query rectangle.  Note that it may return objects which do not in fact intersect.
四叉树的空间索引结构的二维矩形的高效查询。如果其他类型的空间对象需要被索引他们可以通过自己的最小外包矩形来表示
四叉树结构是用来提供一个初级过滤器为矩形范围查询。在query()方法返回一个可以相交的查询区域内的所有对象的列表。请注意,它可能会返回其实不相交的对象。
eg:
public class QuadTreeDemo {
	
	private Quadtree quadTree = new Quadtree();
	
	public void buildQuadTree(){
		Envelope enve = new Envelope(0, 1, 0, 1);
		Envelope enve1 = new Envelope(0, 1, 0, -1);
		Envelope enve2 = new Envelope(0, -2, 0, 2);
		Envelope enve3 = new Envelope(0, -3, 0, -3);
		quadTree.insert(enve, "first");
		quadTree.insert(enve1, "second");
		quadTree.insert(enve2, "third");
		quadTree.insert(enve3, "fourth");
	}

	
	public void query(Envelope enve){
		List<String> StrList = quadTree.query(enve);
		for(String str:StrList) {
			System.out.println(str);
		}
	}
	
	public static void main(String[] args) {
		QuadTreeDemo qd = new QuadTreeDemo();
		qd.buildQuadTree();
		Envelope enve = new Envelope(0.1, 0.5, 0.1, 0.5);
		qd.query(enve);
		System.out.println("------分割线--------");
		Envelope enve1 = new Envelope(0.5, 0.5, 0.5, -0.5);
		qd.query(enve1);
	}
}
输出结果:
first
------分割线--------
second
first

(2)、K-d树索引
 k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构。主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索)。
k-d树是一个二叉树,每个节点表示一个空间范围。表1给出的是k-d树每个节点中主要包含的数据结构。
域名 数据类型 描述
Node-data 数据矢量 数据集中某个数据点,是n维矢量(这里也就是k维)
Range 空间矢量 该节点所代表的空间范围
split 整数 垂直于分割超平面的方向轴序号
Left k-d树 由位于该节点分割超平面左子空间内所有数据点所构成的k-d树
Right k-d树 由位于该节点分割超平面右子空间内所有数据点所构成的k-d树
parent k-d树 父节点
  表1  k-d树中每个节点的数据类型

以上述举的实例来看,过程如下:

  由于此例简单,数据维度只有2维,所以可以简单地给x,y两个方向轴编号为0,1,也即split={0,1}。

  (1)确定split域的首先该取的值。分别计算x,y方向上数据的方差得知x方向上的方差最大,所以split域值首先取0,也就是x轴方向;

  (2)确定Node-data的域值。根据x轴方向的值2,5,9,4,8,7排序选出中值为7,所以Node-data = (7,2)。这样,该节点的分割超平面就是通过(7,2)并垂直于split = 0(x轴)的直线x = 7;

  (3)确定左子空间和右子空间。分割超平面x = 7将整个空间分为两部分,如图2所示。x < =  7的部分为左子空间,包含3个节点{(2,3),(5,4),(4,7)};另一部分为右子空间,包含2个节点{(9,6),(8,1)}。


如算法所述,k-d树的构建是一个递归的过程。然后对左子空间和右子空间内的数据重复根节点的过程就可以得到下一级子节点(5,4)和(9,6)(也就是左右子空间的'根'节点),同时将空间和数据集进一步细分。如此反复直到空间中只包含一个数据点,如图1所示。最后生成的k-d树如图3所示。

JST KD树实现原理
com.vividsolutions.jts.index.kdtree.KdTree
An implementation of a 2 - D KD- Tree. KD -trees provide fast range searching on point data.
This implementation supports detecting and snapping points which are closer than a given
tolerance value. If the same point (up to tolerance) is inserted more than once a new node is
not created but the count of the existing node is incremented.
一个实现了二维的KD-tree。 KD-树提供快速搜索范围点上的数据。
eg:
public class KDTreeDemo {
	
	private KdTree kdTree = new KdTree();
	
	public void builKDTree(){
		Coordinate p1 = new Coordinate(0,0);
		Coordinate p2 = new Coordinate(1,1);
		Coordinate p3 = new Coordinate(2,2);
		Coordinate p4 = new Coordinate(3,3);
		Coordinate p5 = new Coordinate(4,4);
		Coordinate p6 = new Coordinate(5,5);
		kdTree.insert(p1, "first");
		kdTree.insert(p2, "second");
		kdTree.insert(p3, "third");
		kdTree.insert(p4, "fourth");
		kdTree.insert(p5, "Fifth");
		kdTree.insert(p6, "Sixth");
	}

	
	public void query(Envelope enve){
		List<KdNode> StrList = kdTree.query(enve);
		for(KdNode node:StrList) {
			System.out.println(node.getData());
		}
	}

	public static void main(String[] args) {
		KDTreeDemo kd = new KDTreeDemo();
		kd.builKDTree();
		Envelope enve = new Envelope(-1,2,-1,2);
		kd.query(enve);
		System.out.println("------分割线--------");
		Envelope enve1 = new Envelope(2, 4, 2, 4);
		kd.query(enve1);
	}
}

输出结果:
first
second
third
------分割线--------
third
fourth
Fifth
(3)、R-Tree 索引
R树是一棵平衡树。树上有两类结点:叶子结点和非叶子结点。每一个结点由若干个索引项构成。对于叶子结点,索引项形如(Index,Obj_ID)。其中,Index表示包围空间数据对象的最小外接矩形MBR,Obj_ID标识一个空间数据对象。对于一个非叶子结点,它的索引项形如(Index,Child_Pointer)。 Child_Pointer 指向该结点的子结点。Index仍指一个矩形区域,该矩形区域包围了子结点上所有索引项MBR的最小矩形区域。
搜索算法:
记R树的根节点记为T。搜索算法要求输入一个搜索矩形S,输出所有与S相交的索引记录。
步骤S1:搜索子树——如果T不是一个叶节点,则检查其中的每一个条目E,如果EI与S相交,则对Ep所指向的那个子树根节点调用Search算法。这里注意,Search算法接收的输入为一个根节点,所以在描述算法的时候,原文称对子树根节点调用Search算法,而不是对子树调用Search算法。
步骤S2:搜索叶节点——如果T是一个叶节点,则检查其中的每个条目E,如果EI与S相交,则E就是需要返回的检索结果之一。
JTS R-Tree 树实现原理
分两种树:STRtree和SIRtree
com.vividsolutions.jts.index.strtree.STRtree
A query-only R-tree created using the Sort-Tile-Recursive (STR) algorithm. For two-dimensional spatial data.The STR packed R-tree is simple to implement and maximizes space utilization; 
查询指R树采用排序 - 压缩 - 递归(STR)算法创建的。为二维空间data.The STR​​压缩的R-树是实现简单并且最大化空间利用率
eg:
public class STRtreeDemo {

	private STRtree strTree = new STRtree();
	
	private GeometryFactory gf = new GeometryFactory();
	
	public LineString createLineByWKT(String lineStr)throws ParseException{
		WKTReader reader = new WKTReader(gf);
		LineString line = (LineString) reader.read(lineStr);
		return line;
	}
	
	public void buildStrTree() throws ParseException{
		strTree.insert(createLineByWKT("LineString(1 1, 2 2,3 0,6 10)").getEnvelopeInternal(), "first");
		strTree.insert(createLineByWKT("LineString(0 0, 2 0)").getEnvelopeInternal(), "second");
		strTree.insert(createLineByWKT("LineString(-1 1, 2 0)").getEnvelopeInternal(), "third");
		strTree.insert(createLineByWKT("LineString(-1 -1, -2 -2)").getEnvelopeInternal(), "fourth");
	}

	
	public void query(Envelope enve){
		List<String> StrList = strTree.query(enve);
		for(String str:StrList) {
			System.out.println(str);
		}
	}
	
	public static void main(String[] args) throws ParseException {
		STRtreeDemo qd = new STRtreeDemo();
		qd.buildStrTree();
		Envelope enve = new Envelope(1, 1.5, 1, 1.5);
		qd.query(enve);
		System.out.println("------分割线--------");
		Envelope enve1 = new Envelope(0.5, 0.5, 0.5, -0.5);
		qd.query(enve1);
	}
}
输出结果:
third
first
------分割线--------
second
third

com.vividsolutions.jts.index.strtree.SIRtree
One-dimensional version of an STR-packed R-tree. SIR stands for
"Sort-Interval-Recursive". 
一维版本的STR-压缩的R-树







  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值