FastTileDatabase
轻量级高性能瓦片地图数据库
Loading...
Searching...
No Matches
Fast Tile Database

Fast Tile Database 简称 FTD,是一款基于c/c++开发的轻量级高性能跨平台地图瓦片数据

库,设计之初主要是用来解决全球卫星影像的存储管理。常见的存储方式包括本地磁盘以瓦

片坐标的形式规整存储碎片化的瓦片文件,或者使用常规数据库或空间数据库进行存储,但

需要对数据进行迁移或部分数据从原有数据中提取出来使用时,这些方式往往不够便捷或者

效率非常低下,如果让你把全球的数据进行备份,或者从全球的数据中提取某一个省的某几

个级别的数据单独使用时,你需要花费多久时间才能解决?FTD 以单文件的形式存储,它具

有空间范围,对瓦片数据的访问时间复杂度为 O(1),可以直接通过范围对数据进行遍历操

作,结构化的存储模式,可以充分利用磁盘的存储空间,节约储存硬件成本。

FTD 的存储结构趋向于 LSM 储存结构,在写入数据时以竟可能将缓存区的数据规整为顺序结

构写入磁盘。建议在向瓦片数据库写入数据时,遵循从左到右,从上到下的顺序。

示例数据

谷歌地球全球 2-10 级基础数据 【提取码 8888】

安装

快速开始

本章节将通过简单 c++ 示例代码告诉您如何创建文件,以及对文件进行写入、读取、更新、

删除操作,如果您对 c++ 熟悉并且有一些 GIS 基础,相信您可能仅需要花费几分钟就可以熟

悉 FTD 的操作。

  • 创建文件
#include "FTD.h"
//定义数据范围
MeFTDExtent exent
exent.MinX = -180.0;
exent.MinY = -90.0;
exent.MaxX = 180.0;
exent.MaxY = 90.0;
//创建文件时同时进行初始化的级别
MeFTDZooms initZooms;
for(int zoom=0; zoom<10; zoom++)
initZooms.push_back(zoom);
//创建文件
MeFTDHandler* pFTDHandler = MeFTDHandler::FTDBuilder()
.setFileName("D:\\myftd.ftd") //文件路径
.setExtent(exent) //文件数据范围
.setFormat(FMT_JPEG) //文件存储格式
.setZoomRange(0, 18) //最小和最大级别
.setEPSG(FTD_WGS_84_EPSG) //投影
.setInitRes(360.0 / 256.0) //初始分辨率
.setInitZooms(initZooms) //初始化级别
.setOverwrite(true) //覆盖已存在文件
.setDescription("附加信息") //自定义描述内容
.build() //构建文件
//判断是否创建成功
if(nullptr == pFTDHandler)
//创建失败
#define FTD_WGS_84_EPSG
Definition: MeFTDApi.h:12
注:创建文件以后,并不会立即打开文件。
  • 写入数据
/*判断文件句柄是否有效*/
if(nullptr == pFTDHandler)
return;
/*打开文件准备写入*/
if(false == pFTDHandler->open(MeFTDHandler::WriteOnly))
return;
/*准备写入的缓存以及缓存大小*/
int nBufferSize = 0;
MeFTDTileData pBuffer = nullptr;
...获取缓存数据
/*写入数据*/
MeFTDTileKey tileKey(0, 0, 0);
bool bOk = pFTDHandler->write(tileKey, pBuffer, nBufferSize);
/*写入成功,将数据同步到磁盘*/
if(bOk)
pFTDHandler->flush();
/*销毁瓦片缓存数据*/
MeFTDHandler::destroyTileData(pBuffer);
/*写入完成,关闭文件句柄*/
pFTDHandler->close();
/*销毁文件句柄*/
MeFTDHandler::destroy(pFTDHandler);
  • 读取数据
/*判断文件句柄是否有效*/
if(nullptr == pFTDHandler)
return;
/*打开文件准备读取*/
if(false == pFTDHandler->open(MeFTDHandler::ReadOnly))
return;
/*准备接收读取的缓存以及缓存大小*/
int nBufferSize = 0;
MeFTDTileData pBuffer = nullptr;
/*读取数据*/
MeFTDTileKey tileKey(0, 0, 0);
bool bOk = pFTDHandler->read(tileKey, &pBuffer, nBufferSize);
if(false == bOk)
{
//读取失败
MeFTDHandler::destroy(pFTDHandler);
return;
}
...读取成功,其它操作
/*销毁瓦片缓存数据*/
MeFTDHandler::destroyTileData(pBuffer);
/*读取完成,关闭文件句柄*/
pFTDHandler->close();
/*销毁文件句柄*/
MeFTDHandler::destroy(pFTDHandler);
  • 更新数据
/*判断文件句柄是否有效*/
if(nullptr == pFTDHandler)
return;
/*打开文件准备更新*/
if(false == pFTDHandler->open(MeFTDHandler::ReadWrite))
return;
/*准备更新的瓦片数据缓存以及大小*/
int nNewBufferSize = 0;
MeFTDTileData pNewBuffer = nullptr;
...获取新的瓦片数据
/*更新数据*/
MeFTDTileKey tileKey(0, 0, 0);
bool bOk = pFTDHandler->updateTile(tileKey, &pNewBuffer, nNewBufferSize);
/*销毁瓦片缓存数据*/
MeFTDHandler::destroyTileData(pNewBuffer);
nNewBufferSize = 0;
if(false == bOk)
{
//更新失败
MeFTDHandler::destroy(pFTDHandler);
return;
}
/*更新完成,关闭文件句柄*/
pFTDHandler->close();
/*销毁文件句柄*/
MeFTDHandler::destroy(pFTDHandler);
  • 删除瓦片数据
/*判断文件句柄是否有效*/
if(nullptr == pFTDHandler)
return;
/*打开文件准备删除*/
if(false == pFTDHandler->open(MeFTDHandler::ReadWrite))
return;
/*更新数据*/
MeFTDTileKey tileKey(0, 0, 0);
bool bOk = pFTDHandler->deleteTile(tileKey);
if(bOk)
//删除成功
/*删除完成,关闭文件句柄*/
pFTDHandler->close();
/*销毁文件句柄*/
MeFTDHandler::destroy(pFTDHandler);
  • 打开已存在的文件
//方式一
MeFTDHandler* pFTDHandler = MeFTDHandler::fromFile(“D:\\myftd.ftd”);
//方式二
MeFTDHandler handler(“D:\\myftd.ftd”);
handler.open(打开模式);

追加级别

FTD 需要索引来快速检索数据,这是一种用空间换时间的方式,当我们创建一个大范围高级

别的数据文件时,索引自身可能会占用较多空间,当我们暂时不需要某些级别的时候,创建

文件时可以不建立这些级别的索引信息,当后续需要的时候再通过追加的形式为其创建。通

过调用 initZoom 接口可以追加新的级别索引,下面的代码片段演示了创建方法。

MeFTDHandler* pFTDHandler = MeFTDHandler::fromFile(“D:\\myftd.ftd”, MeFTDHandler::ReadWrite);
if(nullptr == pFTDHandler)
return; //打开文件失败
//追加11级索引
bool bOk = pFTDHandler->initZoom(11);
if(bOk)
//追加成功
注意:已经存在索引的级别不能再次创建

使用迭代器

FTD 提供了读取数据迭代器,使用迭代器我们可以非常优雅的遍历指定的层级的瓦片数据,

同时迭代器允许指定一个数据范围,从而我们可以定向迭代某个级别指定范围的瓦片数据。

MeFTDHandler* pFTDHandler = MeFTDHandler::fromFile(“D:\\myftd.ftd”, MeFTDHandler::ReadOnly);
if(nullptr == pFTDHandler)
return; //打开文件失败
/*
范围是可选的,当不指定时,将遍历整个级别
*/
MeFTDIterator* pIter = pFTDHandler->iterator(10, [范围]);
while(pIter->hasNext())
{
int nTileDataSize = 0;
MeFTDTileData pTileData = nullptr;
MeFTDTileKey tileKey = pIter->next(&pTileData, nTileData);
if(0 == nTileDataSize)
continue; //跳过读取失败,或跳过无数据的瓦片
...有数据,执行其他操作
MeFTDHandler::destroyTileData(pTileData);
pTileData = nullptr;
nTileDataSize = 0;
}
/*关闭文件句柄并销毁文件句柄*/
pFTDHandler->close();
MeFTDHandler::destroy(pFTDHandler);

回收磁盘空间

在对瓦片数据进行频繁更新或删除操作以后,文件可能会产生大量 "死亡" 的瓦片,FTD 仅仅

是将其标记为删除,因此要完全回收这些磁盘空间,可以通过执行 vacuum 来完成。

注意:执行 vacuum 是代价高昂的操作。

联系我们

关注公众号