当前位置: 首页 >  信息化服务 >  fepk文件格式说明

fepk文件格式说明

导读:1 卫星影像金字塔分块原理说明.通常我们在工作中使用的卫星影像数据,轻则几百M,重则几百个G甚至上TB级。影像数据太大,是大家经常会遇到的一个问题,尤其是想下载一个省以上数据的时候该问题尤为突出。那么该问题是否有一个比较好的解决方案呢?.以全球为例,我们以19级为例,共有2^18

1 卫星影像金字塔分块原理说明

通常我们在工作中使用的卫星影像数据,轻则几百M,重则几百个G甚至上TB级。影像数据太大,是大家经常会遇到的一个问题,尤其是想下载一个省以上数据的时候该问题尤为突出。那么该问题是否有一个比较好的解决方案呢?

以全球为例,我们以19级为例,共有2^18 * 2^17 张瓦片,如此多的瓦片会让磁盘愈来愈慢,同时也无法维护。

当影像范围比较大时,我们可以采用金字塔分块的方式进行管理,系统会自动将大范围分成若干个块,且块与块之间是可以无缝拼接的。

一般情况我们选择全球前10级别作为基础级别,因数据量不大(1G)左右,后续以10级作为基础级别,全球19级别数据被划分为 2^8 * 2^7(512 * 256)个块。每个块中包含了256 * 256 张小瓦片。

1.1 Fepk文件命名规则

文件说明(包含索引与数据两个文件,文件必须都配套才可以正常使用):

*.fepk :文件中存储具体的瓦片数据。

*.fepk.idx :文件中存储的瓦片的索引信息,当给定一个瓦片编号后,可以根据编号计算出来瓦片存在索引中的信息(大小,以及数据在8-174-138.fepk中的位置)。

名称命名规

以8-174-138.fepk为例:其中8是级别,174是列号,138是行号,文件中存储了8-174-138瓦片裂分出来的所有瓦片数据。

2 .fepk文件格式说明

我们一般不会直接采用瓦片作为管理单元,会把一个块作为管理单元,把数据划分为索引文件与数据文件,如下所示:

数据文件:world.fepk

索引文件:world.fepk.idx

2.1 索引文件

1文件说明**
**

文件头 字段
文件头 char szMagic[20] fe.tile.store.data20字节
uint version 版本号4字节
uint typeId 数据类型 enum PKType { 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字节
LevSnap levOff[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定义:

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字节

2.2 数据文件文件

文件头 字段
文件头 char szMagic[20] fe.tile.store.data20字节
uint version 版本号4字节
uint typeId 数据类型 enum PKType { 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字节
LevSnap levOff[24] 级别索引,8 * 24 字节
char _reserve[240] 保留
数据0 Int4 4*4字节,行号,列号,级别,大小
数据
数据1 Int4 4*4字节,行号,列号,级别,大小
数据
数据… Int4 4*4字节,行号,列号,级别,大小
数据

3 如何使用数据

3.1 解压成标注金字塔瓦片

用户可以通过FEPKUNPack.exe 解压程序,将数据加压标准的金字塔瓦片,然后即可使用,导出后如下所示。

导出后可以方便的被osgEarth,cesium,argis,fastearth等软件直接加载。

缺点: 导出后,占用磁盘大小比未解压前大50%。

导出后,维护困难,因为文件很多,拷贝能都受到影响。

数据截图

3.2 API读取瓦片

使用SDK/API访问数据,为了方便大家使用,避免数据解压,可以使用FEPKReadApi

SDK读取数据,SDK使用C语言编写,接口如下所示

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 = "path">目录组,以null结束</param>
    /// <param name = "x">瓦片的编号</param>
    /// <param name = "y">瓦片的编号</param>
    /// <param name = "z">瓦片的编号</param>
    /// <param name = "header">文件头信息</param>
    /// <param name = "pSize">瓦片大小</param>
    /// <return>返回打开的文件</return>
FEPKFile    fepkReadTileHeader(const char** path,int x,int y,int z,FEPHHeader* header,uint* pSize);
    /// <summary>
    /// 从一个文件夹中读取
    /// </summary>
    /// <param name = "file">文件句柄</param>
    /// <param name = "header">文件头信息</param>
    /// <param name = "pBuf">输入/输出,从fepkReadTileHeader读取</param>
    /// <param name = "nBufLen">输入,从fepkReadTileHeader读取</param>
    /// <return>返回读取的长度-1,失败,0,文件内部错误,其他读取的长度</return>
int         fepkReadTileData(FEPKFile file,const FEPHHeader* header,void* pBuf,uint nBufLen);

}

使用说明:

#include "FEPKReaderApi.h"

#include <stdio.h>
/// 如果是SDK,非源码方式,则需要因入库
/// #pragma comment(lib,"FEPKReader.lib")
int main(int, char**)
{
    /// 1. 开发文件
    FEPKFile    file = fepkOpenFile("D:\\FE\\data\\fepk\\world.fepk");
    if (file == nullptr)
    {
        return  0;
    }
    FEPHHeader  header;
    uint        nSize = 0;
    /// 2. 读取给定瓦片编号的文件头信息
    /// 如果返回false,说明当前文件中没有给定的瓦片数据
    if (!fepkReadHeader(file, 0, 0, 0, &header))
    {
        return  0;
    }
    /// 3. 读取数据大小
    if (!fepkReadDataSize(file, &header, &nSize))
    {
        return  0;
    }
    /// 申请空间
    char*   pBuf = new char[nSize];
    /// 4. 读取数据
    if (!fepkReadData(file, &header, pBuf, nSize))
    {
        printf("read ok!\n");
    }
    /// 5. 释放内存
    delete[]pBuf;
    /// 6. 关闭文件
    fepkCloseFile(file);
    return  0;
}

##

内容
  • Unity 中的存档系统(本地存档)
    Unity 中的存档系统(本地存
    2023-12-09
    思想.在游戏过程中,玩家的背包、登录、人物系统都与数据息息相关,无论是一开始就设定好的默认数据,还是可以动态存取的数据,
  • 【MRTK】解决 Unity.IL2CPP.Building.BuilderFailedException: Lump_libil2cpp_vm.cpp 报错问题
    【MRTK】解决 Unity.I
    2023-12-07
    前言.最近在部署 HoloLens 应用的时候遇到了这个报错,无论是本地部署、远程部署、还是导出 APPX 项目包,都会
  • Mybatis的工作原理
    Mybatis的工作原理
    2023-12-05
    mybatis的工作原理.mybatis基本工作原理.封装sql ->调用JDBC操作数据库 -> 返回数据封装.JDB
  • 数据分析师如何用SQL解决业务问题?
    数据分析师如何用SQL解决业务问
    2023-12-03
    本文来自问答。.提问:数据分析人员需要掌握sql到什么程度?.请问做一名数据分析人员,在sql方面需要掌握到什么程度呢?
  • 缓存面试解析:穿透、击穿、雪崩,一致性、分布式锁、Redis过期,海量数据查找
    缓存面试解析:穿透、击穿、雪崩,
    2023-12-03
    为什么使用缓存.在程序内部使用缓存,比如使用map等数据结构作为内部缓存,可以快速获取对象。通过将经常使用的数据存储在缓
  • 十年后的第一篇:记录对两个面试问题的思考
    十年后的第一篇:记录对两个面试问
    2023-12-02
    太久没写过博客了,用户名密码甚至连用哪个邮箱注册的都不记得了,如果不是最近面试官要看的话实在是不想翻出来(如果面试官看到
  • Unity学习笔记--数据持久化Json
    Unity学习笔记--数据持久化
    2023-12-02
    JSON相关.json是国际通用语言,可以跨平台(游戏,软件,网页,不同OS)使用,.json语法较为简单,使用更广泛。
  • 长文多图一步步讲清楚:DDD理论、建模与代码实现全流程
    长文多图一步步讲清楚:DDD理论
    2023-12-01
    1 六个问题.1.1 为什么使用DDD.DDD方法论核心是将问题不断分解,把大问题分解为小问题,大业务分解小领域,简而言
  • 园林绿化养护服务
    园林绿化养护服务
    2024-01-10
    园林绿化养护服务.产品功能.园林绿化养护服务是一项专业的服务,旨在为客户提供全方位的园林绿化管理和养护服务。我们团队的专
  • 园林景观设计
    园林景观设计
    2023-12-11
    园林景观设计产品介绍.产品功能.园林景观设计是一项专业的设计服务,主要用于规划和设计公共和私人的园林空间。其功能包括根据
  • 绿化工程材料供应
    绿化工程材料供应
    2023-12-16
    绿化工程材料供应.产品功能.我们的绿化工程材料供应主要用于城市绿化、园林景观建设、庭院绿化等相关项目。产品种类丰富,覆盖
  • 城市绿化规划设计
    城市绿化规划设计
    2024-01-15
    城市绿化规划设计.随着城市化进程的不断加快,城市绿化规划设计成为了一个备受关注的问题。如何在城市中保护和增加绿地,促进城
  • 喷泉景观设计
    喷泉景观设计
    2024-01-05
    喷泉景观设计.喷泉是一种极具观赏性和装饰性的景观设计元素,它不仅可以为周围的环境增添一份生气与动感,更可以为人们带来一份
  • 公园景观规划设计
    公园景观规划设计
    2024-01-10
    公园景观规划设计.产品功能.我们的公园景观规划设计产品旨在为城市和乡村地区提供高质量的公共休闲空间。我们致力于通过规划和
  • 园林休闲座椅制作
    园林休闲座椅制作
    2024-01-20
    园林休闲座椅制作.产品功能.园林休闲座椅是专门为户外休闲空间设计制作的座椅产品。产品具有耐候性强、外观美观、舒适度高等特
  • 喷泉设计与安装
    喷泉设计与安装
    2023-12-21
    喷泉设计与安装.喷泉是园林景观中不可或缺的元素之一,无论是在公园、**还是私人花园中,喷泉都能为环境增添灵动的气息,成为
  • 室外园林景观配套设施制作
    室外园林景观配套设施制作
    2024-01-15
    室外园林景观配套设施制作.产品功能.我们的室外园林景观配套设施制作主要提供定制化的户外景观配套设施,包括花池、凉亭、栏杆
  • 景观照明工程
    景观照明工程
    2023-12-16
    景观照明工程.产品功能.景观照明工程是一种专门为户外景观设计的照明方案。它既可以美化城市风景,提升城市形象,也可以为人们