Android设备中加载矢量数据的方法,对于在Android中存储矢量数据可以通过Sqlite数据库或以Sqlite数据库扩展的Spatialite空间数据库实现。
1.基于Sqlite数据库
矢量数据存储实际上将Geomentry转成json字符串后存储到数据库中,从数据库读取数据则是将json字符串转成Geomentry。这两个转换的实现借助GeometryEngine类的geometryToJson()和jsonToGeometry()方法。这种方法的不足就是不能直接将Shapefile数据存储到数据库中,也只能对数据库中的数据属性查询,不能对数据库进行空间查询。
2.基于Spatialite空间数据库
Spatialite空间数据库实际上是对salite数据库的扩展,使其能够支持空间数据。可以通过Spalite-gui工具将shapefile数据导入到spatialite数据库中。那如何将数据库中的Geometry读取出来并显示大地图中呢?数据库查询语句可以将Geometry转成OGC标准的wkt(一种文本标记语言)字符串形式,wkt格式如:POINT(0 0),LINESTRING(0 0,1 1,1 2),POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1 ,2 1, 2 2, 1 2, 1 1))通过查询语句“SELECT AsText(Geometry) from table"将Geometry读出来,然后就是讲Wkt字符串转成Geometry了。方法如下:
public static Geometry WKTToGeometry(String wkt){
Geometry geo = null;
if(wkt ==null || wkt ==""){
return null;
}
String headStr = wkt.substring(0, wkt.indexOf("("));
String temp = wkt.substring(wkt.indexOf("(")+1, wkt.lastIndexOf(")"));
if(headStr.equals("POINT")){
String[] values = temp.split(" ");
geo = new Point(Double.valueOf(values[0]),Double.valueOf(values[1]));
}else if(headStr.equals("LINESTRING") || headStr.equals("POLYGON")){
geo = parseWKT(temp,headStr);
}else if(headStr.equals("Envelope")){
String[] extents = temp.split(",");
geo = new Envelope(Double.valueOf(extents[0]),Double.valueOf(extents[1]),Double.valueOf(extents[2]),Double.valueOf(extents[3]));
}else if(headStr.equals("MultiPoint")){
}else{
return null;
}
return geo;
}
private static Geometry parseWKT(String multipath,String type){
String subMultipath = multipath.substring(1, multipath.length()-1);
String[] paths;
if(subMultipath.indexOf("), (") >=0 ){
paths = subMultipath.split("\\), 多个几何对象的字符串
}else{
paths = new String[]{subMultipath};
}
Point startPoint = null;
MultiPath path = null ;
if(type.equals("LINESTRING")){
path = new Polyline();
}else{
path = new Polygon();
}
for(int i=0;i<paths.length;i++){
String[] points = paths[i].split(",");
startPoint = null;
for(int j=0;j<points.length;j++){
String[] pointStr = points[j].trim().split(" ");
if(startPoint ==null){
startPoint = new Point(Double.valueOf(pointStr[0]),Double.valueOf(pointStr[1]));
path.startPath(startPoint);
}else{
path.lineTo(new Point(Double.valueOf(pointStr[0]),Double.valueOf(pointStr[1])));
}
}
}
return path;
}
转成Geometry后在GraphicsLayer中以Graphic的形式显示即可。
那么将Geometry存储到数据库中则是相反的过程,实际上存储的是wkt字符串形式,在数据库中以Blob格式存储,通过:"insert into table fiels(Geometry) VALUES(AsText(Geometry))) "插入语句存到数据库中。这个数据库支持sql语句的空间操作,通过Contains,Intersect,等方法操作,如:
"SELECT * where Contains(GeomFromText(wkt'),Geometry)",查询语句获得是位于GeomFromText(wkt')内的记录。如果建立了空间索引,数据库的存取速度会提升很多。
最后你可能问数据直接存储在数据库中是否安全,其实通过修改数据库源码是可以设置用户名和密码访问的,然后再编译成功。这样数据库就通过用户名和密码才能访问。