天地图WMTS地图瓦片下载

2023-11-15

        最近在开发个人项目中遇到了这样一个问题,即:本地开发使用天地图在线地图服务,部署到线上时,突然想到——天地图提供的开放地图服务是需要申请秘钥key才能够使用的,而且需要连接外网,同时也是有访问次数限制的,那么,如果是在内网环境中如何进行迁移呢?

        其实解决方案很简单:通常在项目开发中,我们是通过第三方地图数据下载器进行遥感影像/电子地图/矢量数据下载,然后将其处理之后,发布到自己的专用服务器上。但是对于个人开发者而言,数据下载第一步往往最为艰难,因为不仅要考虑数据可靠性、现势性、完备性等,还要考虑坐标系是否正确,如果不正确的话,还要进行坐标系转换、影像纠偏处理等等,很是麻烦。

        然而如果有WMS/WFS/WMTS等地图服务发布经验的小伙伴,脑瓜一拍,立刻就明白常规地图服务是怎么回事了。天地图提供的WMTS服务也不例外,其实就是通过建立影像金字塔,然后逐层切分,转换为256*256的n张图片,供前端地图开发使用。

        于是,按照天地图的瓦片剖分规则(更为详细的可以自行深入研究哈),在第level层级,对应的行列数分别是:

int rowCount = (int) Math.pow(2, level); //行数
int colCount = (int) Math.pow(2, level); //列数

        对于条件有限的小伙伴来讲,可以通过网络编程简单抓取前几级的地图瓦片,然后进行使用即可。当然,只是兴趣使然,拿本篇文章做一下日常开发记录,我个人是不建议这样做的哈,毕竟有“盗用他人劳动成果”,即:白嫖的嫌疑,相比之下,更为推荐通过Nginx代理天地图服务,将其丝滑的缓存到本地的方案。 

        基于Java的下载第8层级的示例代码如下,可根据需要自行调节参数。

package com.example.xwd;


import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class DownloadTIles {

    public static void main(String[] args) {
        String outPath = "D:\\文档资料\\tiles\\";
        downWorld1To3(outPath,8,8);
    }


    //计算瓦片范围-世界范围-[1-TopLevel级]
    private static void downWorld1To3(String basePath, int lowLevel, int TopLevel) {
        System.out.println("basePath=" + basePath);
        for (int level = lowLevel; level <= TopLevel; level++) {
            int rowCount = (int) Math.pow(2, level); //行数
            int colCount = (int) Math.pow(2, level); //列数
            System.out.println("level:" + level + "row:" + rowCount + ",col:" + colCount);
            //下载瓦片
            for (int j = 0; j < colCount; j++) {
                for (int i = 0; i < rowCount; i++) {
                    String url_tilePath = "http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&tk=您的天地图key=" + i +
                            "&TILECOL=" + j
                            + "&TILEMATRIX=" + level;//拼接请求路径
                    String save_tilePath = level + "/" + j + "/";//拼接存储路径
                    String save_fileName = +i + ".png";//拼接存储名称
                    String fullFolder = basePath + save_tilePath;
                    File folder = new File(fullFolder);
                    System.out.println(folder.getAbsolutePath());
                    if (!folder.exists()) {
                        folder.mkdirs();
                    }
                    File file = new File(folder, save_fileName);
                    System.out.println("存储路径:" + file.getAbsolutePath());
                    downloadTilePNG(url_tilePath, file);
                }
            }
        }

    }


    private static void downloadTilePNG(String tileUrl, File outFile) {
        URL url = null;
        URLConnection urlConnection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        int len = -1;
        byte[] buffer = new byte[1024];
        try {
            url = new URL(tileUrl);
            urlConnection = url.openConnection();
            urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.1.5162 SLBChan/111");
            inputStream = urlConnection.getInputStream();
            outputStream = new FileOutputStream(outFile);
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            System.out.println("success:" + tileUrl);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("error:" + tileUrl);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

       然后得到如下所示的瓦片结果,并将其使用Nginx进行资源发布,


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        add_header 'Access-Control-Allow-Origin' '*';
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

    }


}

        最终使用Cesium.js做本地测试示例代码以及效果如下,

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    />
    <title>Document</title>
    <link href="../../Build/Cesium/Widgets/widgets.css" rel="stylesheet"/>
    <script src="../../Build/Cesium/Cesium.js"> </script>
    <style>
        *{
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }
        html,body{
            width: 100%;
            height: 100%;
        }
        #map{
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <script>
        Cesium.Ion.defaultAccessToken = "Your AccessToken"
        const viewer = new Cesium.Viewer("map")
        viewer.scene.imageryLayers.removeAll();

        viewer.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
            url: "http://localhost:80/tiles/" + '/{z}/{x}/{y}.png',
            minimumLevel: 0,
            maximumLevel: 7
        }));
    </script>
</body>

</html>

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

天地图WMTS地图瓦片下载 的相关文章

  • 栅格切片与WMTS服务发布

    WMTS OGC Web Map Tile Service https gdal org drivers raster wmts html 切瓦片 https www cnblogs com wang985850293 p 5381684
  • cesium与three.js 结合的栗子,结合了一下网友们的栗子,解决了three.js 高版本模型出不来的问题

    废话不多说先上图 下面是源代码
  • VS Code断点调式Cesium

    1 在VS Code中安装Debugger for Firefox插件 2 下载安Firefox Developer Edition 3 创建launch json 编辑并保存launch json Use IntelliSense to
  • CesiumJS三维案例

    WebGL近几年越来越被人们所关注 但是二三维开发难度也比普通web要高出许多 不管我们是在在开发或者是学习过程中 往往需要耗费大量的时间去查阅资料和研究官方案例 让本来就非常紧张的而宝贵的精力卷到了不关紧要的地方 而大多二三维的包 ope
  • 第九届GIS技能应用大赛试题技术文档 -上午

    1 项目概述 1 1 项目要求 如图1 1 1所示为雷尼尔山国家公园 根据题目要求 现有一份雷尼尔山国家公园地形图的一部分扫描图 需要利用该扫描图制作三维模型用来分析和展示 图1 1 1 雷尼尔山国家公园 1 具体任务要求如下 任务一 使扫
  • 天地图WMTS地图瓦片下载

    最近在开发个人项目中遇到了这样一个问题 即 本地开发使用天地图在线地图服务 部署到线上时 突然想到 天地图提供的开放地图服务是需要申请秘钥key才能够使用的 而且需要连接外网 同时也是有访问次数限制的 那么 如果是在内网环境中如何进行迁移呢
  • cesium+vue-cli安装步骤

    1 依赖node所以先安装node 可从官网下载安装 安装一直下一步最后选安装目录 2 win r输入cmd运行 先输入node v和npm v查看node安装是否正常 我这里node是10 5 0 npm是6 1 0 3 安装vue np
  • Cesium - 使用相机缩放多边形以在放大/缩小时匹配经纬度位置

    我正在努力解决相机功能 我认为 可以提供一种方法强制我的多边形粘在我房子的顶部缩小 放大和旋转 或相机移动 这个问题遵循较早的question问题已解决 现在我需要一点帮助来解决我的下一个问题 我试图遵循的示例代码位于黄金标准似乎已融入现有
  • 无法自动确定Cesium基本URL(Typescript)

    我正在尝试为 React TypeScript 设置 cesium 和 resium 但在最初的步骤上陷入了困境 我目前正在参考以下步骤恢复网站 https resium darwineducation com installation 从
  • 使用铯最轻的方法是什么?

    我有兴趣使用 Cesium 构建带有自定义图块的 3D 地球 但根据此处为 开始 说明 http cesiumjs org 2013 04 12 Cesium up and running 似乎您必须下载一个巨大的 30mb 目录并将整个内
  • 如何设置默认视图位置(Cesium 1.6)

    我想为 cesium 应用程序设置默认视图 主页位置 我不只是想飞到那个地点一次 我希望将位置设置为默认 主页 以便它可以在应用程序的其他地方使用 例如在里面主页按钮 http cesiumjs org Cesium Build Docum
  • 如何在Cesium.js中绘制自定义动态广告牌

    我目前正在使用铯进行地图应用程序 并且我需要为我正在绘制的每个项目提供状态指示器 例如 如果我正在绘制的项目是一架飞机 那么我需要有燃料状态指标 我无法使用 Cesium 的绘图工具来执行此操作 因为它们是使用地理位置绘制的 但我需要我的状
  • CesiumViewer 中的响应式 DIV [CesiumJS]

    我正在定制一个 Cesium 地图 它有一个覆盖层 里面有各种信息 我用 bootsrap 实现的覆盖层的样式 不幸的是我放置的 div 保留在特定位置并忽略页面大小的调整 有没有办法让添加到铯查看器的 DIV 响应 我现在做的是 var
  • 铯标签模糊

    我使用以下代码创建了一个 Cesium 标签 var label Cesium LabelGraphics new Cesium LabelGraphics text lab verticalOrigin Cesium VerticalOr
  • Cesium JS 椭球切平面计算

    Problem 我对铯如何计算大地测量和地心表面法线有点困惑 根据计算法线生成的平面实际上并不与给定点的椭球面相切 而且 根据大地表面法线创建的平面与根据地心表面法线生成的平面完全相同 示例以及为什么我需要这个 In this 沙堡 htt
  • Cesium地图可以在Apache HTTP服务器而不是node.js环境上运行吗?

    我有一个 Apache HTTP 服务器 可以处理我对 Ruby on Rails 项目的所有请求 我们正在考虑添加 Cesium 地图组件 我想知道是否可以在 Apache HTTP 服务器上运行 Cesium 而不是设置 node js
  • 如何根据视图边界在Cesium Map中向左或向右旋转

    想要模仿 CesiumJS 应用程序中的左右箭头键 类似于 Google 地球导航 按向右或向左箭头键应分别向右或向左旋转地球约 5 的视图边界 如果缩小 则旋转较大范围 而放大则旋转较小范围 已经查看了文档Viewer https ces
  • 更新Cesium回调属性导致实体闪烁

    这是一些可以粘贴到铯沙堡中的代码 它将一个实体添加到地图中 然后每秒更新位置属性的 CallbackProperty 每次更新时实体都会闪烁 var viewer new Cesium Viewer cesiumContainer var
  • cesium:如何在Cesium中设置不同形状的Z-index?

    如何在Cesium中设置不同形状的Z index 请参阅下面的屏幕截图 我希望圆柱体内的广告牌图标显示在圆柱体上 提前致谢 这并不容易 因为您的圆柱体是实际的 3D 体积 并且您的广告牌位于其中 3D 渲染引擎中没有 CSS 样式的 Z 索
  • 查找线段上距某点最近的点的坐标

    我需要计算从点 P 到线段 AB 绘制的垂直线的脚 我需要点 C 的坐标 其中 PC 是从点 P 到线 AB 垂直绘制的 我在 SO 上找到的答案很少here https stackoverflow com questions 129956

随机推荐

  • Transformer(一)--论文翻译:Attention Is All You Need 中文版

    转载请注明出处 https blog csdn net nocml article details 103082600 本系列传送门 Transformer 一 论文翻译 Attention Is All You Need 中文版 Tran
  • 【论文翻译】【剪枝】Filter Pruning via Geometric Medianfor Deep Convolutional Neural Networks Acceleration

    目录 摘要 1 介绍 2 相关工作 3 方法 3 1 前置内容 3 2 基于规范的准则分析 3 3 真实场景中的Norm统计 3 4 通过几何中值进行过滤修剪 3 5 理论和现实加速 3 5 1理论加速 3 5 2 实际加速 4 实验 4
  • [LeetCode]二叉树题目总结

    LeetCode 二叉树习题个人总结 近一个月来 刷了不少LeetCode题目 但是总还是感觉提高的不多 自己最初想的一边做一边总结的初衷也没有正常执行 今晚静下心来 总结一下和二叉树有关的题目 基础题目 二叉树遍历 Binary Tree
  • 有哪些研究数据结构的好的方法?

    来源 我是码农 转载请保留出处和链接 本文链接 http www 54manong com id 17 研究数据结构是为了编写程序 编写程序是为了解决问题 用计算机求解一个现实问题 一般可用以下的问题求解模型加以描述 现实问题 数学模型 算
  • C++知识点——仿函数

    仿函数 并不是函数 却有着类似于函数的行为 简单地说就是重载括号运算符号 把对象当作一个函数用 仿函数拥有自己的数据成员 意味着仿函数拥有状态 include
  • 【MMDetection】bug记录

    bug1 if env cfg get cudnn benchmark AttributeError NoneType object has no attribute get 解决办法 配置文件缺少了env cfg信息 需要在config文
  • php error:0A000126:SSL routines::unexpected eof while reading

    文章目录 问题 解决 问题 file get contents https api weixin qq com sns jscode2session appid this gt appid secret this gt secret js
  • 32位/64位 libmysql.dll和libmysql.lib下载

    为了解决C MFC 32位程序不能连接64位MySQL数据库 需要用到32位的libmysql dll和libmysql lib 花了好久才找到 直接附上官网下载地址 https downloads mysql com archives c
  • aop中获取@PathVariable参数

    1 controller中的声明 2 aop中获取 RequestAttributes attributes RequestContextHolder getRequestAttributes ServletRequestAttribute
  • 【对比Java学Kotlin】数据类

    我们在 Java 里面会创建一些专门用于盛放数据的类 比如各种以 Bean Model 作为后缀结尾的类 这些类的成员变量通常是各种类型的数据 成员函数是 setter 和 getter 或者偷懒的同学直接把成员变量的可见性设置为 publ
  • 封装C++风格的rdkafka库

    项目中用到了kafka 系统是C 开发的 没有现成的可集成API 查阅github 发现有rdkafka 这个C库 挺好用的 但是 他依然不够简洁 因此 对他做了一下封装 ifndef KAFKAMQ H define KAFKAMQ H
  • frida的基本命令

    1 frida ps Ua 打印usb连接设备正在运行的进程 进程ID 进程名 包名 2 frida ps Uai 打印usb连接设备上所有的进程 进程ID 进程名 包名 3 frida加载js脚本 frida U l js 进程名或进程I
  • VScode 路径自动补全插件: Path Autocomplete、Path Intellisense

    目录 前言 路径自动补全插件 Path Autocomplete Path Intellisense 配置 编辑设置 json 顺路安利一个文件 icon 插件 Material Icon Theme 后记 Path Autocomplet
  • K8S生命周期---初始化容器(Init Container)

    Init 容器 Init 容器是一种特殊容器 在 Pod 内的应用容器启动之前运行 Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本 你可以在 Pod 的规约中与用来描述应用容器的 containers 数组平行的位置指定 I
  • 极氪汽车的云资源治理细探

    作者 极氪汽车吴超 前言 2021 年 极氪 001 迅速崭露头角 仅用 110 天便创下了首款车型交付量 最快破万 的纪录 2022 年 11 月 极氪 009 在短短 76 天内便率先完成了首批交付 刷新了中国豪华纯电品牌交付速度的纪录
  • go语言之tcp编程

    效果展示 原理图解 源码编写 go服务端的编写 package main import fmt net func processData conn net Conn 数据处理完之后关闭连接 defer conn Close for buf
  • 组合逻辑电路的设计(二) -- 五路输入呼叫显示电路和两个BCD8421码的加法运算电路

    一 实验任务及要求 1 设计要求 2题任选1题 鼓励2题都做 1 设计一个五路输入呼叫显示电路 5个数码开关分别模拟用户的输入信号 用户优先权按用户编号依次递减 即1号的优先权最高 5号最低 1至5号按键输入时 七段数码管对应显示1 2 3
  • ChatGPT写新闻-ChatGPT写文章

    ChatGPT写新闻 ChatGPT可以用于生成新闻稿件 但需要注意的是 由ChatGPT生成的新闻稿件可能存在语义 逻辑 事实准确性等方面的问题 因此需要进行人工审核和编辑 确保其准确性 下面是一个示例过程 大致了解如何使用ChatGPT
  • 计算机中丢失VCRUNTIME140_1怎么办,vcruntime140_1.dll的三个修复方法

    vcruntime140 1 dll是一个Windows系统文件 它是Microsoft Visual C Redistributable for Visual Studio 2019软件包的一部分 用于运行使用Visual C 开发的应用
  • 天地图WMTS地图瓦片下载

    最近在开发个人项目中遇到了这样一个问题 即 本地开发使用天地图在线地图服务 部署到线上时 突然想到 天地图提供的开放地图服务是需要申请秘钥key才能够使用的 而且需要连接外网 同时也是有访问次数限制的 那么 如果是在内网环境中如何进行迁移呢