欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

程序员文章站 2022-04-24 20:05:40
一、项目目录结构树 二、项目启动 三、往指定的shp文件里写内容 (1) json数据【Post】 (2)接口调用 (3)QGIS查看,验证数据有效性 四、读取指定shp文件,并显示内容 (1)接口调用 (2)QGIS显示北京故宫【shp文件在项目中的static文件夹下】 五、将指定的shp文件转 ......

一、项目目录结构树

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

 

二、项目启动

 

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

 

 

三、往指定的shp文件里写内容

 

 

(1) json数据【post】

 

 

{
    "name":"test",
    "path":"c:/test",
    "geom":"multipolygon(((101.870371 25.19228,101.873633 25.188183,101.880564 25.184416,101.886808 25.186028,101.892043 25.189969,101.896592 25.190163,101.903716 25.190785,101.905454 25.193464,101.899897 25.196202,101.894146 25.197911,101.891657 25.19826,101.886078 25.197658,101.884211145538 25.2007060137013,101.88172564506 25.1949712942389,101.87874 25.199619,101.874641 25.200998,101.868547 25.202415,101.863741 25.202415,101.85887 25.202842,101.854557 25.202182,101.852604 25.199736,101.852282 25.19628,101.854492 25.194183,101.855608 25.192668,101.863698 25.192105,101.870371 25.19228)))",
    "id":1001,
    "des":"湖泊水面"
        
}

 

 

(2)接口调用

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

(3)qgis查看,验证数据有效性

 

 

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

 

 

四、读取指定shp文件,并显示内容

 

 

 

(1)接口调用

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

(2)qgis显示北京故宫【shp文件在项目中的static文件夹下】

 

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

 

五、将指定的shp文件转成image文件或流

 

 

(1) 接口调用  === 转image【png】文件

 

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

c盘下查看

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

(2) 接口调用  === 转image流,输出到客户端

 

 

Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

 

 

 

 

 

六、核心工具类【shptools】

 

 

 

package com.appleyk.geotools;

import com.appleyk.io.stringtokenreader;
import com.appleyk.pojos.shpdatas;
import com.appleyk.pojos.shpinfo;
import com.appleyk.result.responsemessage;
import com.appleyk.result.responseresult;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.geom.point;
import com.vividsolutions.jts.geom.polygon;
import org.geotools.data.*;
import org.geotools.data.shapefile.shapefiledatastore;
import org.geotools.data.shapefile.shapefiledatastorefactory;
import org.geotools.data.simple.simplefeaturesource;
import org.geotools.feature.featurecollection;
import org.geotools.feature.featureiterator;
import org.geotools.feature.simple.simplefeaturetypebuilder;
import org.geotools.geometry.jts.referencedenvelope;
import org.geotools.map.featurelayer;
import org.geotools.map.layer;
import org.geotools.map.mapcontent;
import org.geotools.referencing.crs.defaultgeographiccrs;
import org.geotools.renderer.lite.streamingrenderer;
import org.geotools.styling.sld;
import org.geotools.styling.style;
import org.geotools.swing.jmapframe;
import org.geotools.swing.data.jfiledatastorechooser;
import org.opengis.feature.property;
import org.opengis.feature.simple.simplefeature;
import org.opengis.feature.simple.simplefeaturetype;
import org.springframework.util.resourceutils;

import javax.imageio.imageio;
import javax.servlet.http.httpservletresponse;
import java.awt.*;
import java.awt.image.bufferedimage;
import java.io.file;
import java.io.ioexception;
import java.io.serializable;
import java.nio.charset.charset;
import java.util.collection;
import java.util.hashmap;
import java.util.map;

/**
 * <p>shapefile读写工具类</p>
 * @author appleyk
 * @blob https://blog.csdn.net/appleyk
 * @date created on 上午 11:54 2018-10-12
 */
public class shptools {


    /**
     * 集合对象构造器【自定义的】
     */
    private  static geometrycreator gcreator = geometrycreator.getinstance();

    /**
     * 边界
     */
    private  static referencedenvelope bounds;

    // 画布的宽度
    private static final int image_width = 2400;

    // 画布的高度
    private static final int image_height = 1200;


    /**
     * 通过shp文件路径,读取shp内容
     * @param filepath
     * @throws exception
     */
    public static shpdatas readshpbypath(string filepath,integer limit) throws exception {

        // 一个数据存储实现,允许从shapefiles读取和写入
        shapefiledatastore shpdatastore =  new shapefiledatastore(new file(filepath).touri().tourl());
        // 设置编码【防止中文乱码】
        shpdatastore.setcharset(charset.forname("utf-8"));

        // gettypenames:获取所有地理图层,这里我只取第一个【如果是数据表,取出的就是表名】
        string typename = shpdatastore.gettypenames()[0];
        system.out.println("shp【图层】名称:"+typename);
        featurecollection<simplefeaturetype, simplefeature> result = getfeatures(shpdatastore, typename);

        // 迭代特征集合
        featureiterator<simplefeature> iterator = result.features();

        shpdatas shpdatas = new shpdatas();
        shpdatas.setname(typename);
        shpdatas.setshppath(filepath);
        buildshpdatas(limit, iterator, shpdatas);
        iterator.close();
        return  shpdatas;
    }


    /**
     * 根据数据源及图层名称拿到特征集合
     * @param shpdatastore
     * @param typename
     * @return
     * @throws ioexception
     */
    private static featurecollection<simplefeaturetype, simplefeature> getfeatures(shapefiledatastore shpdatastore, string typename) throws ioexception {

        // 通过此接口可以引用单个shapefile、数据库表等。与数据存储进行比较和约束
        featuresource<simplefeaturetype, simplefeature> featuresource = shpdatastore.getfeaturesource(typename);
        // 一个用于处理featurecollection的实用工具类。提供一个获取featurecollection实例的机制
        featurecollection<simplefeaturetype, simplefeature> result = featuresource.getfeatures();
        system.out.println("地理要素【记录】:"+result.size()+"个");
        system.out.println("==================================");
        return result;
    }

    /**
     * 构建shpdatas对象
     * @param limit
     * @param iterator
     * @param shpdatas
     */
    private static void buildshpdatas(integer limit, featureiterator<simplefeature> iterator, shpdatas shpdatas) {
        // 这里我们只迭代前limit个
        int stop = 0;
        while (iterator.hasnext()) {
            if (stop > limit) {
                break;
            }
            // 拿到一个特征
            simplefeature feature = iterator.next();
            // 取出特征里面的属性集合
            collection<property> p = feature.getproperties();

            // 遍历属性集合
            map<string,object> prop = new hashmap<>();
            for (property pro : p) {
                string key = pro.getname().tostring();
                string val = pro.getvalue().tostring();
                prop.put(key, val);
                system.out.println("key【字段】:"+key+"\t||  value【值】:"+val);
            }
            system.out.println("\n============================ 序号:"+stop+"\n");
            shpdatas.addprop(prop);
            stop++;
        } // end 最外层 while
    }

    /**
     * 将一个几何对象写进shapefile
     * @param filepath
     * @param geometry
     */
    public  static  void writeshpbygeom(string filepath, geometry geometry) throws exception{

        shapefiledatastore ds = getshpds(filepath, geometry);

        featurewriter<simplefeaturetype, simplefeature> writer = ds.getfeaturewriter(ds.gettypenames()[0],
                transaction.auto_commit);

        // interface simplefeature:一个由固定列表值以已知顺序组成的simplefeaturetype实例。
        simplefeature feature = writer.next();
        feature.setattribute("name", "xxxx名称");
        feature.setattribute("path", "c:/test");
        feature.setattribute("the_geom", geometry);
        feature.setattribute("id", 1010l);
        feature.setattribute("des", "xxxx描述");

        system.out.println("========= 写入【"+geometry.getgeometrytype()+"】成功 !=========");

        // 写入
        writer.write();

        // 关闭
        writer.close();

        // 释放资源
        ds.dispose();

    }


    /**
     * 将一个几何对象写进shapefile
     * @param shpinfo
     */
    public  static responseresult writeshpbygeom(shpinfo shpinfo) throws exception{

        // 特殊字符串解析器
        stringtokenreader reader = new stringtokenreader();
        // 根据几何对象的wkt字符串,反解【解析】成geometry对象
        geometry geometry = reader.read(shpinfo.getgeom());
        // 拿到shp对象所在的目录【文件夹】
        string path = shpinfo.getpath();
        file file = new file(path);
        if(!file.exists()){
            file.mkdir();
        }

        if(!file.isdirectory()){
            return  new responseresult(responsemessage.bad_request,"path不是有效的文件夹" );
        }

        string filepath = shpinfo.getpath()+"/"+shpinfo.getname()+".shp";
        shapefiledatastore ds = getshpds(filepath, geometry);
        string typename = ds.gettypenames()[0];
        featurewriter<simplefeaturetype, simplefeature> writer ;
        if(shpinfo.isappendwrite()){
            // 追加写几何对象
            writer = ds.getfeaturewriterappend(typename, transaction.auto_commit);
        }else{
            // 覆盖写几何对象
            writer = ds.getfeaturewriter(typename, transaction.auto_commit);
        }

        // interface simplefeature:一个由固定列表值以已知顺序组成的simplefeaturetype实例。
        simplefeature feature = writer.next();
        feature.setattribute("name", shpinfo.getname());
        feature.setattribute("path", shpinfo.getpath());
        feature.setattribute("the_geom", geometry);
        feature.setattribute("id", shpinfo.getid());
        feature.setattribute("des", shpinfo.getdes());

        system.out.println("========= 写入【"+geometry.getgeometrytype()+"】成功 !=========");

        // 写入
        writer.write();

        // 关闭
        writer.close();

        // 释放资源
        ds.dispose();

        // 返回创建成功后的shp文件路径
        return  new responseresult(responsemessage.ok,filepath);

    }

    /**
     * 拿到配置好的datastore
     * @param filepath
     * @param geometry
     * @return
     * @throws ioexception
     */
    private static shapefiledatastore getshpds(string filepath, geometry geometry) throws ioexception {
        // 1.创建shape文件对象
        file file = new file(filepath);

        map<string, serializable> params = new hashmap<>();

        // 2、用于捕获参数需求的数据类 urlp:url to the .shp file.
        params.put(shapefiledatastorefactory.urlp.key, file.touri().tourl());

        // 3、创建一个新的数据存储【如果存在,则不创建】
        shapefiledatastore ds = (shapefiledatastore) new shapefiledatastorefactory().createnewdatastore(params);

        // 4、定义图形信息和属性信息 -- simplefeaturetypebuilder 构造简单特性类型的构造器
        simplefeaturetypebuilder tbuilder = new simplefeaturetypebuilder();

        // 5、设置 -- wgs84:一个二维地理坐标参考系统,使用wgs84数据
        tbuilder.setcrs(defaultgeographiccrs.wgs84);
        tbuilder.setname("shapefile");

        // 添加名称
        tbuilder.add("name", string.class);
        // 添加shp所在目录名称
        tbuilder.add("path", string.class);
        // 添加 一个几何对象
        tbuilder.add("the_geom", geometry.getclass());
        // 添加一个id
        tbuilder.add("id", long.class);
        // 添加描述
        tbuilder.add("des", string.class);

        // 设置此数据存储的特征类型
        ds.createschema(tbuilder.buildfeaturetype());

        // 设置编码
        ds.setcharset(charset.forname("utf-8"));
        return ds;
    }

    /**
     * 打开shp文件,获取地图内容
     * @param filepath  文件路径
     * @param isopenbychoose 是否自定义打开shp文件
     * @throws exception
     */
    public static  mapcontent getmapcontentbypath(string filepath,boolean isopenbychoose,string color) throws  exception{

        file file;
        if(isopenbychoose){
            // 1.1、 数据源选择 shp扩展类型的
            file = jfiledatastorechooser.showopenfile("shp", null);
        }else{
            // 1.2、根据路径拿到文件对象
            file = new file(filepath);
        }

        if(file==null){
            return null;
        }
        // 2、得到打开的文件的数据源
        filedatastore store = filedatastorefinder.getdatastore(file);

        // 3、设置数据源的编码,防止中文乱码
        ((shapefiledatastore)store).setcharset(charset.forname("utf-8"));

        /**
         * 使用featuresource管理要素数据
         * 使用style(sld)管理样式
         * 使用layer管理显示
         * 使用mapcontent管理所有地图相关信息
         */

        // 4、以java对象的方式访问地理信息 --    简单地理要素
        simplefeaturesource featuresource = store.getfeaturesource();

        bounds = featuresource.getbounds();

        // 5、创建映射内容,并将我们的shapfile添加进去
        mapcontent mapcontent = new mapcontent();

        // 6、设置容器的标题
        mapcontent.settitle("appleyk's geotools");

        color color1;
        if(color == null || "".equals(color)){
            color1 = color.black;
        }else if("red".equals(color)){
            color1 = color.red;
        }else if("green".equals(color)){
            color1 = color.green;
        }else if("blue".equals(color)){
            color1 = color.blue;
        }else{
            color1 = color.orange;
        }

        // 7、创建简单样式 【颜色填充】
        style style = sld.createsimplestyle(featuresource.getschema(),color1);

        // 8、显示【shapfile地理信息+样式】
        layer layer = new featurelayer(featuresource, style);

        // 9、将显示添加进map容器
        mapcontent.addlayer(layer);

        return  mapcontent;
    }

    public  static  void showmap(mapcontent mapcontent){
        jmapframe.showmap(mapcontent);
    }

    /**
     * shp文件转image【格式定png】
     * @param shpfilepath shp目标文件
     * @param destimagepath 转成图片的文件 == 如果没有,转成的图片写进response输出流里
     * @param response 响应流
     * @throws exception
     */
    public static void shp2image(string shpfilepath,string destimagepath,string color, httpservletresponse response) throws  exception{

        // 流渲染器
        streamingrenderer renderer = new streamingrenderer();
        mapcontent mapcontent = getmapcontentbypath(shpfilepath,false,color );
        renderer.setmapcontent(mapcontent);
        rectangle imagebounds = new rectangle(0, 0, image_width, image_height);
        bufferedimage dumpimage = new bufferedimage(image_width, image_height, bufferedimage.type_int_rgb);
        graphics2d g2d = dumpimage.creategraphics();
        g2d.fillrect(0, 0, image_width, image_height);
        g2d.setrenderinghint(renderinghints.key_antialiasing, renderinghints.value_antialias_on);
        renderer.paint(g2d, imagebounds, bounds);
        g2d.dispose();
        if(destimagepath == null || "".equals(destimagepath)){
            imageio.write(dumpimage, "png", response.getoutputstream());
        }else{
            imageio.write(dumpimage, "png", new file(destimagepath+".png"));
        }
    }

    public static void main(string[] args) throws  exception{

        file file = resourceutils.getfile("classpath:static/shptest[point]/dp_tl.shp");
        // 从shp文件里面读取属性信息
        readshpbypath(file.getabsolutepath(),10);
        system.out.println("=================下面开始往shp文件里面写几何对象===================");

        // 先创建文件夹test
        string filepath = "c:/test/test.shp";

        string pointwkt="point (120.76164848270959 31.22001141278534)";
        point point = gcreator.createpointbywkt(pointwkt);

        // polygon【面】
        string polygonwkt="polygon ((103.859188 34.695908, 103.85661 34.693788, 103.862027 34.69259, 103.863709 34.695078, 103.859188 34.695908))";
        polygon polygon = gcreator.createpolygonbywkt(polygonwkt);

        // linestring【线】
        string linestringwkt="linestring(113.511315990174 41.7274734296674,113.51492087909 41.7284983348307,113.516079593384 41.727649586406,113.515907932007 41.7262243043929,113.514019656861 41.7247989907606,113.512131381714 41.7250872589898,113.51138036319 41.7256637915682,113.511315990174 41.7274734296674)";
        linestring linestring = gcreator.createlinebywkt(linestringwkt);

        // multipolygon【多面】
        string multipolywkt = "multipolygon(((101.870371 25.19228,101.873633 25.188183,101.880564 25.184416,101.886808 25.186028,101.892043 25.189969,101.896592 25.190163,101.903716 25.190785,101.905454 25.193464,101.899897 25.196202,101.894146 25.197911,101.891657 25.19826,101.886078 25.197658,101.884211145538 25.2007060137013,101.88172564506 25.1949712942389,101.87874 25.199619,101.874641 25.200998,101.868547 25.202415,101.863741 25.202415,101.85887 25.202842,101.854557 25.202182,101.852604 25.199736,101.852282 25.19628,101.854492 25.194183,101.855608 25.192668,101.863698 25.192105,101.870371 25.19228)))";
        multipolygon multipolygon = gcreator.createmulpolygonbywkt(multipolywkt);

        // 几何对象的范围【矩形边界】
        envelope envelope = polygon.getenvelopeinternal();
        system.out.println(envelope);

        // 往shp文件里面写几何对象
        writeshpbygeom(filepath,point);
    }

}

 

 

 

 

 

七、联系我

 

csdn名: appleyk

csdn博客:https://blog.csdn.net/appleyk

本篇csdn对应博文:https://blog.csdn.net/appleyk/article/details/83376510