Cesium Terrain Builder 非压缩瓦片

it2025-05-20  9

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(非压缩) /** * @details * Serialize a MeshTile to the Directory store * 增加zibFlag,是否输出压缩格式文件 */ 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); 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方法 /// Output mesh tiles represented by a tiler to a directory 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); // 如果没有指定瓦片坐标或zoom级别不是一个,使用原来逻辑 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结束索引。
最新回复(0)