概述

**前文**讲了在前端实现地图的导出,本文简单的通过java实现一下后端地图的导出。

实现效果

实现代码

package com.lzugis.image;import sun.misc.BASE64Decoder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;public class MapPrint {static int TILE_SIZE = 256;static double RES_ZERO = 156543.03392804097;static double[] resolutions = new double[19];static int ZOOM = 4;public static void main(String[] args) {long start = new Date().getTime();System.out.println("开始出图。。。");double res = RES_ZERO;for (int i = 0; i < 19; i++) {resolutions[i] = res;res = res / 2;}double[] extent = {4816313.49458338, 1168266.6364252055, 19000980.555761307, 7826564.13063698};int[] rowCol = getTileRowCol(extent);int xmin = rowCol[0];int xmax = rowCol[1];int ymin = rowCol[2];int ymax = rowCol[3];int width = (xmax - xmin) * TILE_SIZE;int height = (ymax - ymin) * TILE_SIZE;try {BufferedImage mergeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D graphics2D = mergeImage.createGraphics();for (int i = xmin; i <= xmax ; i++) {for (int j = ymin; j <= ymax ; j++) {String destUrl = "http://webrd01.is.autonavi.com/appmaptile?x="+i+"&y="+j+"&z="+ZOOM+"&lang=zh_cn&size=1&scale=1&style=8";BufferedImage tile = getBufferedImageDestUrl(destUrl);int x = (i - xmin) * TILE_SIZE;int y = (j -ymin) * TILE_SIZE;graphics2D.drawImage(tile, x, y, TILE_SIZE, TILE_SIZE, null);}}// 添加wms图层String extentStr = extent[0]+"," + extent[1]+"," + extent[2]+"," + extent[3];String wmsUrl = "http://localhost:8081/geoserver/ecodrought/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&LAYERS=ecodrought%3Apaddy-rice&CRS=EPSG%3A3857&SRS=EPSG%3A3857&WIDTH="+width+"&HEIGHT="+height+"&STYLES=&BBOX="+extentStr;BufferedImage wms = getBufferedImageDestUrl(wmsUrl);System.out.println(wmsUrl);graphics2D.drawImage(wms, 0, 0, width, height, null);// 添加地图标题String mapTitle = "地图导出测试";graphics2D.setColor(new Color(255,0,0,255));Font font = new Font("微软雅黑", Font.BOLD, 24);graphics2D.setFont(font);int length = graphics2D.getFontMetrics(graphics2D.getFont()).charsWidth(mapTitle.toCharArray(), 0, mapTitle.length());int posx = 60, posy = 80, offest = 15;graphics2D.drawString(mapTitle, posx, posy);graphics2D.setStroke(new BasicStroke(2.0f));int x1 = posx - offest, y1 = posy - offest - 18, x2 = posx + length + offest, y2 = posy + offest + 6;graphics2D.drawLine(x1, y1, x2, y1);graphics2D.drawLine(x2, y1, x2, y2);graphics2D.drawLine(x2, y2, x1, y2);graphics2D.drawLine(x1, y2, x1, y1);// 添加指北针String base64 = "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";int w =50, h = 50, x = width - w - posx;graphics2D.drawImage(base64ToBufferedImage(base64), x , posx, w, h, null);// 保存图片generateSaveFile(mergeImage, "merge.png");long end = new Date().getTime();System.out.println(String.format("出图结束,耗时%sms", end - start));} catch (Exception e) {e.printStackTrace();}}/*** 获取切片行列号* @param {double[]} extent - 出图四至,格式为[xmin, ymin, xmax, ymax]* @return {int[]} - 切片的行列号范围*/public static int[] getTileRowCol (double[] extent) {if(extent.length != 4) return new int[]{};double originY = RES_ZERO * TILE_SIZE / 2;double originX = -originY;double res = resolutions[ZOOM] * TILE_SIZE;int xmin = (int) Math.floor((extent[0] - originX) / res);int xmax = (int) Math.ceil((extent[2] - originX) / res);int ymax = (int) Math.ceil((originY - extent[1]) / res);int ymin = (int) Math.floor((originY - extent[3]) / res);// 往周围扩充一圈return new int[]{ xmin + 1, xmax - 1, ymin + 1, ymax - 1 };}/*** 远程图片转BufferedImage* @return {BufferedImage} - 返回图片BufferedImage*/public static BufferedImage getBufferedImageDestUrl(String destUrl) {HttpURLConnection conn = null;BufferedImage image = null;try {URL url = new URL(destUrl);conn = (HttpURLConnection) url.openConnection();if (conn.getResponseCode() == 200) {image = ImageIO.read(conn.getInputStream());return image;}} catch (Exception e) {e.printStackTrace();} finally {conn.disconnect();}return image;}/*** base64转BufferedImage* @param {String} base64* @return {BufferedImage}* @throws Exception*/public static BufferedImage base64ToBufferedImage(String base64) throws Exception {BASE64Decoder decoder = new BASE64Decoder();byte[] result = decoder.decodeBuffer(base64);InputStream stream = new ByteArrayInputStream(result);BufferedImage bufferedImage = ImageIO.read(stream);return bufferedImage;}/*** 输出图片* @param buffImg  图像拼接叠加之后的BufferedImage对象* @param savePath 图像拼接叠加之后的保存路径*/public static void generateSaveFile(BufferedImage buffImg, String savePath) {int temp = savePath.lastIndexOf(".") + 1;try {File outFile = new File(savePath);if(!outFile.exists()){outFile.createNewFile();}ImageIO.write(buffImg, savePath.substring(temp), outFile);} catch (IOException e) {e.printStackTrace();}}
}

实现分析

上面的实现中,实现了两类图层的叠加:底图切片和WMS图层的加载。底图切片的核心加载逻辑是通过传入的四至和地图级别计算需要叠加的切片的x和y的范围,并计算合并后的图片的大小,wms加载的逻辑是通过传入的四至和计算好的图片大小,再通过参数url和layers获取对应的图层的图片,再将两个图片合并。

Java实现地图的导出相关推荐

  1. Java使用geotools将Geometry(地图要素)导出为shp文件

    做图形方面的功能,往往会遇到将地图要素导出成shap文件的需求,现整理记录一下方便后期直接使用. 1.需要用到的依赖 <geotools.version>20.5</geotools ...

  2. 【Apache POI】Java Web根据模板导出word文件

    最近工作中遇到一个需求:根据word模板文档导出word文件. 查阅了一些资料,发现Apache POI可以实现文档读写的功能,于是就研究了一下,总结如下: Apache-POI在线Javadoc:h ...

  3. java中将查询数据导出_如何在R中将数据框导出到Excel

    java中将查询数据导出 What if I tell, that you can export data frames to excel in R within a couple of minute ...

  4. java 通用工具 POI XSSF导出.xls或者.xlsx

    我是用的java类反射方式生成的excel 1. pom依赖 <!-- <artifactId>poi</artifactId> //适用于低版本,也就是xls结尾的Ex ...

  5. Java按照word模板导出、下载文档

    在日常的开发工作中,我们时常会遇到导出Word文档报表的需求,比如公司的财务报表.医院的患者统计报表.电商平台的销售报表等等. 导出Word方式多种多样,通常有以下几种方式: 1. 使用第三方Java ...

  6. Java后端实现Excel导出,及添加Excel文件标题样式

    简单Java实现Excel文件导出 Java导出要在action层(controller层)中操作 需要到的jar包: 后端代码: 后面两个函数都是设置Excel文件里的标题样式,专注第一个方法就可以 ...

  7. java实现excel导入导出,对象图片读取,上传七牛云

    java实现excel导入导出以及解决方案 因为公司业务需求,要完成针对表格的导入导出,excel这里使用MultipartFile类接收 ,下面是部分关键代码,希望有所帮助 //获取excel文件的 ...

  8. java excel单元格背景色,『excel表格尺寸设置』Java如何设置被导出excel单元格的样式?比如背景色,大小什么的?...

    Java如何设置被导出excel单元格的样式?比如背景色,大小什么的? 使 poi ,具体实现 HSSFCellStyle style = null; // 创建表头style HSSFCellSty ...

  9. Java EXCEL 表格导入导出(带下拉选-带VLOOKUP函数封装)

    Java EXCEL 表格导入导出(带下拉选-带VLOOKUP函数封装) 对于excel Java POI 使用 目前简单导出导入功能网上很多,但是对于有下拉选,样式等缺点却是最大硬伤,故此封装一个通 ...

  10. java大数据量导出csv文件并压缩

    java大数据量导出csv文件并压缩 java使用POI大数据量导出excel一般会存在以下几个问题: 一次从数据库查询出这么大数据,查询缓慢 查询数据量过大时会内存溢出 解决方案:分页查询数据,比如 ...

最新文章

  1. VC运行时库(/MD、/MT等)
  2. [BZOJ 2523][Ctsc2001]聪明的学生(递归)
  3. String类型数组 根据首字母排序
  4. 技术实践 | Web 端实现 RTC 视频特效的解决方案
  5. python不是内部或外部命令的解决方法_详解python常见报错--NO MODULE NAMED _SQLITE3解决方法...
  6. Win7下使用U盘安装linux Ubuntu16.04双系统图文教程
  7. (软件工程复习核心重点)第三章需求分析-第三节:状态转换图
  8. 无法发送具有此谓词类型的内容正文_采用多模态细化类型进行程序合成
  9. 知乎:为什么魂斗罗只有128KB却可以实现那么长的剧情?
  10. 正则表达式非捕获分组?:
  11. 克隆的虚拟机一直重复出现登录界面_QQ空间里的装扮怎样才能克隆到自己空间?...
  12. GNS 3路由器7200介绍
  13. 【办公自动化】Excel“一键”生成国土“三调”转换代码
  14. 【面试经历】问题总结
  15. python测试开发django-155.bootbox使用(alert/confirm/prompt/dialog)
  16. EXCEL常用小技巧系列02----多条件求和
  17. mp4转mp3,mp4转换成mp3方法步骤
  18. 口碑营销:如何让传统行业的电商引发口碑效应并营销
  19. stm32使用XR20M1172详细攻略·SPI转UART串口
  20. 第三篇:读《今日简史》

热门文章

  1. linux安全策略加固文档_系统加固之Linux安全加固
  2. mysql增删改查sql语句_sql增删改查语句是什么?
  3. Nexus 的下载和部署
  4. ADMM算法在神经网络模型剪枝方面的应用
  5. 传感器系列之4.6雨滴传感器
  6. mariadb10 java包_编译安装MariaDB-10.0.21
  7. php操作redis实例大全
  8. uniapp判断是ios、android、小程序
  9. 源泉设计cad插件下载 | 含源泉cad插件使用教程
  10. H265H264视频流播放