基于SuperMap iObjects Java生成地图瓦片

news/2024/7/7 22:22:28

作者: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://lihuaxi.xjx100.cn/news/1876703.html

相关文章

LeetCode Hot100 78.子集

题目&#xff1a; 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 方法&#xff1a;灵神 选 or 不选 class Solution {private final List&…

应用架构——集群、分布式、微服务的概念及异同

一、什么是集群&#xff1f; 集群是指将多台服务器集中在一起&#xff0c; 每台服务器都实现相同的业务&#xff0c;做相同的事&#xff1b;但是每台服务器并不是缺 一不可&#xff0c;存在的主要作用是缓解并发能力和单点故障转移问题。 集群主要具有以下特征&#xff1a; …

Python ItsDangerous库:构建安全可靠的数据传输

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com ItsDangerous是Python中一个轻量级的库&#xff0c;旨在提供安全且简单的数据传输和签名功能。本文将深入介绍ItsDangerous的核心特性、基本用法以及在实际应用中的一些示例&#xff0c;通过丰富的示例代码&…

microblaze仿真

verdivcs (1) vlogan/vcs增加编译选项 -debug_accessall -kdb -lca (2) 在 simulation 选项中加入下面三个选项 -guiverdi UVM_VERDI_TRACE"UVM_AWARERALHIERCOMPWAVE" UVM_TR_RECORD 这里 -guiverdi是启动verdi 和vcs联合仿真。UVM_VERDI_TRACE 这里是记录 U…

macOS 获取文件夹大小

macOS 获取文件夹大小 获取文件夹大小的扩展如下&#xff1a; extension URL {var fileSize: Int? { // in bytesdo {let val try self.resourceValues(forKeys: [.totalFileAllocatedSizeKey, .fileAllocatedSizeKey])return val.totalFileAllocatedSize ?? val.fileAll…

库卡LBR_iisy_3_R760协作机器人导入到coppeliasim

1.从库卡官网xpert下载模型 一般载都是这个step文件格式&#xff0c;其他的好像不太好用。coppeliasim导入格式用的是stl,需要用freeCAD打开重新转换一下。下载下来后&#xff0c;很多都是一个整体&#xff0c;在freeCAD导入中&#xff0c;导入选择要不勾选合并。 下载完用CAD …

ERPNext SQL 注入漏洞复现

0x01 产品简介 ERPNext 是一套开源的企业资源计划系统。 0x02 漏洞概述 ERPNext 系统frappe.model.db_query.get_list 文件 filters 参数存在 SQL 注入漏洞,攻击者除了可以利用 SQL 注入漏洞获取数据库中的信息(例如,管理员后台密码、站点的用户个人信息)之外,甚至在高权…

vue pc官网顶部导航栏组件

官网顶部导航分为一级导航和二级导航 导航的样子 文件的层级 router 文件层级 header 组件代码 <h1 class"logo-wrap"><router-link to"/"><img class"logo" :src"$config.company.logo" alt"" /><i…