使用Geotools中的Shapefile plugin支持小数位精确控制

1背景

       当前Java语言实现的Shapefile读写库中,Geotools中的shapefile插件是使用最多的开源实现,实现比较全面,成熟。但是可能为了与Geotools的核心概念一致,其对小数位DecimalCount的控制支持没有在适配层实现,只是默认了小数位的位数(其底层还是支持小数位的控制的)。

    改进有几种方式,其一是参考Shapefile插件自己实现一个独立的干净的Shapefile类库,但是又有不少细节需要考虑;其二是完全实现一套新的Shapefile库,但是意义有多大呢?所以改进的方式就是简单的利用目前Geotools的扩展机制,修改一下适配层,解决一下精确控制小数位的问题。

2解决方法

       通过对Shapefile源代码的分析,发现控制DecimalCount的位置有两处:

    第一处:org.geotools.data.shapefile.ShapefileDataStore类中createDbaseHeader方法,修改对Number类型的适配,通过AttributeDescriptor的getUserData()数据来获取对decimalCount属性的设定。

    修改如下:

      

else if (Number.class.isAssignableFrom(colType)) {

                int l = Math.min(fieldLen, 33);

                int d = Math.max(l - 2, 0);

                //通过自定义属性支持小数点位数,decimalCount

                Map user_data = type.getUserData();

                if (user_data != null) {

                    try {

                        d = Integer.parseInt(user_data.getOrDefault("decimalCount", d).toString());

                    } catch (Exception ex) {

                        //

                    }

                }

header.addColumn(colName, 'N', l, d);

}

    第二处:org.geotools.data.shapefile.ShapefileFeatureSource类的readAttributes方法。

    其是读取DBF文件,重建AttributeDescriptor,原来的实现没有读取DecimalCount信息,这里加上,同样加入到UserData之中。

    实现如下:

int decimalCount=header.getFieldDecimalCount(i);

if(decimalCount>0){

  build.addUserData("decimalCount", decimalCount);

 }

 

    通过修改上诉两处,重新编译Shapefile插件,就可以支持对小数位的精确控制了。

3使用方法

    1)引入Shapefile以及依赖的库,这里使用Maven命令可以直接提取依赖库

    Shapefile依赖库可以参考上图。

使用Geotools中的Shapefile plugin支持小数位精确控制_第1张图片

   

    2)在定义属性表的时候使用UserData来存放需要设定的decimalCount信息。

    示例如下:

protected SimpleFeatureType createFeatureType() {

 

        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();

        builder.setName("buildiong");

        builder.setCRS(DefaultGeographicCRS.WGS84);

 

        // add attributes in order

        builder.add("the_geom", Point.class);

        builder.length(9).add("ID", Integer.class);

        builder.length(150).add("NAME", String.class);

        builder.length(10).userData("decimalCount",6).add("X", Double.class);

        builder.length(10).userData("decimalCount",6).add("Y", Double.class);

        final SimpleFeatureType BUILDING = builder.buildFeatureType();

 

        return BUILDING;

    }

 

    上面例子通过SimpleFeatureTypeBuilder的userData("decimalCount",6)来设定小数位为6位。

   

4附注,对长度与小数位的理解

       DBF使用的是字符串来存储数值类型,其长度的概念是字符数概念,而且所有字段都是定长概念。

    如果不够长度,则是先补充小数位(用零补充),然后补充整数位(用空格)补充。

    在QGIS里面,显示带小数位的属性表的时候,其长度显示去掉了小数点,就是说会显示长度比我们的定义少一。如我们定义(10,6)在QGIS里面会显示长度为9,小数位为6。

    通常我们定义WGS84坐标来讲,若要保留小数点后6位,则定义N(10,6)就可以,因为整数位不会超过三位。


5编译后的插件以及依赖库,可以从下面的链接下载:

点击打开链接





你可能感兴趣的:(地图技术)