GIS Java 生成四至图

目录

前言

操作步骤:

1,求出多边形的四至点

2,下载地图

3,绘制多边形


前言

对于地图上的一个多边形地块,其四至图就是能够覆盖这个多边形的最小矩形,也就是求出这个多边形的最东点,最西点,最南点,最北点,即四至点,其中最西点和最北点构成左上角,最南点和最东点构成右下点,只要知道了左上角和右下角,就知道这个最小覆盖矩形了。

前端生成四至图是比较简单的,后端如何生成四至图呢?后端生成四至图得到的是一个图片,图片的底图是天地图,在这个底图之上就是多边形。多边形的坐标长这样:"[[31.21729,121.583274],[31.217096,121.58378],[31.216985,121.583457],[31.21729,121.583274]]",它是4326的坐标系,第一个坐标和最后一个坐标是同一个,首尾相连,下图就是它的四至图。

操作步骤:

1,求出多边形的四至点

        即多边形的最东点,最西点,最南点,最北点,然后我们就知道四至图的左上点和右下点这两个点的地理坐标,根据这两个点求出它们各自在天地图的瓦片位置 (x,y) 。

/**
 * 计算瓦片行列号
 * @param latitude  纬度
 * @param longitude 经度
 * @param zoom      缩放级别
 * @return 瓦片行列号数组,格式为 [col, row]
 */
public static int[] calculateTileXY(double latitude, double longitude, int zoom) {
    double n = Math.pow(2, zoom);
    double mercX = (longitude + 180) / 360;
    double mercY = (1 - Math.log(Math.tan(Math.toRadians(latitude)) + 1 / Math.cos(Math.toRadians(latitude))) / Math.PI) / 2;

    int tileX = (int) Math.floor(mercX * n);
    int tileY = (int) Math.floor(mercY * n);

    return new int[]{tileX, tileY};
}

2,下载地图

        下载从左上点到右下点的所有小瓦片图片,并把这些小瓦片地图图片合并为一张完整的大地图图片,这些小瓦片地图的名称依次命名为 1.png,2.png....。下载次序是从左上角开始从左到右,从上到下依次生成图片。记得下载的时候需要有天地图的秘钥 tk 。

int k = 1;
// 从左上角开始从左到右,从上到下依次生成图片,图片序号依次递增
for (int j = leftUp[1]; j <= rightDown[1]; j++) {
    for (int i = leftUp[0]; i <= rightDown[0]; i++) {
        System.out.println("/" + j + "/" + i);
        HttpOkUtil.downloadImg("http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile" +
                "&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX=" + zoom +
                "&TILEROW=" + j + "&TILECOL=" + i + "&tk=xx", pathParent + k + ".png");
        k++;
    }
}

 下载得到的小瓦片大概长这样

 

 融合地图代码:

    /**
     * 合并瓦片图片
     *
     * @param tiles           包含所有瓦片及其行列信息的列表
     * @param outputImagePath 输出合并后地图的文件路径
     * @throws IOException 如果图像文件读取失败或写入失败
     */
    public static void mergeTiles(List<BufferedImage> tiles, String outputImagePath, int widthCnt, int heightCnt) throws IOException {
        // 假设所有瓦片都是正方形,获取瓦片的宽度和高度
        int tileWidth = tiles.get(0).getWidth();
        int tileHeight = tiles.get(0).getHeight();

        // 计算合并后图像的尺寸
        int width = tileWidth * widthCnt;// (int) Math.ceil(Math.sqrt(tiles.size())) * tileWidth;
        int height = tileHeight * heightCnt;// (int) Math.ceil(Math.sqrt(tiles.size())) * tileHeight;// width; //
        // 假设合并后的地图是正方形

        // 创建一个新的图像,用于合并后的地图
        BufferedImage mergedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        // 使用Graphics2D来绘制图像
        Graphics2D g2d = mergedImage.createGraphics();

        // 绘制瓦片到新图像上
        int x = 0;
        int y = 0;
        for (BufferedImage tile : tiles) {
            g2d.drawImage(tile, x, y, null);
            x += tileWidth;
            if (x >= width) {
                x = 0;
                y += tileHeight;
            }
        }

        // 释放Graphics2D资源
        g2d.dispose();

        // 将合并后的图像写入文件
        ImageIO.write(mergedImage, "PNG", new File(outputImagePath));
    }

3,绘制多边形

        在这张融合好的大地图图片上绘制多边形和四至矩形图,因为大地图图片和小瓦片是 png 格式,没有地图坐标,所有要把 path 中的点相对于其在瓦片中的位置按比例进行计算。因为每个小瓦片都是 256*256 的像素格式,所以大地图就是 (256*width,256*height) ,以大地图的左上点为相对起始点开始绘画,可以精确到像素级。

// boundingBox 就是四至图,有左上,右下两个点,也就是西北点,东南点,即west,east,north,south这四个属性
for (GeoPoint point : list) {
    int[] pointXy = FourBoundariesGraphUtil.calculateTileXY(point.getY(), point.getX(), zoom);
    FourBoundariesGraphUtil.BoundingBox tmp = FourBoundariesGraphUtil.tile2boundingBox(pointXy[0], pointXy[1], zoom);
    res.add((pointXy[0] - originX) * 256 + (int) ((point.getX() - tmp.west) / (tmp.east - tmp.west) * 256));
    res.add((pointXy[1] - originY) * 256 + (int) ((tmp.north - point.getY()) / (tmp.north - tmp.south) * 256));
}

public static class BoundingBox {
        double north;
        double south;
        double east;
        double west;

        public double[] get_tianditu_info() {
            return new double[]{west, north, east, south};
        }
    }

    public static BoundingBox tile2boundingBox(final int x, final int y, final int zoom) {
        BoundingBox bb = new BoundingBox();
        bb.north = tile2lat(y, zoom);
        bb.south = tile2lat(y + 1, zoom);
        bb.west = tile2lon(x, zoom);
        bb.east = tile2lon(x + 1, zoom);
        return bb;
    }

    public static double tile2lon(int x, int z) {
        return x / Math.pow(2.0, z) * 360.0 - 180;
    }

    public static double tile2lat(int y, int z) {
        double n = Math.PI - (2.0 * Math.PI * y) / Math.pow(2.0, z);
        return Math.toDegrees(Math.atan(Math.sinh(n)));
    }
/**
 * 计算瓦片行列号
 * @param latitude  纬度
 * @param longitude 经度
 * @param zoom      缩放级别
 * @return 瓦片行列号数组,格式为 [col, row]
 */
public static int[] calculateTileXY(double latitude, double longitude, int zoom) {
    double n = Math.pow(2, zoom);
    double mercX = (longitude + 180) / 360;
    double mercY = (1 - Math.log(Math.tan(Math.toRadians(latitude)) + 1 / Math.cos(Math.toRadians(latitude))) / Math.PI) / 2;

    int tileX = (int) Math.floor(mercX * n);
    int tileY = (int) Math.floor(mercY * n);

    return new int[]{tileX, tileY};
}

把得到的坐标点绘制到图片,这个需要使用 Java Image 的 api,百度一下就知道了。如果需要在大地图图片里写其他的信息但发现大地图图片生成得有些小了,那就在下载瓦片的地方减小左上角或增大右下角的位置,多留一点空间,如果有其他的要求,也可以对生成好的地图图片进行裁剪。下载的地图可以是任意级别经度,只要天地图支持,默认是18级最大精度。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CATIA进阶操作——创成式曲面设计入门(1)线架设计,三维点、直线、平面、曲线

目录 引出三维空间点生成三维直线三维平面三维曲线总结异形弹簧新建几何体草图编辑&#xff0c;画一条样条线进行扫掠&#xff0c;圆心和半径画出曲面上的螺旋线再次选择扫掠&#xff0c;圆心和半径 其他自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自定义信号重…

搭建基于Django的博客系统数据库迁移从Sqlite3到MySQL(四)

上一篇&#xff1a;搭建基于Django的博客系统增加广告轮播图&#xff08;三&#xff09; 下一篇&#xff1a;基于Django的博客系统之用HayStack连接elasticsearch增加搜索功能&#xff08;五&#xff09; Sqlite3数据库迁移到MySQL 数据库 迁移原因 Django 的内置数据库 SQL…

亚马逊对IP的要求是什么?

IP的全称为Internet Protocol&#xff0c;是TCP/IP体系中的网际层协议&#xff0c;IP只为主机提供一种无连接、不可靠的、尽力而为的数据包传输服务。IP规定网络上所有的设备都必须有一个独一无二的IP地址&#xff0c;就好比是邮件上都必须注明收件人地址&#xff0c;邮递员才能…

鸿蒙OS初识

学习官网&#xff1a;https://www.harmonyos.com/cn/develop 准备 注册&#xff0c;安装软件&#xff08;node:12, DevEco Studio&#xff09;&#xff1a; https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415#ZH-CN_TOP…

OpenAI 推出ChatGPT Edu,为高校定制版本

近日&#xff0c;OpenAI 宣布推出 ChatGPT Edu&#xff0c;这是一款专为高校打造的 ChatGPT 版本&#xff0c;旨在帮助学生、教师、研究人员和校园运营部门以负责任的方式部署和使用 AI。 ChatGPT Edu 由 GPT-4o 提供支持&#xff0c;具备强大的文本和图像推理能力&#xff0c;…

【笔记】Sturctured Streaming笔记总结(Python版)

目录 相关资料 一、概述 1.1 基本概念 1.2 两种处理模型 &#xff08;1&#xff09;微批处理 &#xff08;2&#xff09;持续处理 1.3 Structured Streaming和Spark SQL、Spark Streaming关系 二、编写Structured Streaming程序的基本步骤 三、输入源 3.1 File源 &am…

微服务架构-微服务实施

目录 一、概述 二、微服务拆分 2.1 概述 2.2 拆分原则 2.3 拆分方法 2.3.1 以数据为维度进行拆分 2.3.2 按照使用场景拆分 2.3.3 重要和非重要的拆分 2.3.4 变和不变的拆分 三、微服务通信 3.1 概述 3.2 微服务通信方式选择 3.3 微服务编排 3.4 API接口设计 3.5 …

实验报告 Java输入和输出

实验目的&#xff1a; 掌握Java 输入输出流的应用 掌握缓冲流的应用。 实验要求&#xff1a; &#xff08;1&#xff09;掌握字节输入输出流的操作 &#xff08;2&#xff09;掌握字符输入输出流的操作 &#xff08;3&#xff09;理解字节流和字符流的区别 &#xff08;…

游戏找不到steam_api64.dll如何解决,全面解析原因及解决方法

在现代游戏中&#xff0c;Steam平台已经成为了玩家们下载、安装和玩游戏的主要渠道之一。然而&#xff0c;有些玩家可能会遇到一个问题&#xff0c;即游戏找不到steam_api64.dll文件。这个问题可能会导致游戏无法正常运行或启动。本文将详细介绍如何解决这个问题&#xff0c;帮…

深度网络学习笔记(一)——self-attention机制介绍和计算步骤

self-attention机制介绍及其计算步骤 前言一、介绍和意义二、 计算细节2.1 计算Attention Score2.2 计算value2.3 计算关联结果b2.4 统一计算 三、总结 前言 Transformer是一种非常常见且强大的深度学习网络架构&#xff0c;尤其擅长处理输出为可变长度向量序列的任务&#xf…

51仿真器 PZ-51Tracker 未知设备

插上仿真器&#xff0c;右击我的电脑 等待一下&#xff0c;选择winUSB 此时在keil中选择仿真器会报错&#xff0c;需要安装如下我是win10) 安装好后退出再试&#xff0c;没有报错即可 这项也要选择 另外配置晶振

AI去衣技术中的几何着色:揭秘数字时尚的魔法

在数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的速度改变我们的生活&#xff0c;从智能家居到自动驾驶汽车&#xff0c;再到个性化医疗。然而&#xff0c;AI的影响远不止于此。它正在重塑我们对艺术、设计和时尚的理解。特别是在数字时尚领域&#…

数学建模 —— 人工神经网络(6)

目录 一、人工神经网络 1.1 人工神经网络结构 1.2 神经元/感知器 1.3 激活函数 1.3.1 sign函数 1.3.2 sigmoid函数&#xff08;Logistic函数&#xff09; 1.3.3 tanh双曲正切函数 1.3.4 ReLU函数 1.4 分类 二、BP人工神经网络 2.1 概述 2.2 处理过程 2.3 例题 2.…

太空音响器

目录 1&#xff0e;课程设计项目 2.任务和要求 3.总体功能设计与仿真 3.1.元器件汇总 3.2.总体方案设计 3.3 总体电路仿真 4.单元模块设计及电路仿真 4.1 互补型振荡器电路 5.组装&#xff0c;调试与测试 6.分析与总结 7.参考文献 1&#xff0e;课程设…

汇编原理 | 二进制、跳转指令、算数运算、

一.二进制 two complement reprentation&#xff08;补码&#xff09; 二进制的运算&#xff1a; 6的二进制 0110 -6的二进制 如何表示&#xff1f; 四个bit的第一个bit表示符号&#xff1a;1负0正 -6表示为1010 解释&#xff1a; 0 0000 1 0001 -1 1111&#xff08;由 …

[图解]建模相关的基础知识-01

6 00:00:21,930 --> 00:00:25,450 我们尝试以一个更深的 7 00:00:25,460 --> 00:00:27,170 或者更基本的角度 8 00:00:28,410 --> 00:00:32,760 来思考建模的问题 9 00:00:37,630 --> 00:00:42,470 首先&#xff0c;我们来说一个观点&#xff0c;就是说 10 00:…

WPS部分快捷操作汇总

记录一些个人常用的WPS快捷操作 一、去除文档中所有的超链接&#xff1a; 1、用WPS打开文档&#xff1b; 2、用Ctrla全选&#xff0c;或者点击上方的【选择】-【全选】&#xff0c;选中文档全部内容&#xff1b; 3、按CTRLSHIFTF9组合键&#xff0c;即可一次性将取文档中所有…

IDEA一键启动多个微服务

我们在做微服务项目开发的时候&#xff0c;每次刚打开IDEA&#xff0c;就需要把各个服务一个个依次启动&#xff0c;特别是服务比较多时&#xff0c;逐个点击不仅麻烦还费时。下面来说一下如何一键启动多个微服务。 操作步骤 点击Edit Configurations 2.点击“”&#xff0c;…

数据图同步软件ETL

ETL介绍 ETL&#xff08;Extract, Transform, Load&#xff09;软件是专门用于数据集成和数据仓库过程中的工具。ETL过程涉及从多个数据源提取数据&#xff0c;对数据进行转换以满足业务需求&#xff0c;然后将数据加载到目标数据库或数据仓库中。以下是ETL软件的一些关键功能…