程序员人生 网站导航

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

栏目:htmlcss时间:2016-06-02 08:16:45

概述:

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


效果:






实现思路:

1、点抽稀与图片生成

package com.lzugis.web; import java.awt.Color; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.BufferedInputStream; 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 java.util.Map; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.jdbc.core.JdbcTemplate; import com.lzugis.db.SpringUtil; import com.lzugis.web.Model.Pos; /** * Servlet implementation class PoiServlet */ @WebServlet(description = "poi servlet", urlPatterns = {"/poi"}) public class PoiServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static double M_PI = Math.PI; //6378137赤道半径,1度对应赤道上的1米,20037508.342789244 private static double Degree2Meter = M_PI * 6378137 / 180.0; /** * @see HttpServlet#HttpServlet() */ public PoiServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub this.doPost(request, response); } /** * @see HttpServlet#doPost(HttpServletRequest request, 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 z = Integer.parseInt(request.getParameter("z").toString()); String layer = request.getParameter("layer"); System.out.println(z+","+layer+","+bbox); 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; //获得抽稀数据 double dis = 2000000/(z+1); System.out.println(dis); List<Pos> fc = new ArrayList<Pos>(); List<Pos> fcDel = new ArrayList<Pos>(); double buf = dis/Degree2Meter; JdbcTemplate jdbcTemplate = (JdbcTemplate) SpringUtil.getBean("jdbcTemplate"); String sqlQuery = "select * from "+layer+" where x>=? and x<=? and y>=? and y<=?"; List<Map<String, Object>> list = jdbcTemplate.queryForList(sqlQuery, new Object[]{xmin,xmax,ymin,ymax}); 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(); if(list.size()>20){ for(int i=0;i<list.size();i++){ Map<String,Object> map = list.get(i); double x = Double.parseDouble(map.get("x").toString()); double y = Double.parseDouble(map.get("y").toString()); Pos pos = new Pos(x,y); pos.setBuffer(buf); if (fc.contains(pos)) { fcDel.add(pos); } else { fc.add(pos); double scrx = (x-xmin)*3600/scalex, scry = (ymax-y)*3600/scaley; g2d.setColor(Color.RED); Image img = ImageIO.read(new File("c:/icon.png")); g2d.drawImage(img, (int)scrx, (int)scry, null, null); } } } else{ for(int i=0;i<list.size();i++){ Map<String,Object> map = list.get(i); double x = Double.parseDouble(map.get("x").toString()); double y = Double.parseDouble(map.get("y").toString()); Pos pos = new Pos(x,y); pos.setBuffer(buf); fc.add(pos); double scrx = (x-xmin)*3600/scalex, scry = (ymax-y)*3600/scaley; g2d.setColor(Color.RED); Image img = ImageIO.read(new File("c:/icon.png")); g2d.drawImage(img, (int)scrx, (int)scry, null, null); } } System.out.println("共"+list.size()+"个点,其中:保存"+fc.size()+"个,删除"+fcDel.size()+"个"); 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)) != ⑴){ os.write(buffer, 0, count); } os.flush(); inStream.close(); os.close(); } catch (IOException e) { e.printStackTrace(); } } }
其中,Pos类以下:

package com.lzugis.web.Model; public class Pos { public double x; public double y; private double buf; public Pos(double x, double y) { this.x = x; this.y = y; } public void setBuffer(double buf) { this.buf = buf; } public boolean equals(Object pt) { if (pt instanceof Pos) return (Math.abs(this.x - ((Pos) pt).x) <= buf && Math.abs(this.y - ((Pos) pt).y) <= buf); return false; } public int hashCode() { return Integer.valueOf(x + "" + y); } }
2、扩大wms,在要求参数后添加zoom和layername

OpenLayers.Layer.PoiLayer = OpenLayers.Class(OpenLayers.Layer.Grid, { DEFAULT_PARAMS: { service: "WMS", version: "1.1.1", request: "GetMap", styles: "", format: "image/jpeg" }, isBaseLayer: true, encodeBBOX: false, noMagic: false, yx: {}, layer:"", initialize: function(name, url, params, options) { var newArguments = []; //uppercase params params = OpenLayers.Util.upperCaseObject(params); if (parseFloat(params.VERSION) >= 1.3 && !params.EXCEPTIONS) { params.EXCEPTIONS = "INIMAGE"; } newArguments.push(name, url, params, options); OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments); OpenLayers.Util.applyDefaults( this.params, OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS) ); //layer is transparent if (!this.noMagic && this.params.TRANSPARENT && this.params.TRANSPARENT.toString().toLowerCase() == "true") { // unless explicitly set in options, make layer an overlay if ( (options == null) || (!options.isBaseLayer) ) { this.isBaseLayer = false; } // jpegs can never be transparent, so intelligently switch the // format, depending on the browser's capabilities if (this.params.FORMAT == "image/jpeg") { this.params.FORMAT = OpenLayers.Util.alphaHack() ? "image/gif" : "image/png"; } } }, clone: function (obj) { if (obj == null) { obj = new OpenLayers.Layer.WMS(this.name, this.url, this.params, this.getOptions()); } //get all additions from superclasses obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]); // copy/set any non-init, non-simple values here return obj; }, reverseAxisOrder: function() { var projCode = this.projection.getCode(); return parseFloat(this.params.VERSION) >= 1.3 && !!(this.yx[projCode] || OpenLayers.Projection.defaults[projCode].yx); }, getURL: function (bounds) { bounds = this.adjustBounds(bounds); var imageSize = this.getImageSize(); var newParams = {}; // WMS 1.3 introduced axis order var reverseAxisOrder = this.reverseAxisOrder(); newParams.BBOX = this.encodeBBOX ? bounds.toBBOX(null, reverseAxisOrder) : bounds.toArray(reverseAxisOrder); newParams.WIDTH = imageSize.w; newParams.HEIGHT = imageSize.h; var requestString = this.getFullRequestString(newParams); var zoom = this.map.getZoom(); var layer = this.name; return requestString+"&z="+zoom+"&layer="+layer; }, mergeNewParams:function(newParams) { var upperParams = OpenLayers.Util.upperCaseObject(newParams); var newArguments = [upperParams]; return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this, newArguments); }, getFullRequestString:function(newParams, altUrl) { var mapProjection = this.map.getProjectionObject(); var projectionCode = this.projection && this.projection.equals(mapProjection) ? this.projection.getCode() : mapProjection.getCode(); var value = (projectionCode == "none") ? null : projectionCode; if (parseFloat(this.params.VERSION) >= 1.3) { this.params.CRS = value; } else { this.params.SRS = value; } if (typeof this.params.TRANSPARENT == "boolean") { newParams.TRANSPARENT = this.params.TRANSPARENT ? "TRUE" : "FALSE"; } return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply( this, arguments); }, CLASS_NAME: "OpenLayers.Layer.PoiLayer" });
3、前台调用并展现

<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF⑻"> <title>openlayers map</title> <link rel="stylesheet" href="../../../plugin/OpenLayers⑵.13.1/theme/default/style.css" type="text/css"> <style> html, body, #map{ padding:0; margin:0; height:100%; width:100%; overflow: hidden; } .tool{ position: absolute; top:10pt; right: 10pt; padding: 5px; background: #fff; border: 1px solid #ff5500; z-index: 1000; } </style> <script src="../../../plugin/OpenLayers⑵.13.1/OpenLayers.js"></script> <script src="extend/PoiLayer.js"></script> <script src="../../../plugin/jquery/jquery⑴.8.3.js"></script> <script> var map; var tiled; OpenLayers.IMAGE_RELOAD_ATTEMPTS = 5; OpenLayers.DOTS_PER_INCH = 25.4 / 0.28; $(window).load(function() { var format = 'image/png'; var bounds = new OpenLayers.Bounds( 73.45100463562233, 18.16324718764174, 134.97679764650596, 53.531943152223576 ); var options = { controls: [], maxExtent: bounds, maxResolution: 0.2403351289487642, projection: "EPSG:4326", units: 'degrees' }; map = new OpenLayers.Map('map', options); var url = "http://localhost:8088/geoserver/lzugis/wms"; tiled = new OpenLayers.Layer.WMS( "Geoserver layers - Tiled", url, { "LAYERS": 'lzugis:province', "STYLES": '', format: format }, { buffer: 0, displayOutsideMaxExtent: true, isBaseLayer: true, yx : {'EPSG:4326' : true} } ); map.addLayers([tiled]); map.addControl(new OpenLayers.Control.Zoom()); map.addControl(new OpenLayers.Control.Navigation()); map.zoomToExtent(bounds); $("#addchart").on("click",function(){ var poiurl = "http://localhost:8081/lzugis/poi"; var wms = new OpenLayers.Layer.PoiLayer("county", poiurl, { layers: "poi", transparent: true }, { opacity: 1, singleTile: true }); map.addLayers([wms]); }); }); </script> </head> <body> <div id="map"> <div class="tool"> <button id="addchart">添加marker</button> </div> </div> <map name="marker" id="marker"></map> </body> </html>

传播GIS知识 | 交换GIS经验 | 分享GIS价值 | 专注GIS发展

技术博客

http://blog.csdn.net/gisshixisheng


在线教程

http://edu.csdn.net/course/detail/799

Github

https://github.com/lzugis/


联系方式

q       q:1004740957

e-mail:niujp08@qq.com

公众号:lzugis15

Q Q 群:452117357(webgis)
             337469080(Android)





------分隔线----------------------------
------分隔线----------------------------

最新技术推荐