前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >大量POI点展示的一种解决方案——续

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

作者头像
lzugis
发布2018-10-23 12:00:06
1.3K0
发布2018-10-23 12:00:06
举报

概述:

在上文“ 大量POI点展示的一种解决方案”中,介绍了在在后台将POI生成图片在前台展示,文章中没有涉及到点的抽稀问题,也就是当点的数据量非常大的时候,这种展示方式还是会有一定的效率问题,在本文,书接上文,介绍一种点抽稀的算法,并结合上文,实现大量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赤道半径,一度对应赤道上的一米,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)) != -1){
	            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-8">
    <title>openlayers map</title>
    <link rel="stylesheet" href="../../../plugin/OpenLayers-2.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-2.13.1/OpenLayers.js"></script>
    <script src="extend/PoiLayer.js"></script>
    <script src="../../../plugin/jquery/jquery-1.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>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年05月30日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档