前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java矢量切片实现

java矢量切片实现

作者头像
lzugis
发布2023-05-27 14:33:25
5850
发布2023-05-27 14:33:25
举报

概述

可通过多种方式实现矢量切片的制作,前面讲到了基于postgis数据库、tippecanoe、Qgis等方式,本文讲述基于spring Boot框架下java的实现。

实现代码

后端代码

  1. 引入依赖
代码语言:javascript
复制
<dependency>
      <artifactId>giscat-vector-mvt</artifactId>
      <groupId>org.wowtools</groupId>
      <version>g1.6.1</version>
</dependency>
  1. MvtController
代码语言:javascript
复制
package com.lzugis.controller;

import com.lzugis.utils.FileUtil;
import io.swagger.annotations.Api;
import org.locationtech.jts.geom.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.wowtools.giscat.vector.mvt.MvtBuilder;
import org.wowtools.giscat.vector.mvt.MvtLayer;
import org.wowtools.giscat.vector.pojo.Feature;
import org.wowtools.giscat.vector.pojo.FeatureCollection;
import org.wowtools.giscat.vector.pojo.converter.GeoJsonFeatureConverter;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

@Api(tags = "矢量切片")
@RestController
@RequestMapping("tile")
public class MvtController {
    private static final FeatureCollection areaFeatureCollection;//面数据
    private static final FeatureCollection lineFeatureCollection;//线数据
    private static final FeatureCollection pointFeatureCollection;//点数据
    private static final GeometryFactory geometryFactory = new GeometryFactory();
    private static final FileUtil fileUtil = new FileUtil();

    static {
        //构造示例数据
        GeometryFactory gf = new GeometryFactory();
        String strJson = fileUtil.getFileContent("data\\province.geojson");
        areaFeatureCollection = GeoJsonFeatureConverter.fromGeoJsonFeatureCollection(strJson, gf);
        ArrayList<Feature> pointFeatures = new ArrayList<>(areaFeatureCollection.getFeatures().size());
        ArrayList<Feature> lineFeatures = new ArrayList<>(areaFeatureCollection.getFeatures().size());
        for (Feature feature : areaFeatureCollection.getFeatures()) {
            Feature pointFeature = new Feature();
            ArrayList center = (ArrayList) feature.getProperties().get("center");
            if (center != null) {
                Point point = gf.createPoint(new Coordinate((Double) center.get(0), (Double) center.get(1)));
                Map map = new HashMap();
                map.put("name", feature.getProperties().get("name"));
                pointFeature.setProperties(map);
                pointFeature.setGeometry(point);
                pointFeatures.add(pointFeature);
            }
            Feature lineFeature = new Feature();
            if (feature.getGeometry() instanceof MultiPolygon) {
                MultiPolygon multiPolygon = (MultiPolygon) feature.getGeometry();
                LineString[] lines = new LineString[multiPolygon.getNumGeometries()];
                for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
                    Polygon polygon = (Polygon) multiPolygon.getGeometryN(i);
                    lines[i] = gf.createLineString(polygon.getExteriorRing().getCoordinates());
                }
                MultiLineString ml = gf.createMultiLineString(lines);
                lineFeature.setGeometry(ml);
            } else {
                LineString line = gf.createLineString(feature.getGeometry().getCoordinates());
                lineFeature.setGeometry(line);
            }
            lineFeatures.add(lineFeature);
        }
        lineFeatureCollection = new FeatureCollection();
        lineFeatureCollection.setFeatures(lineFeatures);
        pointFeatureCollection = new FeatureCollection();
        pointFeatureCollection.setFeatures(pointFeatures);
    }

    @RequestMapping("/{z}/{x}/{y}")
    public void getTile(@PathVariable byte z, @PathVariable int x, @PathVariable int y, HttpServletResponse response) {
        //构造一个MvtBuilder对象
        MvtBuilder mvtBuilder = new MvtBuilder(z, x, y, geometryFactory);
        //向mvt中添加layer
        MvtLayer layer = mvtBuilder.getOrCreateLayer("province-polygon");
        //向layer中添加feature
        for (Feature feature : areaFeatureCollection.getFeatures()) {
            //这里简单地从内存中取数据并判断其是否与瓦片有交集,实际运用中可从数据库查询,例如postgis的ST_intersects函数
            if (mvtBuilder.getBbox().envIntersects(feature.getGeometry())) {
                layer.addFeature(feature);
            }
        }
        //如法炮制添加layer
        layer = mvtBuilder.getOrCreateLayer("province-line");
        for (Feature feature : lineFeatureCollection.getFeatures()) {
            if (mvtBuilder.getBbox().envIntersects(feature.getGeometry())) {
                layer.addFeature(feature);
            }
        }
        //如法炮制添加layer
        layer = mvtBuilder.getOrCreateLayer("province-point");
        for (Feature feature : pointFeatureCollection.getFeatures()) {
            if (mvtBuilder.getBbox().envIntersects(feature.getGeometry())) {
                layer.addFeature(feature);
            }
        }
        //数据添加完毕,转为
        byte[] bytes = mvtBuilder.toBytes();
        String vtContentType = "application/octet-stream";
        exportByte(bytes, vtContentType, response);
    }
    //将bytes写进HttpServletResponse
    private void exportByte(byte[] bytes, String contentType, HttpServletResponse response) {
        response.setContentType(contentType);
        try (OutputStream os = response.getOutputStream()) {
            os.write(bytes);
            os.flush();
        } catch (org.apache.catalina.connector.ClientAbortException e) {
            //地图移动时客户端主动取消, 产生异常"你的主机中的软件中止了一个已建立的连接",无需处理
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

前端代码

代码语言:javascript
复制
<div id="map"></div>
 <script>
     var mapStyle = {
         "version": 8,
         "name": "Dark",
         "sources": {
             'province-data': {
                 'type': 'vector',
                 'tiles': ['http://localhost:18888/lzugis/tile/{z}/{x}/{y}']
             }
         },
         "layers": [
             {
                 'id': 'province-line',
                 'type': 'line',
                 'source': 'province-data',
                 'source-layer': 'province-line',
                 'paint': {
                     'line-color': '#31aa00',
                     'line-width': 2
                 }
             },
             {
                 'id': 'province-point',
                 'type': 'circle',
                 'source': 'province-data',
                 'source-layer': 'province-point',
                 'paint': {
                     'circle-color': '#f00',
                     'circle-radius': 5
                 }
             }
         ]
     };
     window.map = new mapboxgl.Map({
         container: 'map',
         maxZoom: 10,
         minZoom: 3,
         zoom: 3,
         center: [109.1699, 45.9719],
         style: mapStyle,
         attributionControl: false
     });
     map.on('click', function (e) {
         const coords = e.lngLat;
         const r = [
             [e.point.x - 5, e.point.y - 5],
             [e.point.x + 5, e.point.y + 5],
         ];
         const features = map.queryRenderedFeatures(r, {});
         console.log(features);
     })
 </script>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 实现代码
    • 后端代码
      • 前端代码
      相关产品与服务
      数据库
      云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档