1、背景
在最近的工作当中,需要在空间中找到指定范围的目标点。由此想到了R树索引,利用R树索引进行高性能查询,将返回指定范围内的经纬度坐标点。大致的方向已明确,便开始寻找相关实现。通过在互联网上查找资料,已经有开源的JTS工具包可进行相关的索引构建工作,并提供查询功能。本文由此简单的说明如何利用jts进行相关操作。
2、相关代码
2.1 索引的构建,具体代码如下:
STRtree tree=new STRtree();
GeometryFactory factory=new GeometryFactory();
com.vividsolutions.jts.geom.Point point=factory.createPoint(new Coordinate(112.971585, 28.265007));//长沙
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(113.040862, 28.192062));//芙蓉区
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(112.902882, 28.223639));//岳麓区
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(113.040862, 28.142129));//雨花区
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(111.491465, 27.269792));//邵阳市
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(109.982886, 27.630889));//怀化市
tree.insert(point.getEnvelopeInternal(), point);
tree.build();
System.out.println("R树索引创建成功!");
通过将各坐标点添加到索引中,最后调用build方法即可完成索引的构建。
2.2 基于R树索引的查询
根据传入的点创建查询范围
public static Geometry generateSearchGeo(double left_top_x,double left_top_y,double right_bottom_x,double right_bottom_y){
Coordinate[] coors=new Coordinate[5];
coors[0]=new Coordinate(left_top_x, left_top_y);
coors[1]=new Coordinate(right_bottom_x, left_top_y);
coors[2]=new Coordinate(left_top_x, right_bottom_y);
coors[3]=new Coordinate(right_bottom_x, right_bottom_y);
coors[4]=new Coordinate(left_top_x, left_top_y);
LinearRing ring = new LinearRing(new CoordinateArraySequence(coors), new
GeometryFactory());
return ring;
}
在这里需要注意的是,由于构建的是完整点,所以一定要保证起始点在一起即闭合。所以,coors[4] 的值和coors[0]一致。否则会报错。
调用R树索引进行查询。
/**
* R树查询
* param tree
* @param searchGeo
* @return
*/
@SuppressWarnings("rawtypes")
public static List<Point> query(STRtree tree,Geometry searchGeo){
List <Point> result=new ArrayList<Point>();
List list=tree.query(searchGeo.getEnvelopeInternal());
for (Object object : list) {
Point point = (Point)object;
result.add(point);
}
return result;
}
3、写在后面
3.1 本文使用的资源jar包为:
<dependencies>
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts-core</artifactId>
<version>1.14.0</version>
</dependency>
</dependencies>
3.2 感谢KingWang_WHU提供的例子程序,解决了一些基础性的问题。他的博客中有一些关于R树的科普及相关说明。详情可参考【JTS】利用JTS生成R树索引。
3.3 完整的代码如下:
package nudt.dbrg.jtsdemo.test;
import java.util.ArrayList;
import java.util.List;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
import com.vividsolutions.jts.index.strtree.STRtree;
public class TestMain3 {
/**
* R树查询
* @param tree
* @param searchGeo
* @return
*/
@SuppressWarnings("rawtypes")
public static List<Point> query(STRtree tree,Geometry searchGeo){
List <Point> result=new ArrayList<Point>();
List list=tree.query(searchGeo.getEnvelopeInternal());
for (Object object : list) {
Point point = (Point)object;
result.add(point);
}
return result;
}
public static Geometry generateSearchGeo(double left_top_x,double left_top_y,double right_bottom_x,double right_bottom_y){
Coordinate[] coors=new Coordinate[5];
coors[0]=new Coordinate(left_top_x, left_top_y);
coors[1]=new Coordinate(right_bottom_x, left_top_y);
coors[2]=new Coordinate(left_top_x, right_bottom_y);
coors[3]=new Coordinate(right_bottom_x, right_bottom_y);
coors[4]=new Coordinate(left_top_x, left_top_y);
LinearRing ring = new LinearRing(new CoordinateArraySequence(coors), new GeometryFactory());
return ring;
}
public static void main(String[] args) {
STRtree tree=new STRtree();
GeometryFactory factory=new GeometryFactory();
com.vividsolutions.jts.geom.Point point=factory.createPoint(new Coordinate(112.971585, 28.265007));//长沙
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(113.040862, 28.192062));//芙蓉区
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(112.902882, 28.223639));//岳麓区
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(113.040862, 28.142129));//雨花区
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(111.491465, 27.269792));//邵阳市
tree.insert(point.getEnvelopeInternal(), point);
point=factory.createPoint(new Coordinate(109.982886, 27.630889));//怀化市
tree.insert(point.getEnvelopeInternal(), point);
tree.build();
System.out.println("R树索引创建成功!");
Geometry searchGeo = TestMain3.generateSearchGeo(112.764903, 28.18409, 113.484697,28.264261);
List<Point> list = TestMain3.query(tree, searchGeo);
for (Point p : list) {
System.out.println("p==>" + p);
System.out.println(p.getX() + "\t" + p.getY());
}
System.out.println("找到数据条数为==> " + list.size());
}
}