• Openlayers离线加载天地图


    概述:

    经过一个春节的休整,今天终于开始了!不论什么时候,都不要忘记学习,学习是一辈子的事情!今天,我来说说如何实现天地图的离线以及Openlayers加载离线数据实现天地图数据的展示。


    实现:

    1、获取天地图的数据

    可以通过网络上下载各大地图的工具将天地图的数据下载下来,并制作成mbtiles文件。制作过程在此就不详述,将已经制作好的一个文件上传到了百度网盘,需要的童鞋可以下载哦~~~~

    下载链接:http://pan.baidu.com/s/1dEmNtnF 密码:xqd8


    2、读取mbtiles并返回到页面

    mbtiles其实就是一个sqllite数据库, 其详细可移步至http://www.cnblogs.com/i-gps/p/3919475.html查看详细。在此方案中,我用了一个servlet,具体的实现代码如下:

    package com.lzugis.web;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * Created by Administrator on 2016/2/27.
     */
    @WebServlet(description = "tian ditu tile", urlPatterns =  {"/tdttile"})
    public class TiandituTile extends HttpServlet {
        private String tilepath = "D:/data/tdt/";
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String tile_column = request.getParameter("X");
            String tile_row = request.getParameter("Y");
            String zoom_level = request.getParameter("L");
            String layer = request.getParameter("T");
            // TODO Auto-generated method stub
            try {
                Class.forName("org.sqlite.JDBC");
            }
            catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
                System.out.println("数据库驱动未找到!");
            }
            // 得到连接 会在你所填写的目录建一个你命名的文件数据库
            Connection conn;
            try {
                String conurl = "jdbc:sqlite:"+tilepath+layer+".mbtiles";
                conn = DriverManager.getConnection(conurl,null,null);
                // 设置自动提交为false
                conn.setAutoCommit(false);
                Statement stmt = conn.createStatement();
                //判断表是否存在
                ResultSet rsTables = conn.getMetaData().getTables(null, null, "tiles", null);
                if(!rsTables.next()){
                    System.out.println("表不存在");
                }
                // 得到结果集
                String sql = "SELECT * FROM tiles WHERE zoom_level = "+zoom_level+
                        " AND tile_column = "+tile_column+
                        " AND tile_row = "+tile_row;
                ResultSet rs = stmt.executeQuery(sql);
                if(rs.next()) {
                    byte[] imgByte = (byte[]) rs.getObject("tile_data");
                    InputStream is = new ByteArrayInputStream(imgByte);
                    OutputStream os = response.getOutputStream();
                    try {
                        int count = 0;
                        byte[] buffer = new byte[1024 * 1024];
                        while ((count = is.read(buffer)) != -1) {
                            os.write(buffer, 0, count);
                        }
                        os.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        os.close();
                        is.close();
                    }
                }
                else{
                    System.out.println(sql);
                    System.out.println("未找到图片!");
                }
                rs.close();
                conn.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
                System.out.println("SQL异常!");
            }
        }
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request,response);
        }
    }
    其中,请求地址为:http://localhost:8081/lzugis/tdttile?T=vec_c&L=5&X=25&Y=3,请求的结果如下所示:



    3、openlayers调用

    从网上拔了下openlayers加载天地图的代码,并稍作修改,扩展了一个openlayers图层TiandituLayer,其代码如下:

    OpenLayers.Layer.TiandituLayer = OpenLayers.Class(OpenLayers.Layer.Grid,{
    	mapType : null,
    	mirrorUrls : null,
    	topLevel : null,
    	bottomLevel : null,
    	
    	//用于标识是本地天地图切片库还是访问在线天地图
    	isOnline:true,
    
    	topLevelIndex : 0,
    	bottomLevelIndex : 20,
    	topTileFromX : -180,
    	topTileFromY : 90,
    	topTileToX : 180,
    	topTileToY : -270,
    
    	isBaseLayer : true,
    
    	initialize : function(name, url, options) {
    		options.topLevel = options.topLevel ? options.topLevel
    				: this.topLevelIndex;
    		options.bottomLevel = options.bottomLevel ? options.bottomLevel
    				: this.bottomLevelIndex;
    		options.maxResolution = this
    				.getResolutionForLevel(options.topLevel);
    		options.minResolution = this
    				.getResolutionForLevel(options.bottomLevel);
    		var newArguments = [ name, url, {}, options ];
    		OpenLayers.Layer.Grid.prototype.initialize.apply(this,
    				newArguments);
    	},
    
    	clone : function(obj) {
    
    		if (obj == null) {
    			obj = new OpenLayers.Layer.TiandituLayer(this.name,
    					this.url, this.options);
    		}
    
    		obj = OpenLayers.Layer.Grid.prototype.clone
    				.apply(this, [ obj ]);
    
    		return obj;
    	},
    
    	getURL : function(bounds) {
    		var level = this.getLevelForResolution(this.map.getResolution());
    		var coef = 360 / Math.pow(2, level);
    		var x_num = this.topTileFromX < this.topTileToX ? Math
    				.round((bounds.left - this.topTileFromX) / coef) : Math
    				.round((this.topTileFromX - bounds.right) / coef);
    		var y_num = this.topTileFromY < this.topTileToY ? Math
    				.round((bounds.bottom - this.topTileFromY) / coef)
    				: Math.round((this.topTileFromY - bounds.top) / coef);
    
    		var type = this.mapType;
    		var url = this.url;
    		if (this.mirrorUrls != null) {
    			url = this.selectUrl(x_num, this.mirrorUrls);
    		}
    		return this.getFullRequestString({
    			T : type,
    			X : x_num,
    			Y : y_num,
    			L : level
    		}, url);
    	},
    	getFullRequestString: function(params, url){
    		url = url+'?T='+params.T+'&L='+params.L+'&X='+params.X+'&Y='+params.Y;
    		return url;
    	},
    	selectUrl : function(a, b) {
    		return b[a % b.length]
    	},
    	getLevelForResolution : function(res) {
    		var ratio = this.getMaxResolution() / res;
    		if (ratio < 1)
    			return 0;
    		for ( var level = 0; ratio / 2 >= 1;) {
    			level++;
    			ratio /= 2;
    		}
    		return level;
    	},
    	getResolutionForLevel : function(level) {
    		return 360 / 256 / Math.pow(2, level);
    	},
    	getMaxResolution : function() {
    		return this.getResolutionForLevel(this.topLevelIndex)
    	},
    	getMinResolution : function() {
    		return this.getResolutionForLevel(this.bottomLevelIndex)
    	},
    	CLASS_NAME : "OpenLayers.Layer.TiandituLayer"
    }); 
    在代码中新建一个TiandituLayer,并添加到map中即可实现,代码如下:

    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <title>OpenLayers MapQuest Demo</title>
        <link rel="stylesheet" href="../../../../plugin/OpenLayers-2.13.1/theme/default/style.css" type="text/css">
        <script src="../../../../plugin/OpenLayers-2.13.1/OpenLayers.js"></script>
        <script src="TiandituLayer-src.js"></script>
        <style type="text/css">
            html, body, #map{
                padding:0;
                margin:0;
                height:100%;
                100%;
                overflow: hidden;
            }
        </style>
        <script type="text/javascript">
            var map;
            function init(){
                var vec_c = new OpenLayers.Layer.TiandituLayer("vec_c", "http://localhost:8081/lzugis/tdttile",{
                    mapType:"vec_c",
                    topLevel: 2,
                    bottomLevel: 10,
                    isBaseLayer:true,
                    isOnline:false
                });
                var cva_c = new OpenLayers.Layer.TiandituLayer("cva_c", "http://t0.tianditu.com/DataServer",{
                    mapType:"cva_c",
                    topLevel: 0,
                    bottomLevel: 18,
                    isBaseLayer:false,
                    isOnline:true
                });
                map = new OpenLayers.Map({
                    div: "map",
                    projection: "EPSG:4326",
                    layers: [cva_c,vec_c,img_c],
                    numZoomLevels:20,
                    center: [103.847, 36.0473],
                    zoom: 2
                });
                map.addControl(new OpenLayers.Control.LayerSwitcher());
                map.addControl(new OpenLayers.Control.MousePosition());
            }
        </script>
    </head>
    <body onload="init()">
    <div id="map"></div>
    </body>
    说明:

    1、代码中vec_c为天地图矢量层,cva_c为天地图标注层,与天地图的名称相一致;

    2、vec_c为离线的地图,cva_c为在线的,通过参数isOnline区分其为离线还是在线;


    完成后效果:





  • 相关阅读:
    shell 中的expect 用法
    Python下安装protobuf
    google protobuf 中的proto文件编写规则
    ubuntu 16.04 安装grpc
    python 常见的错误类型 和 继承关系
    倒排索引
    python 调用c函数
    python中的re模块,常用函数介绍
    leecode第二十二题(括号生成)
    leecode第十九题(删除链表的倒数第N个节点)
  • 原文地址:https://www.cnblogs.com/lzugis/p/6539795.html
Copyright © 2020-2023  润新知