OsmDroid对于矢量数据的加载(1)

OsmDroid是一款安卓手机上的地图控件,包含了多种的基础图层:覆盖层、点图层(可包含多点)、线(只能包含单条Polyline)、面(只能包含单个Polygon)、底图图层。作为通用型的地图控件,其功能是非常强大的,但是面向于专业的Gis行业使用,难免有些许缺陷。本文主要讲解在OsmDroid上实现对于矢量数据的加载。

矢量数据的存在形式包含多种,常见的有服务发布形式(WMS、WFS)、本地文件形式(Shapefile)以及数据库存储形式。由于ArcGis在数据处理以及属性信息录入时其编码是电脑的默认编码(GBK),QGis可选择编码格式。但是数据处理人员不会在意这些在编码时才会产生的细节,所以一般都不会刻意的去生产UTF-8的编码格式数据。

为什么这里会说到编码的问题呢?OsmDroid现在包含的图层中只有WMS服务图层是可用于加载矢量数据的(还是测试中的哦),所以在完成加载的前提下还需要自己进行矢量数据的读取。

当矢量数据在安卓机上的存在形式为shapefile时,这个需要使用到gdal对其进行解析读取。

当矢量数据在安卓机或者在服务器上的存在形式为数据库文件时,这个时候需要使用基于sqlite的空间数据库插件进行读取。本次的数据存储环境为Spatialite.通过QGis创建Spatialite数据库,然后将矢量数据上传到数据库中。

下面是关于Spatialite数据库的操作类(截取了部分代码出来,文章最后又代码的共享连接):

public class SpatialiteHelper {
    /**
     * 数据库对象
     */
    private SQLiteDatabase sqLiteDatabase;

    public SpatialiteHelper(String path) {

        sqLiteDatabase = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);

    }
 //region 空间查询(涉及空间数据--需要将geom字段进行wkt转换--非空间查询建议不用此类查询方法,会降低效率)


    public  boolean run(String sql){
        try{
            sqLiteDatabase.execSQL(sql);
            return  true;
        }catch (Exception e){

            return  false;
        }



    }

    public boolean deleteGeom(String tableName, String wkt, String geometry) {

        try {
            String sql = String.format("Delete  FROM %s WHERE ST_astext(%s)='%s'", tableName, geometry, wkt);

            sqLiteDatabase.execSQL(sql);
            return true;
        } catch (Exception e) {

            return false;
        }


    }


    /**
     * m模糊查询--关键字查询
     *
     * @param tableName 表名
     * @param keyWord   关键字
     * @return the sq lite cursor models
     */
    public SQLiteCursorModels fuzzyQuery(String tableName, String keyWord) {

        String cols = String.format("PRAGMA  table_info([%s])", tableName);

        SQLiteCursorModels colsInfo = Query(cols);

//        String sql=String.format("select * from %s where ",tableName);

        String sql = String.format(" Select a.*,ASTEXT(b.geom) as geometry from %s a , %s b where a.id=b.id and(", tableName, tableName);

        for (SQLiteCursorModel model : colsInfo.getEntrys()
                ) {
            String colName = model.getColumns().get("name");

            sql = String.format("%s a.%s like '%s%s%s' or", sql, colName, "%",keyWord,"%");

        }

        sql = sql.substring(0, sql.length() - 2);

        sql = sql + ")";
        return Query(sql);

    }

    /**
     * 对指定表名的表格进行空间查询
     *
     * @param tableName 表名
     * @return the array list
     */
    public SQLiteCursorModels GeomQueryByTableName(String tableName) {

        String sql = String.format("Select a.*,ASTEXT(b.geom) as geometry from %s a , %s b where a.id=b.id", tableName, tableName);

        return GeomQuery(sql);
    }

    /**
     * 获取指定表格的指定字段(自动添加geom字段)
     *
     * @param tableName 表名
     * @param fields    字段
     * @return the array list
     */
    public SQLiteCursorModels GeomQueryFiledsByTableName(String tableName, String[] fields) {

        String sql = "SELECT ";

        for (int i = 0; i < fields.length; i++) {

            sql = String.format("%s %s,", new Object[]{sql, fields[i]});

        }

        sql = String.format("%s ASTEXT(%s) as geometry from %s ", new Object[]{sql, "geom", tableName});

        return GeomQuery(sql);
    }

    /**
     * 空间查询
     *
     * @param tableName 表名
     * @param wkt       the wkt
     * @param srid      the srid
     * @param fields    字段集合
     * @return the array list
     */
    public SQLiteCursorModels QueryIntersectsByGemetry(String tableName, String wkt, int srid, String[] fields) {

        String sql = "SELECT ";

        for (int i = 0; i < fields.length; i++) {

            sql = String.format("%s %s,", new Object[]{sql, fields[i]});

        }

        String createGeometry = String.format(" ST_GeomFromText('%s',%s)", wkt, srid);

        sql = String.format("%s ASTEXT(%s) as geometry from %s where ST_Intersects(%s,%s) = 1 ", new Object[]{sql, "geom", tableName, "geom", createGeometry});

        return GeomQuery(sql);

    }

    /**
     * 获取指定表格的指定字段(自动添加geom字段)
     *
     * @param tableName    表名
     * @param field        字段
     * @param isClearEmpty 是否清除空值结果
     * @return the array list
     */
    public SQLiteCursorModels GeomQueryFiledsByTableName(String tableName, String field, boolean isClearEmpty) {

        String sql = String.format("SELECT  %s ,  ASTEXT(%s) as geometry from %s", field, "geom", tableName);

        if (isClearEmpty) {
            sql = String.format("%s where %s<>''", sql, field, field);

        }

        return GeomQuery(sql);
    }

    /**
     * 单属性查询(适用于属性值类型为文本)
     *
     * @param tableName 表名
     * @param field     字段名称
     * @param value     属性
     * @return the array list
     */
    public SQLiteCursorModels GeomQueryBySingleAttribute(String tableName, String field, String value) {

        String sql = String.format("Select a.*,ASTEXT(b.geom) as geometry from %s a , %s b Where a.%s='%s' and a.id=b.id", tableName, tableName, field, value);

        return GeomQuery(sql);
    }

    /**
     * 单属性查询(适用于属性值类型为整形)
     *
     * @param tableName 表名
     * @param field     字段名称
     * @param value     属性
     * @return the array list
     */
    public SQLiteCursorModels GeomQueryBySingleAttribute(String tableName, String field, int value) {

        String sql = String.format("Select a.*,ASTEXT(b.geom) as geometry from %s a , %s b Where %s=%s", tableName, tableName, field, String.valueOf(value));

        return GeomQuery(sql);
    }

    /**
     * 单属性查询(适用于属性值类型为双精度)
     *
     * @param tableName 表名
     * @param field     字段名称
     * @param value     属性
     * @return the array list
     */
    public SQLiteCursorModels GeomQueryBySingleAttribute(String tableName, String field, double value) {

        String sql = String.format("Select a.*,ASTEXT(b.geom) as geometry from %s a , %s b Where %s=%s", tableName, tableName, field, String.valueOf(value));

        return GeomQuery(sql);
    }


    /**
     * 单属性查询(适用于属性值类型为单精度)
     *
     * @param tableName 表名
     * @param field     字段名称
     * @param value     属性
     * @return the array list
     */
    public SQLiteCursorModels GeomQueryBySingleAttribute(String tableName, String field, float value) {

        String sql = String.format("Select a.*,ASTEXT(b.geom) as geometry from %s a , %s b Where %s=%s", tableName, tableName, field, String.valueOf(value));

        return GeomQuery(sql);
    }

    /**
     * 查询相交的要素Query intersects by gemetry array list.
     *
     * @param tableName 表格/图层名称
     * @param wkt       目标图形的wkt
     * @param srid      坐标系代码
     * @return the array list
     */
    public SQLiteCursorModels QueryIntersectsByGemetry(String tableName, String wkt, int srid) {

        String createGeometry = String.format(" ST_GeomFromText('%s',%s)", wkt, srid);

        String sql = String.format("Select a.*,ASTEXT(b.geom) as geometry from %s a , %s b Where ST_Intersects(a.geom,%s) = 1 and ST_Intersects(b.geom,%s) = 1 ", tableName, tableName, createGeometry, createGeometry);

        return GeomQuery(sql);

    }

    public SQLiteCursorModels GeomQueryIntersectAndContain(String tableName, String wkt, int srid) {
        String createGeometry = String.format(" ST_GeomFromText('%s',%s)", wkt, srid);

        String sql = String.format("Select a.*,ASTEXT(b.geom) as geometry from %s a , %s b Where a.id=b.id and( ST_Intersects(a.geom,%s) = 1 or  ST_Contains(%s,a.geom)=1)", tableName, tableName, createGeometry, createGeometry, createGeometry);

        return GeomQuery(sql);

    }

    /**
     * 空间查询
     *
     * @param sql 查询语句
     * @return the array list
     */
    private SQLiteCursorModels GeomQuery(String sql) {
        Cursor cursor = sqLiteDatabase.rawQuery(sql, null);

        SQLiteCursorModels arrayList = new SQLiteCursorModels();

        if (cursor != null && cursor.moveToFirst()) {

            arrayList = ConvertGeomCursorToList(cursor);

        }
        return arrayList;
    }

    /**
     * 将重置位置的游标传入,将会自动遍历游标到最后,并转换为序列
     *
     * @param cursor
     * @return
     */
    protected SQLiteCursorModels ConvertGeomCursorToList(Cursor cursor) {

        SQLiteCursorModels result = new SQLiteCursorModels();

        while (!cursor.isAfterLast()) {

            SQLiteCursorModel tempModel = new SQLiteCursorModel(cursor);

            result.add(tempModel);

            cursor.moveToNext();
        }

        return result;
    }
    //endregion

    /**
     * 关闭数据库连接
     */
    public void CloseConnection() {
        sqLiteDatabase.close();
    }


}

通过这个空间数据库的操作类,我们能获取到所有我们想获取到的数据,并且以SQLiteCursorModel这个类进行使用。下面就是对数据的加载(也就是绘制了)。当前以Polyline这种地理要素作为后面的讲解对象。

在文章的开头我们提到了OSMDroid对于线段的绘制是有一个继承于Overlay的Polyline类,但是这个类只能绘制出一条线,也就是一个覆盖图层只能绘制一个地理对象(Feature),而不是我们以为的FeatureLayer那种概念了。对于如何实现一个Layer加载多个地理要素目标,当前有两种解决方案:1.做一个管理类,在从数据库中获取到一个图层的所有要素数据后,将每个数据创建为OSM中的Polyline图层对象,然后我们自己创建一个类,它也继承与Overlay,同时有个关于Polyline的数组进行要素的存储,这样能够实现一个意义上类似于FeatureLayer的图层效果;2.做一个新的图层,它就是FeatureLayer.

此文讲述的是第一种方案,第二种方案将在下篇文章进行讲述。主要包含三个类来实现Gis上的要素概念:FeatureOverlaySet、FeatureOverlay、FeatureLayerOverlay.部分源码如下:

public class FeatureLayerOverlay {

    private FeatureOverlaySet featureOverlaySet;

    private String layerName;

    private String sourceName;

    private boolean isVisible = true;

    private List<Overlay> featureOverlay = new ArrayList<>();

    public FeatureOverlaySet getFeatureOverlaySet() {
        return featureOverlaySet;
    }

    public String getLayerName() {
        return layerName;
    }

    public String getSourceName() {
        return sourceName;
    }

    public boolean isVisible() {
        return isVisible;
    }

    public void setVisible(boolean visible) {
        isVisible = visible;

        switch (featureOverlaySet.getGeometryType()) {
            case "MultiLineString":

                for (Overlay line : featureOverlay
                        ) {
                    PolylineOverlay polylineOverlay = (PolylineOverlay) line;

                    polylineOverlay.setVisible(visible);
                }

                break;
            case "MultiPolygon":

                for (Overlay polygon : featureOverlay
                        ) {
                    PolygonOverlay polygonOverlay = (PolygonOverlay) polygon;

                    polygonOverlay.setVisible(visible);
                }

                break;
            default:

                break;

        }
    }

    public List<Overlay> getFeatureOverlay() {
        return featureOverlay;
    }

    public FeatureLayerOverlay(FeatureOverlaySet featureOverlaySet, String layerName, String sourceName) {

        this.featureOverlaySet = featureOverlaySet;

        this.layerName = layerName;

        this.sourceName = sourceName;

        this.featureOverlaySet.setLayer(this);

    }


}

传送门:https://github.com/Spe1993/SpeRemarks

 

发布了16 篇原创文章 · 获赞 2 · 访问量 3509

猜你喜欢

转载自blog.csdn.net/weixin_41012454/article/details/88320850
今日推荐