【MBtiles数据索引和服务发布】GeoServer改造Springboot番外系列二

xyz地图服务访问示例:http://192.168.1.240:8081/gmserver/raster/xyz/firstWP:Imagery-raster/{z}/{x}/{y}.jpg

访问示例如下:

mbtiles目录结构

根据z,x,y获取对应mbtiles文件路径的工具方法

说明:重点是使用getMbtilesPath方法,通过xyz获取mbtiles文件路径。

getTilesFile方法是通过图层(因为我做的项目是mbtiles数据集绑定在图层上)获取对应的mbtiles文件。

package com.gs.springboot.gmserver.util;import com.gs.springboot.gmserver.core.CommonConstants;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.StoreInfo;import java.io.File;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;/*** @Desc mbtiles工具类*/
public class MbtilesUtil {/*** 根据zxy索引mbtiles文件所在目录** @param z        层级* @param x        行* @param y        列* @param rootPath mbtiles根目录* @return java.lang.String*/public static String getMbtilesPath(int z, int x, int y, String rootPath) {int p = 0;//文件级别的列号int q = 0;//文件级别的行号int m = 0;//文件夹级别的列号int n = 0;//文件夹级别的行号if (z <= 8) {p = 0;q = 0;m = 0;n = 0;} else if (z >= 9) {double fileTotal = Math.pow(2, 2 * (z - 8));//文件总数double tileTotal = 65536 * fileTotal;//瓦片总数double maxTileNum = Math.sqrt(tileTotal);//行和列坐标轴方向的瓦片个数,行列相等double segmentNum = Math.sqrt(fileTotal);//行和列分的段数,即行和列坐标轴方向的mbtiles文件个数double tileNumOfEachMbtiles = maxTileNum / segmentNum;//单个mbtiles的最大行列的瓦片数,行列瓦片数相等p = (int) (x / tileNumOfEachMbtiles);q = (int) (y / tileNumOfEachMbtiles);if (z == 9 || z == 10) {m = 0;n = 0;} else {double dirTotal = fileTotal / 16;//文件夹总数double segmentDirNum = Math.sqrt(dirTotal);//行和列坐标轴方向的最大文件夹个数,行列相等double tileNumOfEachDir = segmentNum / segmentDirNum;//每段文件夹内的mbtiles的个数m = (int) (p / tileNumOfEachDir);n = (int) (q / tileNumOfEachDir);}}String mbtiles_file = rootPath + "/" + z + "/" + m + "_" + n + "/" + z + "_" + p + "_" + q + ".mbtiles";return mbtiles_file;}/*** 通过图层信息索引瓦片对应文件* @param layerInfo 图层* @param tilecol 列x* @param tilerow 行y* @param z 层级z* @param format 后缀* @return java.io.File*/public static File getTilesFile(LayerInfo layerInfo, int tilecol, int tilerow, Integer z, String format) {StoreInfo store = layerInfo.getResource().getStore();String type = store.getType();File file = null;Map<String, Serializable> connectionParameters = store.getConnectionParameters();for (String key : connectionParameters.keySet()) {if (key.contains("filePath")) {Serializable value = connectionParameters.get(key);String rootPath = (String) value;String tilesPath = null;if (type.equals(CommonConstants.DataStoreType.TilesFolderRaster.getValue())|| type.equals(CommonConstants.DataStoreType.TilesFolderVector.getValue())|| type.equals(CommonConstants.DataStoreType.TilesFolderDEM_terrain.getValue())) {tilesPath = rootPath + "/" + z + "/" + tilecol + "/" + tilerow + "." + format;} else if (type.equals(CommonConstants.DataStoreType.TilesFolderDEM_png.getValue())) {tilesPath = rootPath + "/" + z + "/" + tilecol + "/" + tilerow + ".png";}else if (type.equals(CommonConstants.DataStoreType.MbtilesFolderRaster.getValue())|| type.equals(CommonConstants.DataStoreType.MbtilesFolderVector.getValue())|| type.equals(CommonConstants.DataStoreType.MbtilesFolderDEM.getValue())) {tilesPath = getMbtilesPath(z, tilecol, tilerow, rootPath);}file = new File(tilesPath);if (file.exists() && file.length() > 0) {break;}}}return file;}}

发布mbtiles地图服务的接口。

说明:此处由于是项目的完整功能,所以代码是通过图层名称获取mbtiles的文件,你也可以将layer直接换成mbtiles数据集的根目录,或者直接写死根目录。通过xyz就可以访问瓦片。

package com.gs.springboot.gmserver.tiles;import cn.hutool.core.io.file.FileNameUtil;
import com.gs.springboot.gmserver.core.CommonConstants;
import com.gs.springboot.gmserver.util.MbtilesUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.StoreInfo;
import org.imintel.mbtiles4j.MBTilesReadException;
import org.imintel.mbtiles4j.MBTilesReader;
import org.imintel.mbtiles4j.Tile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.concurrent.CompletableFuture;@RestController
@Api(tags = "栅格瓦片服务发布接口")
public class RasterTilesController {@Autowiredprivate Catalog catalog;@GetMapping("/raster/xyz/{layer}/{z}/{x}/{y}.{format}")@ApiOperation(value = "发布栅格Mbtiles文件夹数据XYZ服务")@ApiImplicitParams({@ApiImplicitParam(name = "layer", value = "图层名称", dataType = "String", paramType = "path"),@ApiImplicitParam(name = "z", value = "z坐标", dataType = "int", paramType = "path"),@ApiImplicitParam(name = "x", value = "x坐标", dataType = "int", paramType = "path"),@ApiImplicitParam(name = "y", value = "y坐标", dataType = "int", paramType = "path"),@ApiImplicitParam(name = "format", value = "格式", dataType = "String", paramType = "path")})public void publishXYZ(@PathVariable("layer") String layer,@PathVariable("z") int z,@PathVariable("x") int x,@PathVariable("y") int y,@PathVariable("format") String format,HttpServletResponse response) {LayerInfo layerInfo = catalog.getLayerByName(layer);StoreInfo store = layerInfo.getResource().getStore();if (store.getConnectionParameters().get("scheme") != null) {String scheme = (String) store.getConnectionParameters().get("scheme");if (!CommonConstants.DataStoreScheme.XYZ.getValue().equals(scheme)) {y = (1 << z) - y - 1;//此处是将xyz转tms}}extracted(layerInfo, z, x, y, format, response);}private void extracted(LayerInfo layerInfo, int z, int x, int y, String format, HttpServletResponse response) {File file = MbtilesUtil.getTilesFile(layerInfo, x, y, z, format);String prefix = FileNameUtil.getSuffix(file);// 异步执行任务,返回一个 CompletableFutureCompletableFuture<Void> future = CompletableFuture.runAsync(() -> {InputStream data = null;if ("mbtiles".equals(prefix)) {MBTilesReader r = null;Tile tile;try {r = new MBTilesReader(file);tile = r.getTile(z, x, y);} catch (MBTilesReadException e) {throw new RuntimeException(e);}data = tile.getData();} try {if ("png".equals(format) || "jpg".equals(format)) {response.setContentType("image/" + format);} else {response.setStatus(400);return;}ServletOutputStream oStream = response.getOutputStream();IOUtils.copy(data, oStream);oStream.flush();oStream.close();} catch (IOException e) {throw new RuntimeException(e);}});// 等待 CompletableFuture 完成future.join();}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/442316.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ入门概念

目录 一、RabbitMQ入门 1.1 rabbitmq是啥&#xff1f; 1.2 应用场景 1.3 AMQP协议与RabbitMQ工作流程 1.4 Docker安装部署RabbitMQ 二、SpringBoot连接MQ配置 2.1 示例1 2.1 示例2 —— 发送实体 一、RabbitMQ入门 1.1 rabbitmq是啥&#xff1f; MQ&#xff08;Message…

02-opencv简单实例效果和基本介绍-上

机器视觉概述 机器视觉是人工智能正在快速发展的一个分支。简单说来,机器视觉就是用机器代替人眼来做测量和判断。机器视觉系统是通过机器视觉产品(即图像摄取装置,分CMOS和CCD两种)将被摄取目标转换成图像信号,传送给专用的图像处理系统,得到被摄目标的形态信息,根据像素…

Win10+wsl2+mmdetection3d(GPU)

2024部署mmdetection3d在win10wsl2 实现过程安装wsl2安装docker与VSCode插件连接其他问题 实现过程 安装WSL2 踩坑点&#xff1a; 基于发行版安装&#xff0c;无法更新wsl1&#xff0c;查证了当前的wi10的驱动是满足要求的&#xff0c;但是无法更新。所以一定要先去更新驱动&…

iZotope RX 10.4.2 mac激活版 音频修复和增强工具

iZotope RX 10 for Mac是一款专业的音频修复软件&#xff0c;旨在提供强大、精确的工具&#xff0c;让用户能够清晰、纯净地处理音频。以下是其主要功能和特点&#xff1a; 软件下载&#xff1a;iZotope RX 10.4.2 mac激活版下载 强大的降噪功能&#xff1a;iZotope RX 10采用了…

SRC实战 | 信息泄露挖掘

本文由掌控安全学院 - 叴龙 投稿 1. 信息搜集 首先老语法先搜集一波&#xff0c;毕竟没有钓鱼和sg的能力&#xff0c;只能找注册站去挖挖了。 web.title”XX大学”&&web.body”忘记密码”&&web.body”注册” 2. 漏洞挖掘 这里找到一个可以注册网站接口&…

Python之PyMySQL模块

Python之PyMySQL模块 目录 Python之PyMySQL模块安装连接数据库connect拓展 获取游标操作数据查找添加更新 安装 pip install pymysql连接数据库 使用connect函数创建连接对象 此对象提供数据库的关闭、事务提交、事务回滚等操作 示例&#xff1a; import pymysql# 以下为必…

java大文件分片上传

1.效果图 2.前端html <!DOCTYPE html> <html> <head></head> <body> <form><input type"file" id"fileInput" multiple><button type"button" onclick"upload()" >大文件分片上传&l…

【JAVA】Long类型返回到前端,精度丢失

一. 问题阐述 20位long类型的数字&#xff0c;从后端接口返回到前端后【四舍五入】 MYSQL端 &#xff08;1&#xff09;bigint (20) &#xff08;2&#xff09;具体某一条数据 JAVA端 &#xff08;1&#xff09;实体类 &#xff08;2&#xff09;服务类 &#xff08;3&…

【Vue.js设计与实现】第一篇:框架设计概览-阅读笔记(完结)

从高层设计的角度去探讨框架需要关注的问题。 参考&#xff1a;速读《Vue.js 设计与实现》 - 掘金 (juejin.cn) 系列目录&#xff1a; 标题博客第一篇&#xff1a;框架设计概览【Vue.js设计与实现】第一篇&#xff1a;框架设计概览-阅读笔记第二篇&#xff1a;响应系统【Vue.…

注册亚马逊店铺用动态IP可以吗?

注册亚马逊店铺可以用动态IP&#xff0c;只要是独立且干净的网线就没问题&#xff0c;亚马逊规则要求一个IP地址只能出现一个亚马逊店铺&#xff0c;若使用不当会导致关联账户。 固定ip可以给我们的账户带来更多的安全&#xff0c;要知道关联问题是亚马逊上的一个大问题&#…

Leetcode—1265. 逆序打印不可变链表【中等】Plus

2024每日刷题&#xff08;一零三&#xff09; Leetcode—1265. 逆序打印不可变链表 实现代码 /*** // This is the ImmutableListNodes API interface.* // You should not implement it, or speculate about its implementation.* class ImmutableListNode {* public:* v…

KubeSphere 核心实战之四【在kubesphere平台上部署Ruoyi-cloud项目】(实操篇 4/4)

**《KubeSphere 核心实战系列》** KubeSphere 核心实战之一&#xff08;实操篇 1/4&#xff09; KubeSphere 核心实战之二&#xff08;实操篇 2/4&#xff09; KubeSphere 核心实战之三&#xff08;实操篇 3/4&#xff09; KubeSphere 核心实战之四&#xff08;实操篇 4/4&…