Cesium Terrain Builder 输出瓦片默认是zib压缩后的,在业务中如果传输不是问题,反而增加浏览器的解压处理,希望能支持输出非压缩瓦片。 针对此需求,修改代码并重新编译。
一、代码分析
1、输出数据对象 文件格式:主要为heightmap-1.0、quantized-mesh-1.0,其类图结构如下:
MeshTile为quantized-mesh-1.0格式数据对象。TerrainTile为heightmap-1.0格式数据对象。
2、瓦片生成器
Meshtiler 用来生成MeshTile对象。TerrainTiler 用来生成TerrainTile对象。
3、迭代器和序列化器
4、ctb-tile.exe的主要流程
二、功能扩展
1、增加非压缩支持。
ctb-tile.cpp中TerrainBuild类,增加参数
bool gzib
;
gzib(false)
static void setGzib(command_t
* command
) {
static_cast<TerrainBuild
*>(Command
::self(command
))->gzib
= true;
}
ctb-tile.cpp中main函数解析参数
command
.option("-G", "--gzip", "use zib compress file(defalut uncompress)", TerrainBuild
::setGzib
);
CTBFileTileSerializer.cpp中,serializeTile函数增加zibFlag参数。根据gzibFlag决定是否使用CTBZFileOutputStream(压缩)或者CTBFileOutputStream(非压缩)
bool
ctb
::CTBFileTileSerializer
::serializeTile(const ctb
::MeshTile
*tile
, bool writeVertexNormals
, bool gzibFlag
) {
const TileCoordinate
*coordinate
= tile
;
const string filename
= getTileFilename(coordinate
, moutputDir
, "terrain");
const string temp_filename
= concat(filename
, ".tmp");
if (gzibFlag
) {
CTBZFileOutputStream
ostream(temp_filename
.c_str());
tile
->writeFile(ostream
, writeVertexNormals
);
ostream
.close();
} else {
FILE
*fp
= fopen(temp_filename
.c_str(), "wb");
CTBFileOutputStream
ostream(fp
);
tile
->writeFile(ostream
, writeVertexNormals
);
fclose(fp
);
}
if (VSIRename(temp_filename
.c_str(), filename
.c_str()) != 0) {
throw new CTBException("Could not rename temporary file");
}
return true;
}
ctb-tile.cpp中buildMesh函数,修改为传递gzlib函数
serializer
.serializeTile(tile
, writeVertexNormals
, command
->gzib
);
2、输出指定范围的瓦片
ctb-tile.cpp中TerrainBuild类,增加参数
int layerStartX
, layerStartY
, layerEndX
, layerEndY
;
layerStartX(-1),
layerStartY(-1),
layerEndX(-1),
layerEndY(-1)
static void setLayerStartX(command_t
*command
) {
static_cast<TerrainBuild
*>(Command
::self(command
))->layerStartX
= atoi(command
->arg
);
}
static void setLayerStartY(command_t
*command
) {
static_cast<TerrainBuild
*>(Command
::self(command
))->layerStartY
= atoi(command
->arg
);
}
static void setLayerEndX(command_t
*command
) {
static_cast<TerrainBuild
*>(Command
::self(command
))->layerEndX
= atoi(command
->arg
);
}
static void setLayerEndY(command_t
*command
) {
static_cast<TerrainBuild
*>(Command
::self(command
))->layerEndY
= atoi(command
->arg
);
}
ctb-tile.cpp中main函数解析参数
command
.option("-A", "--start-x <sx>", "tile’s start x ", TerrainBuild
::setLayerStartX
);
command
.option("-D", "--end-x <ex>", "tile’s end x", TerrainBuild
::setLayerEndX
);
command
.option("-W", "--start-y <sy>", "tile’s start y", TerrainBuild
::setLayerStartY
);
command
.option("-S", "--end-y <ey>", "tile’s end y", TerrainBuild
::setLayerEndY
);
ctb-tile.cpp修改buildMesh方法
static void buildMesh(MeshSerializer
&serializer
, const MeshTiler
&tiler
, TerrainBuild
*command
, TerrainMetadata
*metadata
, bool writeVertexNormals
= false) {
i_zoom startZoom
= (command
->startZoom
< 0) ? tiler
.maxZoomLevel() : command
->startZoom
,
endZoom
= (command
->endZoom
< 0) ? 0 : command
->endZoom
;
int layerStartX
= (command
->layerStartX
< 0)? 0: command
->layerStartX
,
layerStartY
= (command
->layerStartY
< 0) ? 0 : command
->layerStartY
,
layerEndX
= (command
->layerEndX
< 0) ? 0 : command
->layerEndX
,
layerEndY
= (command
->layerEndY
< 0) ? 0 : command
->layerEndY
;
MeshIterator
iter(tiler
, startZoom
, endZoom
);
int currentIndex
= incrementIterator(iter
, 0);
setIteratorSize(iter
);
GDALDatasetReaderWithOverviews
reader(tiler
);
while (!iter
.exhausted()) {
const TileCoordinate
*coordinate
= iter
.GridIterator
::operator*();
if (metadata
) metadata
->add(tiler
.grid(), coordinate
);
if (layerStartX
== 0 && layerEndX
== 0 && startZoom
!= endZoom
) {
if (serializer
.mustSerializeCoordinate(coordinate
)) {
MeshTile
*tile
= iter
.operator*(&reader
);
serializer
.serializeTile(tile
, writeVertexNormals
, command
->gzib
);
delete tile
;
}
}
else {
if (coordinate
->x
>= layerStartX
&& coordinate
->x
<= layerEndX
&& coordinate
->y
>= layerStartY
&& coordinate
->y
<= layerEndY
) {
if (serializer
.mustSerializeCoordinate(coordinate
)) {
MeshTile
*tile
= iter
.operator*(&reader
);
serializer
.serializeTile(tile
, writeVertexNormals
, command
->gzib
);
delete tile
;
}
}
}
currentIndex
= incrementIterator(iter
, currentIndex
);
showProgress(currentIndex
);
}
}
三、命令行说明
编译成功后,就支持非压缩切片和生成指定范围的切片功能了。
调用说明
ctb-tile.exe -o D:/test/tile D:/test/dem.tif -f Mesh -s 6 -e 6 -A 105 -D 107 -W 45 -S 47
完整参数说明
参数说明
-V输出程序版本。-h输出帮助信息。-o切片输出路径。-p切片规则。默认geodetic,可以指定mercator-f切片格式。默认Terrain,可以指定Mesh-c使用线程数。默认同cpu数-t瓦片像素大小。默认65*65-s瓦片开始级别。-e瓦片结束级别。注意:开始级别 > 结束级别-r重采样方法。默认平均值,可以指定min,max,average,nearest,bilinear,cubic等。-R不覆盖现有文件。-G生成zib压缩切片。-A切片范围,x开始索引。-D切片范围,x结束索引。-W切片范围,y开始索引。-S切片范围,y结束索引。