大量POI点展示的一种解决方案

超详细讲解ArcGIS中根据POI点识别功能区 POI是“POInt of Interest”的缩写,中文可以翻译为“兴趣点”。在地理信息系统中,一个POI可以是一栋房子、一个商铺、一个邮筒、一个公交站等。根据POI点识别功能区的方法有多种,本文采取最常见的方法,即POI点缓冲区面积占比大小来识别(具体方法应该根据研究区和POI点特征来选取)。 研究区位置: 数据准备: POI点:由于是长沙市中心,服务业发达,兴趣点主要以商业点和居住点为主; 1.各类兴趣点点比例差异大; 2.在居住区内商业服务多,会存在重叠现象; 3.分布不均匀。 经去除重复点和按. 阅读详情

概述:

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

 

实现后效果:

 

技术难点:

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

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

 

编码实现:

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

 

  1. package com.lzugis.web;  
  2.   
  3.   
  4. import javax.imageio.ImageIO;  
  5.   
  6. import java.awt.Color;  
  7. import java.awt.Image;  
  8. import java.awt.image.BufferedImage;  
  9. import java.io.BufferedInputStream;  
  10. import java.io.ByteArrayInputStream;  
  11. import java.io.File;  
  12. import java.io.FileInputStream;  
  13. import java.io.IOException;  
  14. import java.io.InputStream;  
  15. import java.io.OutputStream;  
  16. import java.util.ArrayList;  
  17. import java.util.List;  
  18.   
  19. import javax.servlet.ServletException;  
  20. import javax.servlet.annotation.WebServlet;  
  21. import javax.servlet.http.HttpServlet;  
  22. import javax.servlet.http.HttpServletRequest;  
  23. import javax.servlet.http.HttpServletResponse;  
  24.   
  25. /** 
  26.  * Servlet implementation class PoiServices 
  27.  */  
  28. @WebServlet(description = "poi to wms", urlPatterns =  {"/map/poi"})  
  29. public class PoiServices extends HttpServlet {  
  30.     private static final long serialVersionUID = 1L;  
  31.          
  32.     /** 
  33.      * @see javax.servlet.http.HttpServlet#HttpServlet() 
  34.      */  
  35.     public PoiServices() {  
  36.         super();  
  37.         // TODO Auto-generated constructor stub  
  38.     }  
  39.   
  40.     /** 
  41.      * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) 
  42.      */  
  43.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  44.         // TODO Auto-generated method stub  
  45.         this.doPost(request,response);  
  46.     }  
  47.   
  48.     /** 
  49.      * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) 
  50.      */  
  51.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  52.         // TODO Auto-generated method stub        
  53.          String bbox= request.getParameter("BBOX");  
  54.          String width= request.getParameter("WIDTH");  
  55.          String height= request.getParameter("HEIGHT");  
  56.          int w = Integer.parseInt(width),  
  57.               h = Integer.parseInt(height);  
  58.          String[] extent = bbox.split(",");  
  59.          double xmin = Double.parseDouble(extent[0]),  
  60.                  ymin = Double.parseDouble(extent[1]),  
  61.                  xmax = Double.parseDouble(extent[2]),  
  62.                  ymax = Double.parseDouble(extent[3]);  
  63.          double scalex = ((xmax-xmin)*3600)/w,  
  64.                  scaley = ((ymax-ymin)*3600)/h;  
  65.          List<String> geoData = new ArrayList<String>();  
  66.          /*geoData.add("87.5758285931,43.7822116460"); 
  67.          geoData.add("91.1629975040,29.7104204643"); 
  68.          geoData.add("116.4575803581078,40.04054437977018"); 
  69.          geoData.add("103.584297498,36.1190864503");*/   
  70.          geoData.add("116.294,39.9742");   
  71.          geoData.add("116.306,39.9754");   
  72.          ……  
  73.            
  74.          BufferedImage image = new BufferedImage(w, h,BufferedImage.TYPE_INT_RGB);  
  75.          java.awt.Graphics2D g2d = image.createGraphics();  
  76.          image = g2d.getDeviceConfiguration().createCompatibleImage(w,h,  
  77.             java.awt.Transparency.TRANSLUCENT);  
  78.          g2d.dispose();  
  79.          g2d = image.createGraphics();  
  80.          for(int i=0;i<geoData.size();i++){  
  81.              String lonLat = geoData.get(i).toString();  
  82.              String lon = lonLat.split(",")[0],  
  83.                      lat = lonLat.split(",")[1];  
  84.              double x = Double.parseDouble(lon),  
  85.                      y = Double.parseDouble(lat);  
  86.              double scrx = (x-xmin)*3600/scalex,  
  87.                      scry = (ymax-y)*3600/scaley;  
  88.              Image img = ImageIO.read(new File("c:/icon.png"));  
  89.              g2d.drawImage(img, (int)scrx, (int)scry, null, null);  
  90.          }  
  91.          g2d.setStroke(new java.awt.BasicStroke(10));  
  92.          // 释放对象  
  93.          g2d.dispose();  
  94.          // 保存文件  
  95.          OutputStream os = response.getOutputStream();  
  96.          try {  
  97.              String poiimg = "c:/wms.png";  
  98.              ImageIO.write(image, "png", new File(poiimg));  
  99.              int count = 0;  
  100.              byte[] buffer = new byte[1024 * 1024];  
  101.              InputStream inStream = new BufferedInputStream(new FileInputStream(poiimg));  
  102.              while ((count = inStream.read(buffer)) != -1){  
  103.                  os.write(buffer, 0, count);  
  104.              }  
  105.              os.flush();              
  106.              inStream.close();  
  107.              os.close();  
  108.          }  
  109.          catch (IOException e) {  
  110.               e.printStackTrace();  
  111.          }  
  112.     }  
  113. }  

说明:

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

 

前台调用:

  1. var poiurl = "http://localhost:8081/lzugis/map/poi";  
  2. var poilayer = new OpenLayers.Layer.WMS("poilayer",  
  3.         poiurl,  
  4.         {  
  5.             layers: "",  
  6.             transparent: true  
  7.         }, {  
  8.             opacity: 1,  
  9.             singleTile: true  
  10.         });  
  11. map.addLayer(poilayer);
谈谈POI点的故事 POI点是Point of Interest(Point of Information)的缩写,就是感兴趣点或者是信息点的意思,它是一种重要的地理信息,有位置有属性的信息在里面。在地图上常常是一些在日常生活中常见的比如说餐馆,地铁站,公交站,酒店等点状地理要素。 每个POI一般包含四方面信息,名称、类别、坐标、分类。丰富的POI点信息能为地图使用提供很多的方便。比如你到了一个陌生的地方,你想找一个餐馆,你会打开APP,从里面按照一定的规则筛选出你感兴趣的POI点,为你的决策做一定的支持。 POI点也会分 阅读详情

相关推荐

同时检测和跟踪大量的点目标

Simultaneous Detection &amp; Tracking of Large Number of Point Targets点目标是指没有形状和外观信息,仅有位置信息的目标,常见于雷达扫描数据中,以及低轨卫星对地面的成像数据中。点目标的主要特点在于其运动,相比于视频监控中的行人等其它目标,点目标的运动方式一般更加简单、轨迹更加平滑,因此可以通过查找运动模式来检测点目标。我在之前的一...

YU_Xianguo的博客 4186

GIS讲堂第四课-大量POI点的展示

概述:今天,阳光灿烂;今天,晴转多云。咦,怎么就突然间晴转多云了呢?算了,不管了,这不是我等小辈该思考的问题,还是就第四节课程的内容“大量POI点的展示”给大家做一个汇报吧。课程详情:1、课程主题大量POI点的展示2、问题提出a、数据量大成千上万,甚至百万级的数据量b、数据传输慢由于量比较大,导致数据传输慢c、前台渲染受限制不论是OL2(Arcgis3)还是OL3(Arcgis 4),前台的渲...

weixin_30725315的博客 368

使用ArcGIS API for JavaScript展示大量点标记

ArcGIS API for JavaScript是一个强大的工具,可以帮助开发人员在Web应用程序中展示和分析地理数据。当需要展示大量的点标记时,如何高效地处理和显示这些数据是一个关键的问题。本文将介绍如何使用ArcGIS API for JavaScript来展示海量的点标记,并提供相应的源代码示例。

QgfaClang的博客 931

小程序地图展示poi帖子点击可跳转

页面有地图入口,点开可打开地图界面地图上展示命中poi的帖子。帖子有图片,文字,用户头像以及用户名称帖子可以自定义样式。

码尚有缘的博客 420

POI数据集PostGIS数据集

经纬度点,数据集,PostGIS经纬度测试数据,坐标,亲测可用 1,百里香奶油草莓基地,劳动路707弄169临,31.44512325,121.3128429,上海市;嘉定区,公司企业;公司企业,13738470228 10,EVCARD电动汽车分时租赁,亨嘉庄东南50米(徐星路西),31.47498901,121.2580786,上海市;嘉定区,生活服务;其它生活服务, 19,上海野生动物园游客服务中心,南六公路178号,31.05707954,121.7114324,上海市;浦东新区,休闲娱乐;旅游景点, 28,南汇?界浜水蜜桃基地,沔新路与申瓦路交叉口南150米,31.131024

基于ensp大学网络规划与设计(完整文档+ensp拓扑图)

大家好,我是小华学长,一名计算机领域的博主。经过多年的学习和实践,我积累了丰富的计算机知识和经验,在这里我想与大家分享我的学习心得和技巧,帮助你成为更好的程序员。 作为一名计算机博主,我一直专注于编程、算法、软件开发等领域,在这些方面积累了大量的经验。我相信分享是一种双赢的方式,通过分享,我可以帮助他人提升技术水平,同时也能够得到学习交流的机会。 在我的文章中,你将会看到我对于各种编程语言、开发工具以及常见问题的解析和分析。我会结合自己的实际项目经验,为你提供实用的解决方案和优化技巧。我相信这些经验不仅能够

qq1325513482的博客 5万+

大量POI的解决方案2

概述 在前面的文章中,讲述了通过“抽稀+后台生成图片”的方式解决大量POI点展示的一种思路,后面看了tilestache的矢量切片方式,自己仔细思考了下,提出了本文大量POI点的展示解决方案。 tilestache 大概看了下tilestache,理解了下,大概解决思路是这样的:随着地图四至范围的变换,实时的去请求数据,并将数据在前段渲染,这样就大大提升了大量点的展示的效率问...

a18826265589的博客 240

Vue路由守卫实战:利用token实现跨项目免登录跳转(最新版)

本文详细介绍了如何利用Vue路由守卫和Token验证实现跨项目免登录跳转方案。通过核心架构设计、路由守卫精细化控制及Token交换安全实践,有效解决了多系统跳转中的认证问题,提升用户体验和系统连贯性。

n7o8p的博客 138

大量POI点展示的一种解决方案——续

在上文“ 大量POI点展示的一种解决方案”中,介绍了在在后台将POI生成图片在前台展示,文章中没有涉及到点的抽稀问题,也就是当点的数据量非常大的时候,这种展示方式还是会有一定的效率问题,在本文,书接上文,介绍一种点抽稀的算法,并结合上文,实现大量poi点的高效展示。

LZUGIS 6776

Stata做DID平行趋势检验,用coefplot画图时遇到的3个坑及解决办法

本文详细解析了使用Stata进行DID平行趋势检验时,利用coefplot绘图可能遇到的三个常见问题及其解决方案。包括基线期选择陷阱、置信区间变形和图形元素错位,提供专业调试步骤和高阶技巧,帮助研究者高效完成学术级图表绘制。

weixin_42530458的博客 325

零基础NPU固件开发学习路线--1.4 学习路线与工具链:编译器、仿真器、调试器、烧录工具

本文系统介绍了NPU固件开发的学习路径与工具链。学习路线分为四个阶段:基础认知、环境搭建、模块开发和联调量产。重点讲解了交叉编译器、代码管理工具、调试器和烧录工具等核心工具链的使用方法。文章强调工具链在NPU固件开发中的关键作用,详细阐述了从代码同步到固件烧录的全流程开发闭环,为开发者提供了一条从零基础到独立开发的完整学习路径。

MHD0815的博客 116

arcgis怎么做poi_GIS讲堂第四课-大量POI点的展示

概述:今天,阳光灿烂;今天,晴转多云。咦,怎么就突然间晴转多云了呢?算了,不管了,这不是我等小辈该思考的问题,还是就第四节课程的内容“大量POI点的展示”给大家做一个汇报吧。课程详情:1、课程主题大量POI点的展示2、问题提出a、数据量大成千上万,甚至百万级的数据量b、数据传输慢由于量比较大,导致数据传输慢c、前台渲染受限制不论是OL2(Arcgis3)还是OL3(Arcgis 4),前台的渲染都...

weixin_31990755的博客 546

【S32K3 MCAL配置】-4.1-CAN Driver:如何解决CAN帧发送丢帧问题

【S32K3 MCAL配置】-4.1-CAN Driver:如何解决CAN帧发送丢帧问题

「汽车电子助手」的博客 1442

POI大量数据读取内存溢出分析及解决方案

点击关注公众号,实用技术文章及时了解来源:blog.youkuaiyun.com/liangjf85/article/details/84914798在使用POI进行excel操作时,当数据量较大时经常会产生内存溢出异常。下面我们通过分析如何解决该问题一、POI结构图二、内存溢出问题在项目中遇到二十万行数据要写入到excel中时会内存溢出,一般方法是调大tomcat的内存,但是调到2...

Java知音 8849

【我的Android进阶之旅】异常: Problems reading data from Binary store in Local\Temp\gradlexxx.bin (exist: true)

一、异常描述 今天开个会议,电脑自动关机了,重启电脑之后,打开Android Studio,编译代码,就编译失败,如下所示:异常提示 : Caused by: java.lang.RuntimeException: Problems reading data from Binary store in C:\Users\000\AppData\Local\Temp\gradle6337489649031706149.bin (exist: true) Caused by: java.lang.Runtime

字节卷动 3823

UG NX二次开发(C#)-外部模式-批量删除某些图层中的体对象和曲线对象

在 UG NX中,有时需要批量删除某文件夹下多个.prt文件中固定一些图层中的体对象和曲线对象,这时如果采用手动逐个打开模型,并选择针对的图层删除,即耗时也容易遗漏,因此采用外部模式来处理比较方便。本文介绍批量删除某些图层中的体对象和曲线对象。

GimiGimmy 3035
上一篇: 抽稀+图片生成
下一篇: Openlayers2中聚类的动态实现
韩慧兵
博客等级 码龄15年 170粉丝 171原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值