- 浏览: 7246131 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (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 3284TestNG和junit的整合 ... -
TestNG简单的学习(十二)TestNG运行
2013-12-03 09:08 51437文档来自官方地址: ... -
TestNG简单的学习(十一)TestNG学习总结
2013-12-03 09:08 13990最近一直在学习关于TestNG方面的知识,根 ... -
TestNG简单的学习(十)TestNG @Listeners 的使用
2013-12-03 09:07 8618TestNG官方网站: http://testng.or ... -
TestNG简单的学习(九)TestNG Method Interceptors 的使用
2013-12-03 09:07 2648TestNG官方网站: http://testng ... -
TestNG简单的学习(八)TestNG Annotation Transformers 的使用
2013-12-03 09:07 2753TestNG官方网站: http://testng.or ... -
TestNG简单的学习(七)TestNG编程方式运行
2013-12-02 09:22 2395TestNG官方网站: http://testng.or ... -
TestNG简单的学习(六)测试工厂注释的使用
2013-12-02 09:22 2709TestNG官方网站: http://testng.or ... -
TestNG简单的学习(五)参数化测试数据的定制
2013-12-02 09:22 2637TestNG官方网站: http://testng.or ... -
TestNG简单的学习(四)测试方法通过名称名称依赖实现
2013-12-02 09:21 2025TestNG官方网站: http://testng.or ... -
TestNG简单的学习(三)测试方法通过测试分组依赖实现
2013-12-02 09:21 2760TestNG官方网站: http://testng.or ... -
TestNG简单的学习(二)参数化测试并发且多方法测试方法判定
2013-11-29 15:35 3629TestNG官方网站: http://testng.or ... -
TestNG简单的学习(一)类和方法级别@Test的区别
2013-11-29 15:31 9375TestNG官方文档的地址: http://testng ... -
Feed4Junit的简单使用(七)Feed4TestNg
2013-11-29 13:35 6077在Feed4Junit主要针对junit实现的 ... -
Feed4Junit的简单使用(六)数据来特定格式文件
2013-11-29 12:29 2686Feed4Junit官方地址: http://da ... -
Feed4Junit的简单使用(五)数据来自动态约束数据
2013-11-29 12:29 2558Feed4Junit官方地址: http://datab ... -
Feed4Junit的简单使用(四)数据来自定义数据源
2013-11-28 14:09 3036Feed4Junit官方地址: http://databe ... -
Feed4Junit的简单使用(三)数据源来自数据库
2013-11-28 13:58 3092Feed4Junit官方地址: http://databe ... -
Feed4Junit的简单使用(二)数据源来自文件
2013-11-28 13:50 4519Feed4Junit官方地址: http://datab ... -
Feed4Junit的简单使用(一)
2013-11-28 13:47 2153Feed4Junit官方地址: http://databe ...
相关推荐
NULL 博文链接:https://topmanopensource.iteye.com/blog/1637317
gis地图 百度地图离线版(江苏省瓦片至13级),需要其他省份瓦片请下载专门下载工具下载吧,太多了。
VUE 离线地图的下载与使用,下载瓦片离线使用
js+arcgis+html 开发一个arcgis离线地图加载,显示离线地图,在内网访问。。。。
.net 开发gis 加载离线文件 mmpk, shp,tpk完整源代码,并包含gis sdk 安装包 C#
LeafLet离线地图案例demo集合非常详细,功能多,实用性强。
tpk 文件,离线地图,arcgis,gis qgis,ucmap,里都可以加载
Arcgis android 离线地图 缓存制作 教程
PC离线地图服务
离线地图GIS与设备远程监测方案,C++实现离线本地地图拼接、平移、缩放、经纬度坐标与地图摩托卡坐标转换。 可以管理设备,每个设备以一个图标在地图上标注。 可在地图任意位置叠加文字和图形。
ArcGIS API For Android离线地图的实现
此实例为vue版本三维GIS地图,其中包含底图切换、图层控制、图上量算、空间分析、坐标定位、图上标绘、地图打印等功能
离线地图可视化解决方案(方案).pdf
百度地图api离线版,基于api2.0,带demo和示例数据,支持google地图转换,转换所需的GoogleToBaidu.jar也在本压缩包内
极地图.NET控件为二次开发而生,无需购买地图数据即可快速构建桌面GIS地图应用。专业、简单、易用的二次开发接口,可应用于学术科研、工程、规划、设计等工作,在测绘、地址、交通、电力、水利、农业、林业和旅游等...
研究了好几天终于研究出来了,教你从瓦片下载到离线加载轻松实现arcgis加载google离线地图。帮你学习少走弯路!
最新谷歌离线包,html里面的js代码含...1、离线地图加载,缩小到第四级别可以看见离线地图。 2、影像图与路网图叠加 3、坐标系转换 4、两种不同风格的轨迹回放 5、添加marker点和信息 对于新手来说,非常具有参考价值。
离线式移动GIS关键技术研究
离线地图API+地图瓦片工具,解压密码123456 离线地图API+地图瓦片工具,解压密码123456