自從Google Earth 沒法訪問後,做爲開發者的我感同身受,很是理解那麼同行們的感覺。服務器
好在我已經下載了全國的地圖數據,抱着一顆數據來源於網絡服務於網絡的心態,我把微信
我手上的全國Google Earth 19級數據免費的開放給你們,旨在能盡一點綿薄之力,避免網絡
被那些不法之徒用來獲取暴利。函數
數據我已經上傳到百度雲盤:目前已經把全國31個省、直轄市、特別行政區數據已經徹底工具
傳到網盤,總量約10T左右。ui
須要的朋友,能夠經過微信搜索「LonlatWorld」微信號,獲取地圖。spa
固然若是有朋友特別急着用,也能夠經過郵寄硬盤給到我這邊,我會把全國的數據一併copy到硬盤3d
在回寄回去。指針
關於文件格式orm
一般咱們在工做中下載谷歌衛星影像數據時,輕則幾百M,重則幾百個G甚至上TB級。影像數據太大,是你們常常會遇到的一個問題,
尤爲是向下載一個省以上數據的時候該問題尤其突出。那麼該問題是否有一個比較好的解決方案呢?
以全球爲例,咱們以19級爲例,共有2^18 * 2^17 張瓦片,如此多的瓦片會讓磁盤越來越慢,同時也沒法維護。花費時間愈來愈長,最後不了了之。
當影像下載範圍比較大時,咱們能夠採用金字塔分塊下載的方式進行下載,系統會自動將大範圍分紅若干個塊,且塊與塊之間是能夠無縫拼接的。
通常狀況咱們選擇全球前10級別做爲基礎級別,因數據量不大(越1G)左右,後續以10級做爲基礎級別,
全球19級別數據被劃分爲 2^8 * 2^7(512 * 256)個塊。每一個塊中包含了512 * 256 張小瓦片。
採用高效的索引方式進行存儲,全球前10級別的數據存儲成一個文件(.fepk),11-19級別存儲爲n個文件。
例如全球第10級一共有 512 * 256 張瓦片(從第0級別開始計算),那麼全球11-19級別會有512 * 256 個文件(.fepk)
文件格式開放
做爲開發者深知每一家的地圖格式都不盡相同,都有本身的規則,我這裏把文件的存儲格式開發給你們,起到拋磚引玉的左右
期待有更好的存儲格式出現,共同提高國內GIS水平。
咱們通常不會直接採用瓦片做爲管理單元,會把一個塊做爲管理單元,把數據劃分爲索引文件與數據文件,以下所示:
數據文件:world.fepk
索引文件:world.fepk.idx
表 1字段說明
文件頭 |
字段 |
值 |
文件頭 |
char szMagic[20] |
fe.tile.store.data20字節 |
uint version |
版本號4字節 |
|
uint typeId |
數據類型 enumPKType { PK_IMAGE , PK_DEM, PK_VEC, PK_QXSY, PK_USER, };4字節 |
|
uint wgs84 |
是不是wgs84經緯投影4字節 |
|
uint flag |
4字節 |
|
uint64 timestamp |
時間戳8字節 |
|
real2 vStart |
經緯度最小範圍8*2字節 |
|
real2 vEnd |
經緯度最大範圍 8*2字節 |
|
LevSnaplevOff[24] |
級別索引,8 * 24 字節 |
|
char _reserve[240] |
保留 |
|
級別1 |
int2 _start |
2 * 4字節,瓦片最小行列號 |
int2 _end |
2 * 4字節,瓦片最大行列號 |
|
uint64 _offset |
8字節 |
|
uint64 _dataSize |
8字節 |
|
uint _lev |
4字節 |
|
char _reserve[216] |
216字節 |
|
瓦片數據索引矩陣數據PKTLHeader |
N * PKTLHeader N = (_end.x - _start.x + 1) * (_end.y - _start.y + 1) |
|
|
PKTLHeader |
|
級別2 |
|
|
級別3 |
|
|
級別… |
|
|
PKTLHeader定義:
struct PKTLHeader
{
/// 有無數據標記,即服務器上是否有該數據 0,無,1,有
uint64 _data:2;
/// 在本文件中是否已經存儲 0,無,1,有
uint64 _stored:2;
/// 狀態,
uint64 _state :6;
/// 數據地址,使用50個bit最大 2^54
/// 單個文件最大16 K T
uint64 _offset : 54;
/// 若是該值!= 0xFFFF,則有效,不然無效,
/// 使用該字段的意義在於解決網絡讀取問題,好比在雲盤上
/// 先讀取索引,若是沒有數據大小,或者數據大小存儲在數據文件中,則須要
/// 再次訪問數據文件,才能夠得大小,增長額外的IO,同時兼顧大小,該變量最大能夠存儲64K
/// 若是超過了64K,那麼同樣的須要訪問數據文件獲取大小
ushort _dataSize;
};
共計10自字節
LevSnap定義:
struct LevSnap
{
uint64 _lev:8;
uint64 _offset:56;
};
共計8字節
文件頭 |
字段 |
值 |
文件頭 |
char szMagic[20] |
fe.tile.store.data20字節 |
uint version |
版本號4字節 |
|
uint typeId |
數據類型 enumPKType { PK_IMAGE , PK_DEM, PK_VEC, PK_QXSY, PK_USER, };4字節 |
|
uint wgs84 |
是不是wgs84經緯投影4字節 |
|
uint flag |
4字節 |
|
uint64 timestamp |
時間戳8字節 |
|
real2 vStart |
經緯度最小範圍8*2字節 |
|
real2 vEnd |
經緯度最大範圍 8*2字節 |
|
LevSnaplevOff[24] |
級別索引,8 * 24 字節 |
|
char _reserve[240] |
保留 |
|
數據0 |
Int4 |
4*4字節,行號,列號,級別,大小 |
數據 |
|
|
數據1 |
Int4 |
4*4字節,行號,列號,級別,大小 |
數據 |
|
|
數據… |
Int4 |
4*4字節,行號,列號,級別,大小 |
數據 |
|
1.3 訪問SDK
爲了方便你們使用數據,提供了C語言版本的SDK(x86/x64)兩個版本
#pragma once typedef void* FEPKFile; #pragma pack (push,1) /// 該文件不能夠被修改 typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned __int64 uint64; struct FEPHHeader { /// 有無數據標記,即服務器上是否有該數據 0,無,1,有 uint64 _data : 2; /// 在本文件中是否已經存儲 0,無,1,有 uint64 _stored : 2; /// 狀態, uint64 _state : 6; /// 數據地址,使用50個bit最大 2^54 /// 單個文件最大16 K T uint64 _offset : 54; /// 若是該值!= 0xFFFF,則有效,不然無效, /// 使用該字段的意義在於解決網絡讀取問題,好比在雲盤上 /// 先讀取索引,若是沒有數據大小,或者數據大小存儲在數據文件中,則須要 /// 再次訪問數據文件,才能夠得大小,增長額外的IO,同時兼顧大小,該變量最大能夠存儲64K /// 若是超過了64K,那麼同樣的須要訪問數據文件獲取大小 ushort _dataSize; }; #pragma pack(pop) extern "C" { /// <summary> /// 打開文件函數,能夠打開索引也能夠打開數據文件 /// </summary> /// <param name = "fileName">文件名稱</param> /// <return>0:失敗,不然成功</return> FEPKFile fepkOpenFile(const char* fileName); /// <summary> /// 讀取索引數據函數 /// </summary> /// <param name = "file">索引文件指針</param> /// <param name = "x">列號</param> /// <param name = "y">行號</param> /// <param name = "z">級別</param> /// <param name = "header">返回文件頭信息</param> /// <return>true:false</return> bool fepkReadHeader(FEPKFile file,int x,int y,int z,FEPHHeader* header); /// <summary> /// 根據文件頭信息讀取文件大小(瓦片數據大小) /// </summary> /// <param name = "file">索引文件指針</param> /// <param name = "header">文件頭信息</param> /// <param name = "pSize">輸出文件大小</param> /// <return>true:false</return> bool fepkReadDataSize(FEPKFile file,const FEPHHeader* header,uint* pSize); /// <summary> /// 讀取瓦片數據函數 /// </summary> /// <param name = "file">索引文件指針</param> /// <param name = "header">文件頭信息</param> /// <param name = "pBuf">輸入緩衝區大小</param> /// <param name = "nBufLen">緩衝區長度</param> /// <return> -1:失敗,0:無數據,>0 數據的真實大小</return> int fepkReadData(FEPKFile file,const FEPHHeader* header,void* pBuf,uint nBufLen); /// <summary> /// 關閉文件 /// </summary> void fepkCloseFile(FEPKFile file); /// <summary> /// 導出文件 /// </summary> /// <param name = "fileName">輸入緩衝區大小</param> /// <param name = "dir">目標文件夾</param> bool fepkExport(const char* fileName,const char* dir); /// <summary> /// 導出文件 /// </summary> /// <param name = "fileName">輸入緩衝區大小</param> /// <param name = "dir">目標文件夾</param> bool fepkExportWithLevs(const char* fileName, const char* dir,const unsigned* levs,unsigned levSize); } /// <summary> /// 使用說明 /// FEPKFile file = fepkOpenFile("x:/xx/yy/abc/world0-8.fepk"); /// if (file == nullptr) /// { /// return; /// } /// FEPHHeader header; /// uint nSize = 0; /// if(!fepkReadHeader(file,0,0,0,&header)) /// { /// return; /// } /// /// if(!fepkReadDataSize(file,&header,&nSize)) /// { /// return; /// } /// char* pBuf = new char[nSize]; /// if(!fepkReadData(file,&header,pBuf,nSize)) /// { /// delete []pBuf; /// } /// </summary>
1.4數據解包工具,即將.fepk數據解壓成標準的瓦片
上述文件文檔等數據均可以在QQ羣中獲取
QQ羣號(600975169)
二維碼: