基于SuperMap iObjects Java生成地图瓦片

news2024/11/19 7:43:10

作者:dongyx

前言

在GIS领域,地图瓦片技术作为GIS领域的关键技术,是提高地图服务性能的关键手段之一。通过预先生成地图的瓦片数据,可以显著提升用户访问地图时的响应速度和体验。SuperMap iObjects for Java作为一款强大的GIS开发组件,为开发人员提供了丰富的地图制图、空间分析和数据处理功能,使得地图瓦片的生成变得更加便捷高效。本文将详细介绍如何使用SuperMap iObjects for Java从零开始生成地图瓦片。

一、地图瓦片的概念与优势

地图瓦片是指包含了一系列比例尺、一定地图范围内的地图瓦片文件。地图瓦片按照金字塔组织结构,为每张瓦片进行唯一的级别、行列号标记。在平移、缩放地图时,浏览器根据金字塔规则,计算出所需的瓦片,从瓦片服务器获取并拼接。
在这里插入图片描述SuperMap提供的瓦片类型包括栅格瓦片和矢量瓦片。

栅格瓦片:

栅格瓦片是一种比较传统的模式,其本质上是将空间数据(栅格数据和矢量数据)分别渲染为不同缩放级别的地图图片,然后将各个级别的图片按照一定规则切分,一定的 “规则”存储到硬盘或数据库中,构成一幅完整的地图。栅格瓦片通常以PNG、JPEG、Webp等图像格式存储。
在这里插入图片描述

特点:

  • 兼容性强:几乎所有的设备和浏览器都能够显示图片,因此兼容性很好。
  • 渲染效率高:瓦片是预先渲染好的,客户端不需要进行复杂的渲染计算,加载速度快。
  • 样式固定:样式在瓦片生成时已经确定,后续无法更改。
  • 数据量较大:相比矢量瓦片,栅格瓦片因为是图片,所以数据量通常更大,尤其在高分辨率或大范围地图的情况下。

矢量瓦片:

以图片为介质的栅格瓦片打开了互联网地图的大门,互联网地图得以迅速普及。但是,随着地图的移动化和应用的逐渐深入,栅格瓦片体积大、生成效率低等缺点愈加明显,已经无法满足应用需求,矢量瓦片应运而生。矢量瓦片是将地图中的矢量图层以瓦片的形式进行切分和存储。
矢量瓦片在存储时,其相对于栅格瓦片体积小,生成效率高,适用于地图中时效性要求较高的地物要素的表达,如POI信息、路线信息等。如在天地图中,POI图层采用矢量瓦片技术,满足数据的实时更新需求。同时,可以实现地图离线,大幅提升了移动端地图的浏览性能,提高了工作的可能性和有效性。
另外,矢量瓦片支持样式修改,不再需要为不同的样式而反复进行制图、渲染、切图、更新服务等过程。如在国土等行业涉及海量数据的应用中,当地图样式发生变化时,矢量瓦片可以直接更改样式,省时省力。

特点:

  • 样式灵活:矢量瓦片的样式在客户端动态应用,可以根据需求调整颜色、线宽、透明度等,甚至可以实现动态地图。
  • 数据量小:MVT格式高效压缩了矢量数据,使得瓦片体积小,易于快速传输。
  • 可交互性强:客户端可以解析矢量瓦片中的几何和属性信息,实现点击、高亮、提示框等交互功能。
  • 客户端渲染:矢量瓦片需要客户端进行渲染,这对客户端的性能有一定要求,但随着现代浏览器和硬件的发展,这通常不是问题。

选择哪种瓦片格式主要取决于应用场景和需求。如果需要高度可定制的地图样式和丰富的用户交互,则MVT矢量瓦片是更好的选择。如果优先考虑兼容性和简化客户端负担,或者没有动态样式和交互的需求,则栅格瓦片可能更加合适。

二、SuperMap iObjects Java从零开始生成地图栅格瓦片

经常有客户会有后台自动化切图的需求,该示例主要是通过一张tif影像从创建工作空间、创建数据源、创建镶嵌数据集,然后进行切图处理,后续也可以通过Java代码通过POST请求发iServer地图服务。

2.1 数据准备

2.1.1 创建工作空间

        //实例化一个Workspace
        Workspace workspace = new Workspace();
        //实例化一个工作空间连接参数
        WorkspaceConnectionInfo workspaceConnectionInfo = new WorkspaceConnectionInfo();
        //设置工作空间类型
        workspaceConnectionInfo.setType(WorkspaceType.SMWU);
        String workspaceName = "t"+System.currentTimeMillis();
        //设置工作空间名称
        workspaceConnectionInfo.setName(workspaceName);
        String workspacePath = workspaceDir.concat(File.separator).concat(workspaceName);
        //设置工作空间路径
        workspaceConnectionInfo.setServer(workspacePath);
        boolean flag = workspace.saveAs(workspaceConnectionInfo);
        if (flag) {
            workspace.save();
            System.out.println("新建工作空间成功!"+ workspace.getConnectionInfo().getServer());
        } else {
            System.out.println("新建工作空间失败!"+ workspace.getConnectionInfo().getServer());

        }

2.1.2 创建数据源

        WorkspaceConnectionInfo wInfo = workspace.getConnectionInfo();
        String workspaceDir = new File(wInfo.getServer()).getParent();
        String workspaceName = wInfo.getName();
        String udbPath = workspaceDir.concat(File.separator).concat(workspaceName);
        //实例化数据源连接参数
        DatasourceConnectionInfo dInfo = new DatasourceConnectionInfo();
        //设置数据源类型
        dInfo.setEngineType(EngineType.UDBX);
        //设置数据源文件路径
        dInfo.setServer(udbPath);
        String udbName = "u"+System.currentTimeMillis();
        //设置数据源别名,别名在一个工作空间中是唯一的
        dInfo.setAlias(udbName);
        Datasource datasource = workspace.getDatasources().create(dInfo);
        if (datasource.isOpened()) {
            System.out.println("datasource.isReadOnly() = " + datasource.isReadOnly());
        } else {
            System.out.println("新建Udbx数据源失败!");
        }

2.1.3 创建镶嵌数据集

        Datasets datasets = datasource.getDatasets();
        PrjCoordSys prjCoordSys = new PrjCoordSys();
        prjCoordSys.fromEPSGCode(4326);
        //获取一个可用的数据集名称
        String datasetName = datasets.getAvailableDatasetName("mosaic", DatasetType.MOSAIC);
        //创建镶嵌数据集
        DatasetMosaic datasetMosaic = datasets.createDatasetMosaic(datasetName, prjCoordSys);
        String files = "D:\\陕西省土壤数据.tif";
        //添加影像文件
        datasetMosaic.addFiles(new String[]{files}, null);
        //构建概视图
        datasetMosaic.buildOverview("C:\\Users\\admin\\Desktop\\supermap", 512, 512, 3, false, 0.0);
        //构建统计信息
        boolean flag = datasetMosaic.buildStatistics();
        System.out.println("构建镶嵌数据集统计信息=" + flag);

2.1.4 构建地图

        //构建地图对象
        com.supermap.mapping.Map map = new com.supermap.mapping.Map(workspace);
        Layers layers = map.getLayers();
        //将镶嵌数据集添加到地图中
        LayerMosaicGroup layerMosaicGroup = layers.addMosaicGroup(datasetMosaic, true);
        //设置边界图层不可见。 //设置轮廓图层不可见。//标注图层不可见
        for (int i = 0; i < layerMosaicGroup.getCount(); i++) {
            if (layerMosaicGroup.get(i).getSubLayerType() != LayerType.SUBLAYER_MOSAIC) {
                layerMosaicGroup.get(i).setVisible(false);
            }
        }
        //设置图层风格
        LayerSettingImage layerSettingImage = layerMosaicGroup.getMosaicLayer().getLayerSettingImage();
        PixelFormat pixelFormat = datasetMosaic.getPixelFormat();
        if (PixelFormat.BIT16 == pixelFormat || PixelFormat.BIT32 == pixelFormat || PixelFormat.BIT64 == pixelFormat ||
                PixelFormat.DOUBLE == pixelFormat || PixelFormat.SINGLE == pixelFormat ||
                PixelFormat.UBIT16 == pixelFormat || PixelFormat.UBIT32 == pixelFormat ||
                PixelFormat.UNKONOWN == pixelFormat
        ) {
            ImageStretchOption imageStretchOption = new ImageStretchOption();
            //设置影像拉伸方式
            imageStretchOption.setStretchType(ImageStretchType.STANDARDDEVIATION);
            layerSettingImage.setImageStretchOption(imageStretchOption);
        }
        map.viewEntire();
        Maps maps = workspace.getMaps();
        maps.add("mosaic", map.toXML());
        //保存地图
        maps.setMapXML("mosaic", map.toXML());
        workspace.save();

2.2 创建地图瓦片

        //构建Map对象
        com.supermap.mapping.Map map = new com.supermap.mapping.Map(workspace);
        String mapXML = workspace.getMaps().getMapXML(0);
        map.fromXML(mapXML);
        //设置缓存名称
        String cacheName = "CTH" +System.currentTimeMillis();
        MapCacheBuilder mapCacheBuilder = new MapCacheBuilder();
        // 栅格瓦片参数设置
        mapCacheBuilder.setMap(map);
        mapCacheBuilder.setBounds(map.getBounds());
        mapCacheBuilder.setIndexBounds(mapCacheBuilder.getGlobalIndexBounds());
        mapCacheBuilder.setStorageType(StorageType.Compact);
        mapCacheBuilder.setOutputFolder("F:\\重点客户数据\\");       
        mapCacheBuilder.setCacheName(cacheName);
        // 进度条输出(公共)
        mapCacheBuilder.addSteppedListener(new SteppedListener() {
            @Override
            public void stepped(SteppedEvent steppedEvent) {
                System.out.println(steppedEvent.getTitle() + ":" + steppedEvent.getMessage() + ":" + steppedEvent.getPercent() + "%");
            }
        });
        boolean build = false;
        mapCacheBuilder.computeOutputScales();
        mapCacheBuilder.setIgnoreInvalidDrawing(true);
        mapCacheBuilder.setTileFormat(TileFormat.JPG_PNG);
        mapCacheBuilder.setTilingMode(MapTilingMode.GLOBAL);
        HashMap<Double, String> scalesMaps = mapCacheBuilder.getGlobalLevelScales();
        Integer minScales = 6;
        Integer maxScales = 8;
        // 获取比例尺
        double[] outputScales = getOutputScales(scalesMaps, minScales, maxScales);
        HashMap<Double, String>  doubleStringHashMap2 = new HashMap<>();
        doubleStringHashMap2.put(outputScales[0],"6");
        doubleStringHashMap2.put(outputScales[1],"7");
        doubleStringHashMap2.put(outputScales[2],"8");
        mapCacheBuilder.setOutputScales(outputScales);
        mapCacheBuilder.setOutputScaleCaptions(doubleStringHashMap2);
        mapCacheBuilder.resumable(false);
        // 开始切图(栅格瓦片)
        build = mapCacheBuilder.build();
        // 公共
        if (build) {
            System.out.println("切图成功"+cacheName);
            System.out.println(System.currentTimeMillis());
        } else {
            System.out.println("切图失败");
        }
        // 销毁相关资源
        mapCacheBuilder.dispose();
  private static double[] getOutputScales(HashMap<Double, String> scalesMaps, Integer minScales, Integer maxScales) {
        int arraylength = maxScales - minScales + 1;
        double[] outputScales = new double[arraylength];
        String[] values = new String[arraylength];
        for (int i = 0; i < values.length; i++) {
            values[i] = String.valueOf(minScales + i);
        }
        for (int i = 0; i < outputScales.length; i++) {
            outputScales[i] = getMapKey(scalesMaps, values[i]);
        }
        return outputScales;
    }

    private static Double getMapKey(HashMap<Double, String> maps, String value) {
        Double key = 0.0;
        for (Map.Entry<Double, String> entry : maps.entrySet()) {
            if (entry.getValue().equals(value)) {
                key = entry.getKey();
            }
        }
        return key;
    }

结语

以上就是生成地图瓦片的相关操作步骤,后续将会继续分享如何使用SuperMap iObjects Java进行多任务切图,相比单任务切图,多任务切图大大提升了切图效率,敬请期待!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浏览器渲染页面的过程以及原理

什么是浏览器渲染 简单来说&#xff0c;就是将HTML字符串 —> 像素信息 渲染时间点 浏览器什么时候开始渲染&#xff1f; 网络线程发送请求&#xff0c;取回HTML封装为渲染任务并将其传递给渲染主线程的消息队列。 问题&#xff1a;只取回HTML吗&#xff1f;那CSS和JS呢&am…

帆软认证FCRP第二题

【题目要求】 数据库中有一张地区数据统计表&#xff0c;但是并不规则 &#xff0c;记录类似于&#xff0c;225100:02:3:20160725是一串代码&#xff0c;以&#xff1a;分割&#xff0c;第1位为地区代码&#xff0c;第2位为分类代码&#xff0c;第3位为数量&#xff0c;第4位为…

Leetcode—901.股票价格跨度【中等】

2023每日刷题&#xff08;五十二&#xff09; Leetcode—901.股票价格跨度 算法思想 实现代码 class StockSpanner { public:stack<pair<int, int>> st;int curday -1;StockSpanner() {st.emplace(-1, INT_MAX);}int next(int price) {while(price > st.top(…

[网鼎杯 2020 朱雀组]phpweb1

提示 call_user_func()函数先通过php内置函数来进行代码审计绕过system&#xff08;##不止一种方法&#xff09; 拿到题目养成一个好的习惯先抓个包 从抓到的包以及它首页的报错来看&#xff0c;这里死活会post传输两个参数func以及p func传输函数&#xff0c;而p则是传输参数的…

关于前端原生技术-Jsonp的理解与简述

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/134777717 出自【进步*于辰的博客】 在学习了Jsoup这个知识点之后&#xff0c;发觉js的这一特点…

2、Redis变慢原因排查(下)

感觉Redis变慢了&#xff0c;这些可能的原因你查了没 &#xff1f;(下) Redis变慢排查的上一篇【感觉Redis变慢了&#xff0c;这些可能的原因你查了没 &#xff1f;(上)】&#xff0c;我们是基于Redis命令为入口&#xff0c;比如命令使用不得当&#xff0c;bigkey问题&#xf…

Vue3组件使用问题

Vue3组件学习 文章目录 Vue3组件学习一、Message 全局提示组件返回数据换行问题二、DatePicker 日期选择框组件限制选定年份问题 一、Message 全局提示组件返回数据换行问题 问题&#xff1a;使用中发现仅仅通过写入\n或<br/>&#xff0c;无法实现回车显示的结果。 解决…

网站高性能架构设计——web前端与池化

从公众号转载&#xff0c;关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、高性能浏览器访问 1.减少HTTP请求 HTTP协议是无状态的应用层协议&#xff0c;也就是说每次HTTP请求都需要建立通信链路、进行数据传输&#xf…

Swagger Array 逐步解密:带你简化开发工作

Swagger 允许开发者定义 API 的路径、请求参数、响应和其他相关信息&#xff0c;以便生成可读性较高的文档和自动生成客户端代码。而 Array &#xff08;数组&#xff09;是一种常见的数据结构&#xff0c;用于存储和组织多个相同类型的数据元素。数组可以有不同的维度和大小&a…

想要高速文件传输?这些Aspera替代方案等你来试

在现如今数字化的时代&#xff0c;文件传输已成为企业、组织以及个人日常工作中必不可少的一部分。但是&#xff0c;面对庞大的数据量和低效的传输速度&#xff0c;很多人会感到头疼和无奈。在这样的情况下&#xff0c;高速文件传输工具成为了一个热门话题。而aspera替代方案则…

React/Vue/Svelte 前端项目中开始使用TailwindCSS

背景 TailwindCSS 近年来在前端圈非常流行&#xff0c;它摆脱了原有的CSS限制&#xff0c;以灵活实用为卖点&#xff0c;用户通过各种class组合即可构建出漂亮的用户界面。对于初学者而言&#xff0c;可能需要一些上手成本&#xff0c;一旦掌握实用技巧后&#xff0c;Tailwind…

JetBrains Rider for Mac/win中文版- 跨平台.NET 开发的终极选择!

在.NET开发世界中&#xff0c;JetBrains Rider凭借卓越的性能和丰富的功能成为了开发者的首选。JetBrains Rider是一款跨平台.NET集成开发环境&#xff08;IDE&#xff09;&#xff0c;可在Windows和macOS上无缝运行&#xff0c;为.NET开发提供了卓越的工作体验。 JetBrains R…

C++新经典模板与泛型编程:用成员函数重载实现std::is_convertible

用成员函数重载实现is_convertible C标准库中提供的可变参类模板std::is_convertible&#xff0c;这个类模板的主要能力是判断能否从某个类型隐式地转换到另一个类型&#xff0c;返回的是一个布尔值true或false。例如&#xff0c;一般的从int转换成float或从float转换成int&am…

相控阵天线(十四):常规大阵列天线分布(椭圆阵列、三角阵列、矩形拼接阵列、栅格拼接阵列)

目录 简介椭圆阵列三角阵列子阵拼接的矩形阵列子阵拼接的圆形阵列圆形子阵拼接阵列子阵栅格拼接阵列 简介 前面的博客已经介绍过常见的平面阵有一些基本类型&#xff0c;本篇博客介绍一些实际工程中可能出现的阵列&#xff0c;包括椭圆阵列、子阵通过矩形拼接形成的矩形大阵列…

题目:分糖果(蓝桥OJ 2928)

题目描述&#xff1a; 解题思路&#xff1a; 本题采用贪心思想 图解 题解&#xff1a; #include<bits/stdc.h> using namespace std;const int N 1e6 9; char s[N];//写字符串数组的一种方法,像数组一样***int main() {int n, x;cin >> n >> x;for(int …

有哪些已经上线的vue商城项目?

前言 下面是一些商城的项目&#xff0c;需要练手的同学可以挑选一些来练&#xff0c;废话少说&#xff0c;让我们直接开始正题~~ 1、newbee-mall-vue3-app 是一个基于 Vue 3 和 TypeScript 的电商前端项目&#xff0c;它是 newbee-mall 项目的升级版。该项目包含了商品列表、…

EXP-00056: 遇到 ORACLE 错误 12154 ORA-12154: TNS: 无法解析指定的连接标识符

exp oas/oasoas filed:\daochu.dmp owner(s) 导出特定用户 //exp 用户名/密码数据库 filed:\daochu.dmp owner(用户名) 1.重启oracle监听 cmd 中输入 services.msc 找到服务&#xff1a;OracleOraDb10g_home1TNSListener 与 OracleServiceORCL。 把两个服务启动. 若未解决…

CRM系统选择技巧,什么样的CRM系统好用?

SaaS行业发展迅速&#xff0c;更多的企业逐渐选择CRM管理系统。打开搜索引擎&#xff0c;有非常多的结果。怎样在数十万个搜索结果中选择适合您的CRM系统&#xff1f;下面我们将聊聊&#xff0c;怎样选择CRM系统。 第一步&#xff1a;明确自身需求 重要性&#xff1a;每家企业…

机器学习与低代码开发:创新驱动的双剑合璧

引言 随着科技的日新月异&#xff0c;机器学习和低代码开发已经成为引领技术行业变革的两大重要趋势。机器学习通过模拟人类的学习方式&#xff0c;让计算机具备了自我学习和预测的能力&#xff0c;打破了传统计算机程序的局限性。而低代码开发则以简化软件开发过程为目标&…

leetcode 1466

leetcode 1466 如图 node 4 -> node 0 -> node 1 因为节点数是n, 边长数量是n-1。所以如果是从0出发的路线&#xff0c;都需要修改&#xff0c;反之&#xff0c;如果是通向0的节点&#xff0c;例如节点4&#xff0c;则把节点4当作父节点的节点&#xff0c;之间的路线的方…