Question List in August, 2023
1、日常积累
1.1 超图 S3M 数据格式
超图团队在 2015 年提出了 3 种单体化方法:虚拟动态单体化、ID 单体化、切割单体化。S3M 设计中更多使用的方法是 ID 单体化:即三角面片中的每个顶点都对应存储一个 32 位的唯一标识 ID;由此确保在渲染时能够借助顶点着色器高效选中与高亮、批量改变对象颜色、以及批量改变对象的可见性。2017 年,超图决定在 github 上开源出 S3M 的细节,同时将 S3M 的定义由 SuperMap 3D Model 变更为 Spatial 3D Mode。其官网博客中提到了设计 S3M 格式时的 6 点原则:
通过 3D 瓦片将三维模型组织到一起,以方便在渲染时批次绘制,减少往显卡传输数据的次数,充分利用好带宽。
通过树状结构组织不同细节层次的全要素 3D 瓦片文件,以降低几何复杂度。
每个顶点对应存储一个 ID,在多个模型组合成同一批的同时借助 GPU 实现高效对象化查询。
通过实例化的方式存储,解决 BIM 模型对象被多次重复引用的问题。
3D 瓦片的数据组织对应 OpenGL 的 API ,以支持快速填显卡。
OpenGL 的 API 支持点、线、三角网等对象的绘制,对应的数据格式也可支持点、线、三角网等多种类型的数据。
在实现细节上,有几点需要注意:
- S3M 通过一种文件类型支持各类数据,采用数据文件和描述索引文件分离的数据结构:(1) 数据文件 .s3mb 描述了一个空间范围内的三维瓦片数据;(2) 索引文件 .json 是对瓦片数据的树形结构的描述,数据文件中也同步存储了该描述信息;(3) 描述文件 .scp 描述整个场景所有瓦片数据的基本信息;
S3M 是通过在每个顶点对应存储一个 ID 实现3D瓦片的对象化的;
S3M 的属性切片文件,有单独的 s3md 文件存储,只有根节点有,没有冗余;
3D-Tiles 模型的切片采用 glTF 格式,而 S3M 的几何切片文件是 s3mb 文件;
超图于 2017 年开放了 S3M V1.0 的标准和 SDK,通过 SDK 可以获取到指定文件的顶点和纹理等模型信息,但该标准并不一定适用于 V2.0 和 V3.0 版本,是一个后续开发的隐患。
1.2 Esri I3S 数据格式
ArcGIS 基于 I3S 标准在桌面端的三维数据格式是 multipatch,Web 端和移动端是 SLPK,其中在 Web 端的 SLPK 是用来发服务的交换缓存格式,在移动端的 slpk 用作离线数据。SLPK 即 Scene Layer Package 的缩写。
Writer: https://github.com/Esri/i3s-lib
#地理数据下载
1.3 倾斜摄影模型下载
2、程序与算法
2.1 C++
#cplusplus
实现单例类
class SHPCreator {
public:
static SHPCreator& instance() {
static SHPCreator creator;
return creator;
}
}
实现 var 类型
// c++11 自定义可变 KeyValue 类型更为适合
// c++17 可以更便捷的用 auto 定义 var 类型
struct KeyValue {
public:
std::string key;
enum Type { INTEGER, DOUBLE, STRING } type;
union Value { int Integer; double Double; std::string* String; } value;
public:
~KeyValue() {
if (type == STRING) {
delete value.String;
}
}
};
成员变量的别名
class Point {
public:
union {
struct { double x, y, z, w; };
struct { double u, v, m, k; };
struct { double X, Y, Z, W; };
};
}
QT 调用外部程序并在运行结束后反馈
QString folder = QCoreApplication::applicationDirPath();
QString program = folder + "/shp2obj/pro.02.road.exe";
QStringList params;
QProcess* process = new QProcess(this);
connect(process, &QProcess::finished, this, &shp2obj::exe_finished);
process->start(program, params);
大小端
小端 Little–Endian,大端 Big-Endian。二进制数据从右向左存储,左边是高位,右边是低位;二进制文件内存从左向右,左边是低地址,右边是高地址。
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中
也即:
在保存数值的二进制字节时,若先保存数值的高位则是大端,若先保存数值的低位则是小端。
![]()
typedef unsigned char Byte;
typedef std::vector<Byte> Bytes;
uint32_t to_uint32(Bytes& bytes)
{
uint32_t x = bytes[0];
for (int i = 1; i < 4; ++i) x = (x << 8) | bytes[i];
return x;
}
float to_float32(Bytes& bytes)
{
uint32_t x = bytes[0];
for (int i = 1; i < 4; ++i) x = (x << 8) | bytes[i];
static_assert(
sizeof(float) == sizeof(uint32_t),
"Float and uint32_t size dont match. Check another int type"
);
float f{};
std::memcpy(&f, &x, sizeof(x));
return f;
}
2.2 坐标归一化
问题描述。给定由 \(n\) 个点构成的多边形 \(\mathbf{P}=\{P_i=(x_i\ \ y_i\ \ z_i)^T|i\in[1,n]\}\) ,对该多边形进行坐标归一化处理的算法流程可以描述为:计算并保存参数→归一化坐标→反算原始坐标。
- 计算并保存参数:\[\begin{split} \begin{align} \mathrm{parameters}&=\{x_{\min},x_{\max},y_{\min},y_{\max}\}\\ &=\{x_{\min},\Delta_x,y_{\min},\Delta_y\};\Delta_x=x_{\max}-x_{\min},\Delta_y=y_{\max}-y_{\min} \end{align}\end{split}\]
归一化坐标及坐标反算:
\[\begin{split}P_i'=\begin{pmatrix} (x_i-x_{\min})\cdot s/\Delta_x\\ (y_i-y_{\min})\cdot s/\Delta_y\\ z_i \end{pmatrix}, P_i=\begin{pmatrix} x_i'\cdot\Delta_x/s+x_{\min}\\ y_i'\cdot\Delta_y/s+y_{\min}\\ z_i \end{pmatrix},s=1\times10^3\end{split}\]以上方法采用 XY 方向分别归一化的方式进行计算,计算较为便捷,考虑地理坐标 BLH 体系的特殊性未采用 XY 同除 Z 的投影空间转规范化设备坐标空间的方式。为确保等比缩放,引入:
\[factor=\Delta_y/\Delta_x\]
参考文献
博客园. 超图的倾斜摄影优化方案:《空间三维模型数据格式》标准[EB/OL].
betheme. # SuperMap GIS 倾斜摄影数据优化 QA[EB/OL].
郑州代理记账. ArcGIS三维数据[EB/OL].
CSDN 博客. OSGB 倾斜摄影数据处理为 3DTiles、I3S、S3M 的流程[EB/OL].
知乎. 发布并浏览超图 S3M 数据[EB/OL].
维基百科. Wavefront .obj model[EB/OL].
OBJ 标准. Object Files(.obj)[EB/OL].
知乎. 3D 格式概述:OBJ[EB/OL].
博客园. 复杂多边形的三角剖分[EB/OL].
CSDN 博客. CGAL-5.6的安装与编译(Win10+vs2022+CGAL-5.6+Boost1.82.0)[EB/OL].
CSDN 博客. # 二进制、16进制、大端小端[EB/OL].