一、 桌面工具 spatialite_gui
spatialite_gui是查看.sqlite文件的桌面工具,当然也可以查看.db文件,毕竟Spatialite是在SQLite的基础上拓展出存储空间图形的能力。
工具下载地址:http://www.gaia-gis.it/gaia-sins/index.html
如图输入查询语句后执行右侧的执行按钮就能看到结果。
二、 .sqlite文件中关键的两张表
vector_layers
示例查询语句:SELECT * FROM 'vector_layers' WHERE table_name='country';
会返回条件中表所对应的几何图形类型,坐标系,空间索引是否可用等。
SpatialIndex
空间索引表,查询条件也需要指定表名,我在使用时还使用了search_frame
,对应的值传入Geometry对象,需要使用Spatialite提供的方法来构造语句,方法文档地址:http://www.gaia-gis.it/gaia-sins/spatialite-sql-5.0.1.html
search_frame
的意思就是以传入图形为覆盖范围,查询返回的就是这个图形在所查询的表中所覆盖的图形所对应的行号集合。经测试不论传入什么图形,都会按这个图形的外接矩形来作为覆盖范围。
示例查询语句:SELECT rowid FROM 'SpatialIndex' WHERE f_table_name='DB=main.counties' AND search_frame=ST_Transform(BuildMbr(14.15765827813982, 42.36755511067014, 14.15765827813982, 42.36755511067014, 4326), 23032);
这条查询语句中就用到了ST_Transform
和BuildMbr
两个Spatialite方法。接下来在第三点会介绍常用的一些方法。
三、 常用Spatialite方法介绍
1. ST_Transform
字面意思理解,将一个东西转换为另一个东西,实际是将传入的Geometry转换为和所查询表相同的坐标系的方法。
从ST_Transform(BuildMbr(14.15765827813982, 42.36755511067014, 14.15765827813982, 42.36755511067014, 4326), 23032)
中可以看到BuildMbr
构造的是4236坐标系的一个Geometry,ST_Transform
将它转换为了23032的坐标系。
2. BuildMbr
构造一个矩形的Geometry,BuildMbr(14.15765827813982, 42.36755511067014, 14.15765827813982, 42.36755511067014, 4326)
中的五个参数分别为最小经度、最小纬度、最大经度、最大纬度、坐标系。
示例的最小经度和最大经度相同,最小纬度和最大纬度相同,其实本意是想构造一个点的,其实构造点也可以用MakePoint
方法。
3. MakePoint
构造一个点的Geomtry,MakePoint(116.0, 39.0, 4326)
,三个参数分别为经度、纬度、坐标系。
4. MakeLine
构造一个线的Geomtry,MakeLine(MakePoint(116.0, 39.0, 4326),MakePoint(116.5, 39.5, 4326))
,目前测试只知道如何将两个点构造为线,至于是否可以继续用逗号往后面传点就未知了。构造点线面其实可以统一用GeomFromText
方法来做,在后面会写到。
5. MakePolygon
这个方法比较复杂,可能要将MakeLine
的Geometry作为第一参数,而且后面可以继续传多个MakeLine
的Geometry来作为Hole,未实验但这个方法是存在的,切记点集要封闭。它也是可以用GeomFromText
方法来代替。
6. GeomFromText
GeomFromText 需要两个参数,一个图形文本,一个坐标系,关键是图形文本的构建,需要用到jts-1.12.jar
中的WKTWriter,如下为一段构造面的代码:
WKTWriter wktWriter = new WKTWriter();
Coordinate[] polyCoords = new Coordinate[polyPoints.size() + 1];
for (int i = 0; i < polyPoints.size(); i++) {
LatLng ll = polyPoints.get(i);
polyCoords[i] = new Coordinate(ll.getLongitude(), ll.getLatitude());
}
polyCoords[polyPoints.size()] = polyCoords[0];
LinearRing shell = geometryFactory.createLinearRing(polyCoords);
Polygon polygon = geometryFactory.createPolygon(shell, null);
String geom_frame = wktWriter.write(polygon);
// 一定要将geom_frame用单引号包裹,否则查询语句会报错
return "GeomFromText('" + geom_frame + "',4326)";
完整输出示例:GeomFromText('POLYGON ((115.9388801661513 39.02147477028444, 116.08199368009787 39.052075611608814, 116.08486803004166 38.95648222420448, 115.9388801661513 39.02147477028444))', 4326)
7. ST_Intersects
这个方法比较特殊,返回两个Geometry是否有交集,返回值=1就是有交集,在查询语句中的应用如下
SELECT ogc_fid,AsBinary(ST_Transform(geometry, 4326)) AS geometry FROM 'country' A WHERE ST_Intersects(GeomFromText(ST_AsText(A.geometry)), GeomFromText('POLYGON ((115.9388801661513 39.02147477028444, 116.08199368009787 39.052075611608814, 116.08486803004166 38.95648222420448, 115.9388801661513 39.02147477028444))')) = 1;
可以看到ST_Intersects的参数是两个Geometry,第一个是从表中查到的数据并用A来代替后取出geometry转化出来的,第二个是用点集构造的。
8. AsBinary
将Geometry变为二进制输出。
9. SimplifyPreserveTopology
如果Geomtry太过复杂,存在数据库中的Blob大小过大,那么在用cursor.getBlob()
获取byte[]时会直接抛异常,那么可以在查询语句中先对Geomtry进行简化。
SimplifyPreserveTopology(geometry, 1.0)
便是语句,第一个参数是图形存储在表中的字段名,第二个参数决定精简的粗略程度,越大返回的图形越简单,并且也看图形的复杂程度和坐标系。