地形裙边处理
这篇文章我们介绍下地形边缘裂缝的处理方法
注意
例子里我使用了three插件了,地形的简单的图形构造有内部完成
- 地形周边的压平有three插件内部处理了
- 瓦片边缘采用邻居的边缘值有 tileclip插件里的
terrainTileFixBoundary
完成
背景
当我们在加载mapbox的地形数据时,按照正常的处理流程瓦片构成成图形后,加到地图上发现瓦片和瓦片直接存在 裂缝
我看了下deck.gl里也存在同样的问题
然后我们就进行定位问题:
- 一开始我们以为是图形构造的宽度和高度的精度不够导致的边没有对齐
- 后来发现相邻瓦片的边缘的海拔高度就是不相等导致的
解决方法
针对这个问题我们想到了两种解决方法:
对地形buffer一定大小,然后边缘压扁
每个瓦片的最右边和最下面的一个像素值采用邻居瓦片的值
边缘压扁
边缘压扁的方法就是瓦片的边缘的一个像素的地形值简单的粗暴的设置为0,然后就形成了上面的效果图,但是 因为边缘被压扁了,导致瓦片仍然有缝隙(深沟)
所以这时我们需要地形瓦片进行一定的大小的buffer,比如buffer一个像素对应的长度,这时就可以把深沟给消除掉了。
但是当我们仔细观察后,发现瓦片直接仍然不能严丝合缝的
边缘采用邻居瓦片的值
这个方法的具体是:每个瓦片的最右边和最下面的一个像素值采用邻居瓦片的的值,这样就可以保证相邻的瓦片的 边缘的值就是相同的了
大概代码如下:
js
const currentTile = findTile(minX, minY);
const rightTile = findTile(minX + 1, minY);
const bottomTile = findTile(minX, minY + 1);
const canvas = getCanvas(tileSize);
resizeCanvas(canvas, tileSize, tileSize);
const ctx = getCanvasContext(canvas);
ctx.drawImage(currentTile.image, 0, 0, tileSize, tileSize);
if (rightTile) {
ctx.drawImage(
rightTile.image,
0,
0,
1,
tileSize,
tileSize - 1,
0,
1,
tileSize,
);
}
if (bottomTile) {
ctx.drawImage(
bottomTile.image,
0,
0,
tileSize,
1,
0,
tileSize - 1,
tileSize,
1,
);
}
const image = canvas.transferToImageBitmap();
这样瓦片直接就可以做到严丝合缝了
缺点
请求瓦片时需要我们一拖三,即最少请求三张瓦片了(当前瓦片和其右边和下面的邻居瓦片),不过配合LRU缓存和IndexedDB啥的效率也是可以接受的