Skip to content

Commit

Permalink
dem无效值处修改编码,凑成海拔0
Browse files Browse the repository at this point in the history
  • Loading branch information
FreeGIS committed Jan 17, 2025
1 parent 3b1fc46 commit 1fddd1b
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 37 deletions.
18 changes: 12 additions & 6 deletions bin/dem2terrain.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const path = require('path');
const version = require('../package.json').version;

// node版本检查
if(+process.version.substring(1,3)<16){
if (+process.version.substring(1, 3) < 16) {
console.error(`node版本>=16,当前版本 ${process.version}`);
process.exit();
}
Expand All @@ -27,28 +27,32 @@ program
.option('-g, --epsg <number>', '<可选> Tile适用坐标系,3857 | 4490 | 4326', 3857)
.option('-c, --clean <number>', '<可选> 是否清空输出目录,0 | 1', 0)
.option('-z, --zoom <number-number>', '<可选> 指定瓦片的等级生成范围。例如,想生成 7 ~ 12 级的瓦片,则输入 -z 7-12', '5-14')
.option('-e, --encoding <string>', '<可选> 指定瓦片的数据编码规则(mapbox 或 terrarium)', 'mapbox');
.option('-e, --encoding <string>', '<可选> 指定瓦片的数据编码规则(mapbox 或 terrarium)', 'mapbox')
.option('-b, --baseHeight <number>', '<可选> 基准高度,默认0', 0);

// --- 解析参数
program.parse();

const options = program.opts();
// 判别是否是配置文件还是命令行配置
let params;
if (options['configFile'])
if (options['configFile'])
params = require(options['configFile']);
else
else
params = options;
const inputDem = params['input'];
const outputDir = params['output'];
if(inputDem===undefined||outputDir===undefined){
if (inputDem === undefined || outputDir === undefined) {
console.log('参数缺失: 输入文件路径或输出目录必填');
process.exit();
}

const encoding = params['encoding'];
const epsg = Number(params['epsg']);
const isClean = Number(params['clean']);
let baseHeight = Number(params['baseHeight']);
if (isNaN(baseHeight))
baseHeight = 0;
let zoom = params['zoom'];
zoom = zoom.split('-');
const minZoom = Number(zoom[0]);
Expand All @@ -73,6 +77,7 @@ const logMsg = `\n>> 开始转换...
- 瓦片编码: ${encoding === 'mapbox' ? 'mapbox(raster-dem)' : encoding}
- 瓦片尺寸: 256 px
- 瓦片等级: ${minZoom}${maxZoom}
- 基准高度: ${baseHeight}
`;
console.log(logMsg);

Expand All @@ -81,5 +86,6 @@ main(inputDem, outputDir, {
maxZoom,
epsg,
encoding,
isClean
isClean,
baseHeight
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dem2terrain",
"version": "2.2.4",
"version": "2.2.5",
"description": "使用 GDAL 制作 DEM 栅格的地形瓦片",
"main": "index.js",
"preferGlobal": true,
Expand Down
22 changes: 9 additions & 13 deletions src/createtile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { mapboxEncode, terrariumEncode } = require('./dem-encode');
const path = require('path');
const fs = require('fs');

let dataset = null, no_data = null, memDriver = null, pngDriver = null;
let dataset = null, no_data = null, _baseHeight = 0, memDriver = null, pngDriver = null;
function forEachHeightBuffer(heightBuffer, encode) {
const channelLength = heightBuffer.length;
const rBuffer = new Uint8Array(channelLength);
Expand All @@ -13,20 +13,15 @@ function forEachHeightBuffer(heightBuffer, encode) {
const aBuffer = new Uint8Array(channelLength);
for (let i = 0; i < channelLength; i++) {
let heightVal = heightBuffer[i];
let color, alpha;
if (heightVal === no_data) {
color = [0, 0, 0];
alpha = 0;
}
else {
color = encode(heightVal);
alpha = 255;
}

let color;
if (heightVal === no_data)
color = [1, 134, 160]; // 编码后凑海拔=0,修复地形塌陷产生空白
else
color = encode(heightVal - _baseHeight);
rBuffer[i] = color[0];
gBuffer[i] = color[1];
bBuffer[i] = color[2];
aBuffer[i] = alpha;
aBuffer[i] = 255;
}
return [rBuffer, gBuffer, bBuffer, aBuffer];
}
Expand Down Expand Up @@ -67,11 +62,12 @@ function writeTerrainTile(overviewInfo, readinfo, writeinfo, encoding) {


function createTile(createInfo, callback) {
const { outTileSize, overviewInfo, rb, wb, encoding, dsPath, x, y, z, outputTile } = createInfo;
const { outTileSize, overviewInfo, rb, wb, encoding, dsPath, x, y, z, outputTile, baseHeight } = createInfo;
if (dataset === null) {
dataset = gdal.open(dsPath, 'r');
// 查询no_data数值
no_data = dataset.bands.get(1).noDataValue;
_baseHeight = baseHeight;
}
// 创建一个mem内存,将读取的像素写入mem
if (memDriver === null)
Expand Down
14 changes: 7 additions & 7 deletions src/gdal-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ const gdal = require('gdal-async');
function getBuildOverviewResampling(resampling) {
switch (resampling) {
case 1:
return "AVERAGE";
return "AVERAGE"; // 加权平均法
case 2:
return "BILINEAR";
return "BILINEAR"; // 双线性内插法
case 3:
return "CUBIC";
return "CUBIC"; // 三次卷积内插法
case 4:
return "CUBICSPLINE";
return "CUBICSPLINE"; // B样条卷积内插法
case 5:
return "LANCZOS";
return "LANCZOS"; // Lanczos窗口sinc卷积内插法
case 6:
return "MODE";
return "MODE"; // 最常出现值法
case 7:
return "NEAREST";
return "NEAREST"; // 最邻近法
default:
return "CUBIC";
}
Expand Down
10 changes: 4 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ async function main(input, output, options) {
// 计时开始
const startTime = global.performance.now();
// 结构可选参数
const { minZoom, maxZoom, epsg, encoding, isClean, resampling } = options;
const { minZoom, maxZoom, epsg, encoding, isClean, resampling, baseHeight } = options;
// 固定瓦片尺寸
const tileSize = 256;
tileBoundTool = tileBoundMap.get(epsg);
Expand All @@ -190,19 +190,15 @@ async function main(input, output, options) {
outputDir = path.join(os.tmpdir(), uuid());

let stepIndex = 0;
//#region 步骤 1 - 高程值转 RGB,重新编码
if (isClean === 1) {
if (isSavaMbtiles === true && fs.existsSync(output))
fs.unlinkSync(output);
else
emptyDir(output);
console.log(`>> 步骤${++stepIndex}: 清空输出文件夹 - 完成`);
}

//#endregion
sourceDs = gdal.open(input, 'r');
//#region 步骤 1 - 重投影

if (sourceDs.srs.getAuthorityCode() !== epsg) {
projectPath = project(sourceDs, epsg, resampling);
projectDs = gdal.open(projectPath, 'r');
Expand All @@ -212,6 +208,7 @@ async function main(input, output, options) {
projectDs = sourceDs;
}
sourceDs = null;
//#endregion
//#region 步骤 2 - 建立影像金字塔 由于地形通常是30m 90m精度
const overViewInfo = buildPyramid(projectDs, minZoom, resampling);
console.log(`>> 步骤${++stepIndex}: 构建影像金字塔索引 - 完成`);
Expand Down Expand Up @@ -308,7 +305,8 @@ async function main(input, output, options) {
x: j,
y: i,
z: tz,
outputTile: outputDir
outputTile: outputDir,
baseHeight
};
pileUpCount++;
if (pileUpCount > 500)
Expand Down
7 changes: 4 additions & 3 deletions test/app.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
const path = require('path');
const fs = require('fs');

const demPath = path.join(__dirname, 'no_data.tif');
const demPath = path.join(__dirname, 'DEM.tif');
const tileDirPath = path.join(__dirname, 'terrain');

const config = {
"zoom": "5-13",
"zoom": "5-10",
"epsg": 3857,
"size": 256,
"resampling": 3,
"encoding": "mapbox",
"input": demPath,
"output": tileDirPath,
"clean": true
"clean": true,
"baseHeight":2100,
}

fs.writeFileSync(path.join(__dirname, 'config.json'), JSON.stringify(config));
2 changes: 1 addition & 1 deletion test/terrain_mapbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<div id="map"></div>
<script>
// 注意,请写自己的token运行
mapboxgl.accessToken = '';
mapboxgl.accessToken = 'pk.eyJ1IjoiYm9ibzlvayIsImEiOiJja3cxZjU1Z2UwMnFnMzBvajh4Y29iZTBiIn0.NcOkYbGRCj-C-gm1my6NZg';

const map = new mapboxgl.Map({
container: 'map',
Expand Down

0 comments on commit 1fddd1b

Please sign in to comment.