- 浏览: 7330640 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (1546)
- 企业中间件 (236)
- 企业应用面临的问题 (236)
- 小布Oracle学习笔记汇总 (36)
- Spring 开发应用 (54)
- IBatis开发应用 (16)
- Oracle基础学习 (23)
- struts2.0 (41)
- JVM&ClassLoader&GC (16)
- JQuery的开发应用 (17)
- WebService的开发应用 (21)
- Java&Socket (44)
- 开源组件的应用 (254)
- 常用Javascript的开发应用 (28)
- J2EE开发技术指南 (163)
- EJB3开发应用 (11)
- GIS&Mobile&MAP (36)
- SWT-GEF-RCP (52)
- 算法&数据结构 (6)
- Apache开源组件研究 (62)
- Hibernate 学习应用 (57)
- java并发编程 (59)
- MySQL&Mongodb&MS/SQL (15)
- Oracle数据库实验室 (55)
- 搜索引擎的开发应用 (34)
- 软件工程师笔试经典 (14)
- 其他杂项 (10)
- AndroidPn& MQTT&C2DM&推技术 (29)
- ActiveMQ学习和研究 (38)
- Google技术应用开发和API分析 (11)
- flex的学习总结 (59)
- 项目中一点总结 (20)
- java疑惑 java面向对象编程 (28)
- Android 开发学习 (133)
- linux和UNIX的总结 (37)
- Titanium学习总结 (20)
- JQueryMobile学习总结 (34)
- Phonegap学习总结 (32)
- HTML5学习总结 (41)
- JeeCMS研究和理解分析 (9)
最新评论
-
lgh1992314:
[u][i][b][flash=200,200][url][i ...
看看mybatis 源代码 -
尼古拉斯.fwp:
图片根本就不出来好吧。。。。。。
Android文件图片上传的详细讲解(一)HTTP multipart/form-data 上传报文格式实现手机端上传 -
ln94223:
第一个应该用排它网关吧 怎么是并行网关, 并行网关是所有exe ...
工作流Activiti的学习总结(八)Activiti自动执行的应用 -
ZY199266:
获取不到任何消息信息,请问这是什么原因呢?
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息 -
xiaoyao霄:
DestinationSourceMonitor 报错 应该导 ...
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息
GIS的学习(四十二)osmdroid基于离线地图的几种格式
在osmdroid中支持多种离线地图格式,其中sqlite,mbtiles,zip,gemf等格式,那么他们的格式有什么不同呢?
下面我们慢慢来研究一下源代码既可以知道。
针对ArchiveFileFactory的类查看如下:
package org.osmdroid.tileprovider.modules; import java.io.File; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import android.database.sqlite.SQLiteException; public class ArchiveFileFactory { private static final Logger logger = LoggerFactory.getLogger(ArchiveFileFactory.class); /** * Return an implementation of {@link IArchiveFile} for the specified file. * @return an implementation, or null if there's no suitable implementation */ public static IArchiveFile getArchiveFile(final File pFile) { if (pFile.getName().endsWith(".zip")) { try { return ZipFileArchive.getZipFileArchive(pFile); } catch (final IOException e) { logger.error("Error opening ZIP file", e); } } if (pFile.getName().endsWith(".sqlite")) { try { return DatabaseFileArchive.getDatabaseFileArchive(pFile); } catch (final SQLiteException e) { logger.error("Error opening SQL file", e); } } if (pFile.getName().endsWith(".mbtiles")) { try { return MBTilesFileArchive.getDatabaseFileArchive(pFile); } catch (final SQLiteException e) { logger.error("Error opening MBTiles SQLite file", e); } } if (pFile.getName().endsWith(".gemf")) { try { return GEMFFileArchive.getGEMFFileArchive(pFile); } catch (final IOException e) { logger.error("Error opening GEMF file", e); } } return null; } }
其中sqlite格式如下:存储的表名为:tiles字段为tile,key,provider,
具体实现如下:
package org.osmdroid.tileprovider.modules; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import org.osmdroid.tileprovider.MapTile; import org.osmdroid.tileprovider.tilesource.ITileSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; public class DatabaseFileArchive implements IArchiveFile { private static final Logger logger = LoggerFactory.getLogger(DatabaseFileArchive.class); private final SQLiteDatabase mDatabase; private DatabaseFileArchive(final SQLiteDatabase pDatabase) { mDatabase = pDatabase; } public static DatabaseFileArchive getDatabaseFileArchive(final File pFile) throws SQLiteException { return new DatabaseFileArchive(SQLiteDatabase.openOrCreateDatabase(pFile, null)); } @Override public InputStream getInputStream(final ITileSource pTileSource, final MapTile pTile) { try { InputStream ret = null; final String[] tile = {"tile"}; final long x = (long) pTile.getX(); final long y = (long) pTile.getY(); final long z = (long) pTile.getZoomLevel(); final long index = ((z << z) + x << z) + y; final Cursor cur = mDatabase.query("tiles", tile, "key = " + index + " and provider = '" + pTileSource.name() + "'", null, null, null, null); if(cur.getCount() != 0) { cur.moveToFirst(); ret = new ByteArrayInputStream(cur.getBlob(0)); } cur.close(); if(ret != null) { return ret; } } catch(final Throwable e) { logger.warn("Error getting db stream: " + pTile, e); } return null; } @Override public String toString() { return "DatabaseFileArchive [mDatabase=" + mDatabase.getPath() + "]"; } }
格式为mbtiles的数据结构:
// TABLE tiles (zoom_level INTEGER, tile_column INTEGER, tile_row INTEGER, tile_data BLOB); public final static String TABLE_TILES = "tiles"; public final static String COL_TILES_ZOOM_LEVEL = "zoom_level"; public final static String COL_TILES_TILE_COLUMN = "tile_column"; public final static String COL_TILES_TILE_ROW = "tile_row"; public final static String COL_TILES_TILE_DATA = "tile_data";
具体实现:
package org.osmdroid.tileprovider.modules; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import org.osmdroid.tileprovider.MapTile; import org.osmdroid.tileprovider.tilesource.ITileSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; public class MBTilesFileArchive implements IArchiveFile { private static final Logger logger = LoggerFactory.getLogger(MBTilesFileArchive.class); private final SQLiteDatabase mDatabase; // TABLE tiles (zoom_level INTEGER, tile_column INTEGER, tile_row INTEGER, tile_data BLOB); public final static String TABLE_TILES = "tiles"; public final static String COL_TILES_ZOOM_LEVEL = "zoom_level"; public final static String COL_TILES_TILE_COLUMN = "tile_column"; public final static String COL_TILES_TILE_ROW = "tile_row"; public final static String COL_TILES_TILE_DATA = "tile_data"; private MBTilesFileArchive(final SQLiteDatabase pDatabase) { mDatabase = pDatabase; } public static MBTilesFileArchive getDatabaseFileArchive(final File pFile) throws SQLiteException { return new MBTilesFileArchive( SQLiteDatabase.openDatabase( pFile.getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY)); } @Override public InputStream getInputStream(final ITileSource pTileSource, final MapTile pTile) { try { InputStream ret = null; final String[] tile = { COL_TILES_TILE_DATA }; final String[] xyz = { Integer.toString(pTile.getX()) , Double.toString(Math.pow(2, pTile.getZoomLevel()) - pTile.getY() - 1) // Use Google Tiling Spec , Integer.toString(pTile.getZoomLevel()) }; final Cursor cur = mDatabase.query(TABLE_TILES, tile, "tile_column=? and tile_row=? and zoom_level=?", xyz, null, null, null); if(cur.getCount() != 0) { cur.moveToFirst(); ret = new ByteArrayInputStream(cur.getBlob(0)); } cur.close(); if(ret != null) { return ret; } } catch(final Throwable e) { logger.warn("Error getting db stream: " + pTile, e); } return null; } @Override public String toString() { return "DatabaseFileArchive [mDatabase=" + mDatabase.getPath() + "]"; } }
GEMF文件格式的:
GEMF格式的文件存储算法比较复杂,但是据说为加载最快的方式。
package org.osmdroid.tileprovider.modules; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import org.osmdroid.tileprovider.MapTile; import org.osmdroid.tileprovider.tilesource.ITileSource; import org.osmdroid.util.GEMFFile; public class GEMFFileArchive implements IArchiveFile { private final GEMFFile mFile; private GEMFFileArchive(final File pFile) throws FileNotFoundException, IOException { mFile = new GEMFFile(pFile); } public static GEMFFileArchive getGEMFFileArchive(final File pFile) throws FileNotFoundException, IOException { return new GEMFFileArchive(pFile); } @Override public InputStream getInputStream(final ITileSource pTileSource, final MapTile pTile) { return mFile.getInputStream(pTile.getX(), pTile.getY(), pTile.getZoomLevel()); } @Override public String toString() { return "GEMFFileArchive [mGEMFFile=" + mFile.getName() + "]"; } }
ZIP格式:
package org.osmdroid.tileprovider.modules; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import org.osmdroid.tileprovider.MapTile; import org.osmdroid.tileprovider.tilesource.ITileSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ZipFileArchive implements IArchiveFile { private static final Logger logger = LoggerFactory.getLogger(ZipFileArchive.class); private final ZipFile mZipFile; private ZipFileArchive(final ZipFile pZipFile) { mZipFile = pZipFile; } public static ZipFileArchive getZipFileArchive(final File pFile) throws ZipException, IOException { return new ZipFileArchive(new ZipFile(pFile)); } @Override public InputStream getInputStream(final ITileSource pTileSource, final MapTile pTile) { final String path = pTileSource.getTileRelativeFilenameString(pTile); try { final ZipEntry entry = mZipFile.getEntry(path); if (entry != null) { return mZipFile.getInputStream(entry); } } catch (final IOException e) { logger.warn("Error getting zip stream: " + pTile, e); } return null; } @Override public String toString() { return "ZipFileArchive [mZipFile=" + mZipFile.getName() + "]"; } }
实现:最初显示”中国地图(省界)“,放大到一定程度显示”中国地图(地市分界)“,继续放大切换到Google街道地图。
<!DOCTYPE html> <html> <head> <title>中国地图</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="css/style.css" type="text/css" /> <style type="text/css" media="screen"> body { margin:0; padding:0; height:100%; } .bigmap { position:absolute; left:0; top:0px; padding:0; width:100%; height:100%; border:1px solid #333; } </style> <script type="text/javascript" src="js/OpenLayers/lib/OpenLayers.js"></script> <script src="http://maps.google.com/maps/api/js?v=3.6&sensor=false"></script> <script type="text/javascript"> var map, layer_province, layer_city, layer_street, vlayer; // 第一次打开地图的中心位置(经度、纬度) var firstLon = 109.33981; var firstLat = 33.72419; /* * 切换地图比例尺设置 * scale1: * scale2: 省地图和地市地图切换点 * scale3: 地市地图和谷歌街道地图切换点 */ var scale1 = 20000000; var scale2 = 10000000; var scale3 = 2000000; var level1 = 1; var level2 = 2; var level3 = 3; var level = level1; function init() { // 创建MAP DIV框架 map = new OpenLayers.Map("map", { maxResolution: 'auto', maxExtent: new OpenLayers.Bounds( 73.44696044921875, 6.318641185760498, 135.08583068847656, 53.557926177978516), displayProjection: new OpenLayers.Projection("EPSG:4326") }); // 增加中国地图(省界) Layer addProvinceLayer() // 增加中国地图(地市分界) Layer addCityLayer(); // 增加Google Street Layer addStreetLayer(); // 增加地图Layer切换Register addMapRegister(); map.zoomToMaxExtent(); map.setCenter(new OpenLayers.LonLat(firstLon, firstLat), 0); map.addControl(new OpenLayers.Control.Scale()); map.addControl(new OpenLayers.Control.MousePosition()); map.addControl(new OpenLayers.Control.LayerSwitcher()); } function addProvinceLayer() { layer_province = new OpenLayers.Layer.WMS( "China:province", "http://10.0.0.239:8081/geoserver/wms", { layers: "China:province", }, { singleTile: true, //set single label isBaseLayer: true, projection: "EPSG:4326", maxExtent: new OpenLayers.Bounds( 73.44696044921875, 6.318641185760498, 135.08583068847656, 53.557926177978516) } ); map.addLayer(layer_province); } function addCityLayer() { layer_city = new OpenLayers.Layer.WMS( "China:city", "http://10.0.0.239:8081/geoserver/wms", { layers: "China:city" }, { singleTile: true, //set single label visibility: false, projection: "EPSG:4326", displayInLayerSwitcher: false, maxExtent: new OpenLayers.Bounds( 73.44696044921875, 6.318641185760498, 135.08583068847656, 53.557926177978516) } ); map.addLayer(layer_city); } function addStreetLayer() { layer_street = new OpenLayers.Layer.Google( "Google Streets", // the default { numZoomLevels: 18 , projection: "EPSG:900913", visibility: false, displayInLayerSwitcher: false, maxExtent: new OpenLayers.Bounds( -128 * 156543.03390625, -128 * 156543.03390625, 128 * 156543.03390625, 128 * 156543.03390625) } ); map.addLayer(layer_street); } function addMapRegister(){ map.events.register("zoomend", map, function(){ var cur_scale = map.getScale(); if(cur_scale >= scale2) { if(level != level1) { if(level == level2) { map.setCenter(map.center.transform( new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:4326") ), map.getZoom()); } else { map.setCenter(map.center.transform( new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326") ), map.getZoom()); } level = level1; layer_province.displayInLayerSwitcher = true; layer_city.displayInLayerSwitcher = false; layer_street.displayInLayerSwitcher = false; map.setBaseLayer(layer_province); layer_city.setVisibility(false); layer_street.setVisibility(false); } } else if(cur_scale < scale2 && cur_scale >= scale3){ if(level != level2){ if(level == level1) { map.setCenter(map.center.transform( new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:4326") ), map.getZoom()); } else { map.setCenter(map.center.transform( new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326") ), map.getZoom()); } level = level2; layer_province.displayInLayerSwitcher = false; layer_city.displayInLayerSwitcher = true; layer_street.displayInLayerSwitcher = false; map.setBaseLayer(layer_city); layer_province.setVisibility(false); layer_street.setVisibility(false); } } else if(cur_scale < scale3){ if(level != level3) { map.setCenter(map.center.transform( new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913") ), map.getZoom()); level = level3; layer_province.displayInLayerSwitcher = false; layer_city.displayInLayerSwitcher = false; layer_street.displayInLayerSwitcher = true; map.setBaseLayer(layer_street); layer_city.setVisibility(false); layer_province.setVisibility(false); } } }); } </script> </head> <body onload="init()" > <div id="map" class="bigmap"></div> </body> </html>
参考:
发表评论
-
TestNG简单的学习(十三)TestNG中Junit的实现
2013-12-04 09:00 3353TestNG和junit的整合 ... -
TestNG简单的学习(十二)TestNG运行
2013-12-03 09:08 51575文档来自官方地址: ... -
TestNG简单的学习(十一)TestNG学习总结
2013-12-03 09:08 14176最近一直在学习关于TestNG方面的知识,根 ... -
TestNG简单的学习(十)TestNG @Listeners 的使用
2013-12-03 09:07 8688TestNG官方网站: http://testng.or ... -
TestNG简单的学习(九)TestNG Method Interceptors 的使用
2013-12-03 09:07 2711TestNG官方网站: http://testng ... -
TestNG简单的学习(八)TestNG Annotation Transformers 的使用
2013-12-03 09:07 2805TestNG官方网站: http://testng.or ... -
TestNG简单的学习(七)TestNG编程方式运行
2013-12-02 09:22 2450TestNG官方网站: http://testng.or ... -
TestNG简单的学习(六)测试工厂注释的使用
2013-12-02 09:22 2779TestNG官方网站: http://testng.or ... -
TestNG简单的学习(五)参数化测试数据的定制
2013-12-02 09:22 2698TestNG官方网站: http://testng.or ... -
TestNG简单的学习(四)测试方法通过名称名称依赖实现
2013-12-02 09:21 2079TestNG官方网站: http://testng.or ... -
TestNG简单的学习(三)测试方法通过测试分组依赖实现
2013-12-02 09:21 2825TestNG官方网站: http://testng.or ... -
TestNG简单的学习(二)参数化测试并发且多方法测试方法判定
2013-11-29 15:35 3694TestNG官方网站: http://testng.or ... -
TestNG简单的学习(一)类和方法级别@Test的区别
2013-11-29 15:31 9420TestNG官方文档的地址: http://testng ... -
Feed4Junit的简单使用(七)Feed4TestNg
2013-11-29 13:35 6129在Feed4Junit主要针对junit实现的 ... -
Feed4Junit的简单使用(六)数据来特定格式文件
2013-11-29 12:29 2763Feed4Junit官方地址: http://da ... -
Feed4Junit的简单使用(五)数据来自动态约束数据
2013-11-29 12:29 2624Feed4Junit官方地址: http://datab ... -
Feed4Junit的简单使用(四)数据来自定义数据源
2013-11-28 14:09 3095Feed4Junit官方地址: http://databe ... -
Feed4Junit的简单使用(三)数据源来自数据库
2013-11-28 13:58 3164Feed4Junit官方地址: http://databe ... -
Feed4Junit的简单使用(二)数据源来自文件
2013-11-28 13:50 4565Feed4Junit官方地址: http://datab ... -
Feed4Junit的简单使用(一)
2013-11-28 13:47 2207Feed4Junit官方地址: http://databe ...
相关推荐
GIS地图,全称为地理信息系统(Geographic Information System),是一种能够采集、存储、管理、分析和展示与地理位置相关数据的技术系统。在本资源中,我们关注的是GIS地图的一个具体应用——百度地图的离线版本,...
离线地图技术是一种在无网络连接的情况下仍能使用地图服务的技术,它对于户外探险、旅行、或者在数据网络不稳定或昂贵的地区尤为重要。本资源主要围绕“离线地图学习”展开,通过电子书、源代码和文档片段提供了一个...
在IT行业中,ArcGIS是一款...通过以上步骤,我们可以构建一个基于JavaScript、ArcGIS API for JavaScript和HTML的离线地图应用,让内网用户能够在没有互联网连接的情况下,依然能够浏览和操作地图,满足GIS应用的需求。
同时,本文也提供了一种基于Python的离线Google地图操作实现方法,可以为GIS系统开发提供便利。 关键词:Google地图;离线;地图瓦片;地图操作 一、引言 互联网技术和地图测绘技术的发展推动了一系列与地图相关...
在本文中,我们将详细探讨如何使用osmdroid加载GeoPackage格式的离线地图数据。 GeoPackage是一种开放标准的数据容器,由Open Geospatial Consortium (OGC)制定,用于存储地理空间信息。它可以包含多种地理数据类型...
本文将详细探讨如何使用C#语言加载三种常见的离线地图格式:MMPK(Mobile Map Package)、SHP(Shapefile)和TPK(Tile Package)。 首先,MMPK是Esri公司推出的一种离线地图包格式,它包含了地图数据、样式、元...
本文以“基于互联网离线地图的导航地图制作及应用”为主题,深入探讨了互联网离线地图的制作方法和应用过程。 一、互联网离线地图的概念和价值 互联网离线地图是指在没有网络连接的情况下,依然可以在终端设备上...
通过这个DEMO,开发者可以学习到如何使用OpenLayers来创建和展示离线地图,这对于在没有网络连接或者网络不稳定的情况下仍然需要地图服务的场景非常有用。同时,这也是对OpenLayers API的一个基础实践,为进一步开发...
在IT领域,尤其是在GIS(地理信息系统)开发中,制作和使用离线地图是常见的需求。本文将详细解析“C# WinForm 百度离线瓦片地图”这一主题,包括其核心概念、实现原理以及相关功能。 首先,我们需要了解什么是瓦片...
LeafLet是一款轻量级的JavaScript库,专门用于创建交互式地图。它以其简单易用、高性能和灵活性而受到开发者喜爱。...通过学习和实践这些示例,你可以快速掌握LeafLet离线地图的开发技巧,并应用于实际项目中。
全球离线地图是一种在无网络连接的情况下仍能使用的地图服务,它通过提前下载地图数据到本地设备,确保用户能够在旅行、户外活动或者网络不稳定时查阅地图。这些地图通常包括多种层级,例如本资源中的1-6级,层级...
LeafLet是一款轻量级的JavaScript库,专门用于创建交互式的二维地图。它的设计目标是简单易用,同时提供了丰富的功能,使得开发者可以轻松地在网页上集成地图,并对其进行自定义。LeafLet尤其适合那些需要在网页上...
MBTiles是一种将地图切片存储为SQLite数据库格式的离线地图标准,包含了一整套预渲染的地图图像,适用于各种设备和平台。 一、MBTiles离线地图包介绍 MBTiles由Zachary Forest Johnson在2011年提出,其核心是SQLite...
离线地图技术是移动设备和桌面应用中的一种重要功能,特别是在网络覆盖不稳定或者数据流量有限的情况下,它使得用户能够在无网络连接时仍然可以查看和使用地图。离线地图的实现涉及多个技术领域,包括地理信息系统...
TPK(Tile Package)是Esri(ArcGIS的主要开发者)推出的一种离线地图格式,它允许用户在没有互联网连接的情况下使用GIS数据。TPK文件将地图切片、元数据和相关的地理空间信息打包在一起,便于在ArcGIS桌面、移动...
它支持多种在线地图服务,包括Google Maps,Bing Maps,OpenStreetMap等,并且具有离线地图的功能,允许用户在没有网络连接的情况下使用地图。本文将深入探讨GMap.NET的核心特性、离线地图的下载与使用,以及如何...
离线地图制作工具是一种专为在无网络环境下查看和使用地图而设计的软件或应用程序。这类工具通常允许用户下载特定区域的地图数据,并在本地设备上进行存储和浏览,避免了在网络不稳定或者没有网络覆盖时无法查看地图...
这个工具可能包括自动化下载、格式转换以及存储管理等功能,简化了离线地图的构建过程。 接着,我们来看看JavaScript(js)和C#(c#)的角色。JavaScript,一种广泛用于前端开发的语言,通常通过百度地图API来交互...
【全国电子离线地图】是一种特别适用于内网环境使用的资源,它允许用户在没有网络连接的情况下查看和使用地图数据。这种地图系统对于那些网络不稳定或无法访问互联网的地区尤其有用,比如偏远地区或者网络受限的环境...