概述:

不论是在Arcgis for js还是Openlayers中,当POI点比较多的时候,在前台页面的展示在效率上是一大问题。经过一段时间的研究,发现百度地图在这一问题上的处理思路比较好:将要展示的POI点在服务器端生成图片,页面只调用图片的话效率会比较高。本文讲述如何在java后台实现POI点在服务器端的实时生成以及在Openlayers2的展示。

实现后效果:

技术难点:

要实现POI点在服务器端的生成,难点在与如何通过前台请求的参数计算出坐标点的屏幕坐标。为此参了网上的一篇文章解决了此问题,文章内容如下:

地理坐标定义规则:X轴(代表经度)向右递增,Y轴(纬度)向上递增,就好比小学学过的平面坐标。向左、向下的规则。屏幕坐标定义规则:X轴向右递增,Y轴向下递增。
可以看出,地理坐标和屏幕坐标的区别仅仅只是在于Y轴递增方向是相反的(这就是不同)。
这里强调一点的就是为了保证精度,地理坐标的度*3600换算成秒,所有的取值用double来计算,最后的结果再转换成int。
1 已知道屏幕的高(y)和宽(h),地理坐标区域的范围(maxLon,minLon,maxLat,minLat),这里我们知道了这些已知的参数。
2 我们可以算出每像素所代表的经度和纬度(有人称这个为比例因子)。
公式:scaleX = ((maxLon-minLon)*3600)/h ----------X轴上每像素代表的经度秒数;
公式:scaleY = ((maxLat-minLat)*3600)/y ----------Y轴上每像素代表的纬度秒数;
这两个比例因子就是两个坐标系之间的关系。
3 很简单的一步了,那就是算出该地理坐标区域中的任何一点(lon,lat)在屏幕上的坐标了。
公式:screenX = lon*3600/scaleX;---------屏幕坐标X轴坐标
公式:screenY = lat*3600/scaleY; ---------屏幕坐标Y轴坐标
还有最后一步,那就是我们要把该地理区域占满占个屏幕该怎么办呢?
4 接着我们需要该地理区域占满占个屏幕该怎么办呢
公式:minX = minLon*3600/scaleX;区域左边置最左端
公式:minY = minLat*3600/scaleY; 区域上面置最上端
5 当地地理范围区域占满整个屏幕时,我们需要用到第三步计算出来的 screenX和screenY两个参数,该区域中的任何一点的公式如下:
公式:X = screenX - minX = (lon - minLon)*3600/scaleX;
公式:Y = screenMaxLat - screenLat = (maxLat - lat)*3600/scaleY;
6 总结:
经纬度转屏幕坐标的最终公式如下:
公式:X = (lon - minLon)*3600/scaleX;
公式:Y = (maxLat - lat)*3600/scaleY;
接着我们由上面的公式可以推出屏幕坐标转经纬度坐标公式如下:
公式:lon = X * scaleX/3600 + minLon;
公式:lat = maxLat - y* scaleY/3600;

编码实现:

后台POI图片的实时生成用了一个servlet实现,前台调用用WMS来调用,具体代码如下:

package com.lzugis.web;import javax.imageio.ImageIO;import java.awt.Color;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** Servlet implementation class PoiServices*/
@WebServlet(description = "poi to wms", urlPatterns =  {"/map/poi"})
public class PoiServices extends HttpServlet {private static final long serialVersionUID = 1L;/*** @see javax.servlet.http.HttpServlet#HttpServlet()*/public PoiServices() {super();// TODO Auto-generated constructor stub}/*** @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)*/protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubthis.doPost(request,response);}/*** @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)*/protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stub     String bbox= request.getParameter("BBOX");String width= request.getParameter("WIDTH");String height= request.getParameter("HEIGHT");int w = Integer.parseInt(width),h = Integer.parseInt(height);String[] extent = bbox.split(",");double xmin = Double.parseDouble(extent[0]),ymin = Double.parseDouble(extent[1]),xmax = Double.parseDouble(extent[2]),ymax = Double.parseDouble(extent[3]);double scalex = ((xmax-xmin)*3600)/w,scaley = ((ymax-ymin)*3600)/h;List<String> geoData = new ArrayList<String>();/*geoData.add("87.5758285931,43.7822116460");geoData.add("91.1629975040,29.7104204643");geoData.add("116.4575803581078,40.04054437977018");geoData.add("103.584297498,36.1190864503");*/ geoData.add("116.294,39.9742"); geoData.add("116.306,39.9754"); ……BufferedImage image = new BufferedImage(w, h,BufferedImage.TYPE_INT_RGB);java.awt.Graphics2D g2d = image.createGraphics();image = g2d.getDeviceConfiguration().createCompatibleImage(w,h,java.awt.Transparency.TRANSLUCENT);g2d.dispose();g2d = image.createGraphics();for(int i=0;i<geoData.size();i++){String lonLat = geoData.get(i).toString();String lon = lonLat.split(",")[0],lat = lonLat.split(",")[1];double x = Double.parseDouble(lon),y = Double.parseDouble(lat);double scrx = (x-xmin)*3600/scalex,scry = (ymax-y)*3600/scaley;Image img = ImageIO.read(new File("c:/icon.png"));g2d.drawImage(img, (int)scrx, (int)scry, null, null);}g2d.setStroke(new java.awt.BasicStroke(10));// 释放对象g2d.dispose();// 保存文件OutputStream os = response.getOutputStream();try {String poiimg = "c:/wms.png";ImageIO.write(image, "png", new File(poiimg));int count = 0;byte[] buffer = new byte[1024 * 1024];InputStream inStream = new BufferedInputStream(new FileInputStream(poiimg));while ((count = inStream.read(buffer)) != -1){os.write(buffer, 0, count);}os.flush();         inStream.close();os.close();}catch (IOException e) {e.printStackTrace();}}
}

说明:

此处用了北京市的地铁站点的数据作为测试数据。


前台调用:

                var poiurl = "http://localhost:8081/lzugis/map/poi";var poilayer = new OpenLayers.Layer.WMS("poilayer",poiurl,{layers: "",transparent: true}, {opacity: 1,singleTile: true});map.addLayer(poilayer);

后续:

作为POI,是需要有鼠标的事件的,这部分的内容正在研究中,后期会陆续更新。

转载于:https://www.cnblogs.com/lzugis/p/6539786.html

大量POI点展示的一种解决方案相关推荐

  1. H5前端输入和展示 表情 三种解决方案

    前端表情输入展示需求,最终解决方案. 1.修改数据库编码格式 a.修改my.ini [mysqld] character-set-server=utf8mb4 (没有就自己添加进去) b. 在Conn ...

  2. 移动端采用Flexible将PX转换REM适配及开发中Retina屏1px边框的两种解决方案

    移动端采用Flexible将PX转换REM适配及开发中Retina屏1px边框的两种解决方案 说明:两个方案均基于Webpack构建. 方案一: 搭建环境及相关配置 webpack 3,需要loade ...

  3. 语义分割-地表建筑物识别的一种解决方案

    语义分割-地表建筑物识别的一种解决方案 一,前言 该篇博客是用于记录阿里天池上的一个比赛--语义分割-地表建筑物识别的整个学习,编程的过程,由于是该比赛是我做的第一个机器学习的项目,因此记录的比较详细 ...

  4. 目前java导出word的6种解决方案

    文章转载自:http://www.cnblogs.com/lcngu/p/5247179.html 最近做的项目,需要将一些信息导出到word中.在网上找了好多解决方案,现在将这几天的总结分享一下. ...

  5. Java文档(xls/x、ppt/x、vsd/x、doc/x、txt)转html的3种解决方案

    ** Java文档(xls/x.ppt/x.vsd/x.doc/x.txt)转html的3种解决方案 ** 有个需求,就是文档转html,而且html要使用自定义样式.在网上搜索了一大堆,大部分都是用 ...

  6. 实战 2000w 数据大表的优化过程,提供三种解决方案

    大家好,我是不才陈某~ 当我们业务数据库表中的数据越来越多,如果你也和我遇到了以下类似场景,那让我们一起来解决这个问题 数据的插入,查询时长较长 后续业务需求的扩展 在表中新增字段 影响较大 表中的数 ...

  7. 微信小程序中嵌套html_在微信小程序中渲染HTML内容3种解决方案及分析与问题解决...

    大部分Web应用的富文本内容都是以HTML字符串的形式存储的,通过HTML文档去展示HTML内容自然没有问题.但是,在微信小程序(下文简称为「小程序」)中,应当如何渲染这部分内容呢? 在微信小程序中渲 ...

  8. 优化系统后VS启动不了问题的一种解决方案

    本文只讨论使用第三方软件优化系统后,或者您主动禁止服务后导致VS不能启动的问题.(转载请指明出处) 记得大概是08年时,我使用一些软件对电脑启动项做了优化.后来打开VS2005时,发现VS2005会一 ...

  9. iOS多线程全套:线程生命周期,多线程的四种解决方案,线程安全问题,GCD的使用,NSOperation的使用(上)

    2017-07-08 remember17 Cocoa开发者社区 目的 本文主要是分享iOS多线程的相关内容,为了更系统的讲解,将分为以下7个方面来展开描述. 多线程的基本概念 线程的状态与生命周期 ...

最新文章

  1. 漫画:腾讯面试题(盛最多水的容器)
  2. php 常用字符串函数
  3. 电子设计从零开始 第一章总结
  4. 调用阿里云接口实现短信消息的发送源码——CSDN博客
  5. python中的array函数作用_Python中的Array | 数组2(简介和功能)
  6. day26 java的集合(4)泛型 foreach Set和Map
  7. OS开发(Objective-C)常用库索引
  8. HTML特效动画、焦点图
  9. 10款流程图绘制工具
  10. Redis:哈希表HSET、HSETNX、HGET、HEXISTS、HMSET、HMGET、HKEYS、HVALS、HGETALL、HDEL命令介绍
  11. Office 2010安装过程中修复“错误2203。发生内部错误”
  12. 制造业OEER语言数据挖掘之相关性分析
  13. 好久没写东西了,发些我的卡通头像吧
  14. SQLserver 报错RegCreateKeyEx() 返回了错误 5,“拒绝访问。” (.Net SqlClient Data Provider)错误号: 22002 严重性: 16 状态: 1
  15. 提现业务流程介绍与设计
  16. 魔改《合成大西瓜》——附试玩链接
  17. LT-mapper,LT-SLAM代码运行与学习
  18. 软考中级过了就是中级职称吗?
  19. 一文搞清楚码元速率(波特率)和比特速率(比特率)的区别
  20. csgo人机指令_CSGO指令:命令BOT前往指定位置

热门文章

  1. Linux Unix C 中的curses库——curses.h
  2. 老板评价下属的普遍性原则
  3. Shell编程常用命令
  4. CynosDB技术详解——存储集群管理【文末有福利】
  5. isAssignableFrom和isInstance、instanceof
  6. POJ 1184 聪明的打字员
  7. machine learn in python 第二章2.1.1
  8. 解决Myeclipse下Debug出现Source not found以及sql server中导入数据报错
  9. Java HashMap遍历的两种方式
  10. 丢失或损坏NDF文件如何附加数据库