Openlayers离线载入天地图

概述:

经过一个春节的休整,今天最终開始了!

任何时候。都不要忘记学习。学习是一辈子的事情!今天,我来说说怎样实现天地图的离线以及Openlayers载入离线数据实现天地图数据的展示。

实现:

1、获取天地图的数据

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

下载链接:http://pan.baidu.com/s/1dEmNtnF password: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。请求的结果例如以下所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />

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%;
            width: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区分其为离线还是在线。

完毕后效果:

时间: 2024-12-23 03:43:04

Openlayers离线载入天地图的相关文章

OpenLayers加载天地图

openlayer 是基于JavaScript的webGIS库 ,通过openlayer可以很容易的调用地图,并做相应的操作. 在head中载入openlayer的js文件: <link rel="stylesheet" href="https://openlayers.org/en/v4.1.1/css/ol.css" type="text/css"> <script src="jquery-1.11.1.min.j

OL记载Arcgis Server切片

概述: 本文讲述怎样在OpenLayers中调用Arcgis Server切片并显示. 思路: 在OpenLayers中载入Arcgis Server切片用XYZ图层,Arcgis Server的切片调用地址我们能够看到例如以下: 能够看到,切片的请求地址为http://localhost:6080/arcgis/rest/services/china/MapServer/z/y/x.当中,z为缩放级别,x,y分别为改切片距离tileOrigin的行列号.其计算方式为: var res = th

OpenLayers 3 之 加载天地图

要使用 OpenLayers 3 加载天地图,首先要弄清楚天地图发布的原理,以及遵循的发布规范,上一篇中我们提到了使用 OpenLayers 3 加载百度地图,我们提到一般网络地图为了加快访问速度,都采用缓存切片地图的方式,天地图也不例外,而且原理极其类似,但是其切片的索引组织方式还是有一些不同,虽然都是切片,但是切片的起始坐标原点不一致,百度地图是屏幕的左下角,而天地图是屏幕的左上角(与谷歌地图一致),且所在的坐标系是球形墨卡托投影坐标系(EPSG:3857). 针对这种形式发布的地图切片,O

使用openlayers 3 在线加载天地图及GeoServer发布的地图

使用openlayers3来加载天地图卫星图和标注图层,GeoServer发布地图,一并用openlayers测试加载出来,顺便实现了7种地图控件.下面直接贴代码: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport&q

openlayers应用(二):加载百度离线瓦片

上一篇文章介绍了使用openlayers3加载百度在线地图,对某些项目或应用场景比如不允许上外网的单位,某些项目只针对一定区域地图加载应用,比如一个县的地图,可以采用下载百度瓦片地图,在服务器或者本机单独部署的方式进行. 本篇主要讲述如何使用openlayers3调用下载的百度离线瓦片地图.瓦片地图下载器,网上有很多,在此不做详细描述. Openlayers3加载离线百度瓦片地图,效果以及代码如下: 代码如下: <!DOCTYPE html> <html xmlns="http

离线地图解决方案(一):加载瓦片地图

当前主流的在线地图有百度.高德.天地图.腾讯地图.google地图等.针对局域网内网内脱离要脱离互联网访问的应用,需要下载这些主流厂商的瓦片数据.网上有很多地图下载器软件可以下载地图瓦片,可以通过各种方式获取到这些地图厂商的瓦片数据. 加载高德离线瓦片数据: 加载高德街道瓦片: 地图加载代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtm

HTML5项目笔记5:使用HTML5 WebDataBase设计离线数据库

基于HTML5的Web DataBase 可以让你在浏览器中进行数据持久地存储管理和有效查询,假设你的离线应用程序有需要规范化的存储功能,那么使用Web DataBase,可以使你的应用程序无论是在离线或者在线或者网络不通畅情况下都可以将数据保存在客户端. 下面是HTML5 DataBase中两个不同的DataBase的比较,摘自http://www.html5rocks.com/en 上面的一篇文章. 我们这边使用WebSQL来设计和编写底层服务,W3C 的 WebDatabase 规范中说这

HTML5项目笔记3:使用Canvas设计离线系统的Logo

HTML5 的Cavans API可以动态来展示图形.图表.图像以及动画,我们的这个离线系统中,主要用来设计Logo用的.在网页上使用Canvas的时,他会创建一块矩形区域,默认情况下宽为300像素,高为150像素,当然,可以自定义. 因为我们离线系统主要职责用于在离线的情况下的工作系统,如在上面写工作日志,工作计划,和保存项目的评估数据:在网络在线的情况下与服务器交互,并将数据保存到Server的数据库中.所以我们的这个离线系统被命名为OFLMAIL,我们就根据这个名字来设计Logo. can

Web GIS离线解决方案

1.背景 在离线环境下(局域网中)的GIS系统中如何使用地图?这里的地图主要指的是地图底图,有了底图切片数据,我们就可以看到地图,在上面加上自己的业务数据图层,进行相关操作. 要在离线环境下看到GIS地图,就要有底图切片数据,地图的底图切片数据在一定时间内是不会变化的,可以使用一些地图下载器下载地图切片,如这个地图下载器. 在CS系统中可以基于GMap.Net来做,参考<百度谷歌离线地图解决方案>. 下面介绍下Web系统如何使用GIS切片数据,开发web GIS系统. 2.使用GeoWebCa