当前位置: 首页 > Web前端 > JavaScript

mapboxgl加载tiff

时间:2023-03-26 23:32:57 JavaScript

的由来是最近在项目中遇到这样一个需求,需要在地图上显示一组网格数据。网格大小为2m*2m,地图API使用mapboxgl。一开始觉得这个很容易搞定,只要在地图上加一个填充层就可以了。将网格面数据添加到地图后,大比例尺显示正常,但当局部地图等级小于15时,渲染结果会消失。一个简单的原因是地图缩小后,每个格子所占的像素太小,所以消失了。mapboxgl在处理符号层时,会遇到点自动避让的问题,导致部分点无法显示。解决方法是将布局中的icon-allow-overlap设置为true,相当于关闭自动避让功能,所有点图标保持可见。但是填充层没有这样的属性。但在这种情况下,您需要查看数据。如何实现?首先分析数据。我的原始数据是模型导出的tiff格式的栅格数据,然后根据tiff格式数据中每个像素点的行列号及其在背景中的灰度值生成带有属性的栅格数据,其中像素点的灰度值of是渲染时需要在类别中显示的值。由于原始tiff数据的灰度值是使用的属性值,如果直接加到地图上就好了。接下来的解决办法就是看能不能直接用mapboxgl加载tiff数据,渲染出你想要的效果。mapboxgl加载tiff查看mapboxgl文档,可以看到mapboxgl支持图片图层,传入url和坐标即可//添加到地图map.addSource('someid',{type:'image',url:'https://www.mapbox.com/images/foo.png',坐标:[[-76.54,39.18],[-76.52,39.18],[-76.52,39.17],[-76.54,39.17]]});但是,当我把地址改成tiff数据时,却报错了。以下是错误内容:Couldnotloadimagebecausethesourceimagecouldn'tbedecoded..请确保使用受支持的图像类型,如PNG或JPEG。注意SVGsarenotsupported可以简单理解为不支持tiff格式。tiff文件分析由于mapboxgl的图像层不支持tiff格式,请问是否可以将tiff数据导出为png,所以我用arcmap打开tiff数据,导出的数据格式也支持png,但是报错保存时。经过分析,发现是tiff数据条带数量多的原因。我的数据带号是1,从网上下载了一个测试数据。波段号为3,可以成功导出。在寻找相关解决方案的时候,看到了这样一个工具,geotiff.js,可以解析tiff数据,通过js进行渲染。Leaflet有个扩展用到了这个工具,https://github.com/stuartmatt...。看了geotiff.js的相关文档,发现用起来还是挺方便的,通过简单的代码实现了我的需求.先用geotiff.js解析tiff数据,然后用canvas画图导出base64格式数据,再添加到mapboxgl层。核心代码如下:asyncfunctiongetData(){GeoTIFF.fromUrl(url).then(tiff=>{console.log(tiff)getImage(tiff)});}asyncfunctiongetImage(tiff){constimage=等待TIFF。得到图像();让bbox=awaitimage.getBoundingBox();letdata=awaitimage.readRasters({samples:rgbBands//波段数,一个波段:[0],三个波段:[2,1,0]});让base64Image=getBase64Image(数据)addToMapboxgl(base64Image)}functiongetBase64Image(数据){ctx=canvas.getContext("2d")lettotalPixelCount=0for(lety=0;y0){if(data[0][totalPixelCount]>50&&data[0][totalPixelCount]<=55){color=`rgb(15,255,0,1)`}elseif(data[0][totalPixelCount]>55&&data[0][totalPixelCount]<=60){color=`rgb(155,255,0,1)`}elseif(data[0][totalPixelCount]>60&&data[0][totalPixelCount]<=65){color=`rgb(255,255,0,1)`}else{color=`rgb(255,255,0,1)`}}ctx.fillStyle=colorctx.fillRect(x,y,1,1)totalPixelCount++}}letcanvasImage=canvas.toDataURL("image/png")returncanvasImage}//将图片添加到地图functionaddToMapboxgl(image){map.addSource('tiff-source',{"type":"图片","url":图片,"坐标":[[114.425597191307,38.1091563484708],[114.538187627939,38.1091563484708],[114.538187627939,37.9627378349547129],[13517,127]37.9627378349512]]});map.addLayer({id:'tiff-layer','type':'raster','source':'tiff-source','paint':{'raster-fade-duration':0}});}以为到这里问题就解决了,结果查图的时候发现影像层数据叠加在底图上,有很大的偏移。经过一番对比分析,发现是tiff数据的坐标系和地图坐标系不一致造成的。我拿到的tiff数据的坐标系是西安80的投影坐标系,显示的时候配置了wgs84的地理坐标系,所以会有偏差。既然是坐标系的问题,那就用工具对tiff文件进行投影变换。这里使用Arcmap。打开ArcToolbox–>DataManagementTools–>ProjectionsandTransformations–>Raster–>ProjectRasterconversion后,会发现数据的行值和列值也会发生变化,即tiff的大小和形状图像会有所不同。种类。转换前:转换后:用转换后的数据再次解析,然后叠加到地图上,位置正好匹配。最终的显示方案通过实验发现,在显示单张图片时,由于图片的分辨率是固定的,当地图级别放大到一定程度时,图片会放大很多,导致图片模糊,显示效果不理想;在显示单个网格面时,当地图层级降低到一定程度时,面层会消失,这就是文章开头提到的问题。综上所述,根据自己的网格数据大小,判断网格面数据会在哪一级消失。小于这个级别就用图片显示,大于这个级别就用网格面显示,就可以完美显示你想要的效果。处理前效果:处理后效果:以上是tiff栅格数据情况下的解决方法,只有网格面数据没有tiff栅格数据的情况如何解决?如果在这组网格数据中,每个网格的属性都有其原始tiff数据的像素位置和原始tiff数据的像素大小,可以写一个类似上面的getBase64Image方法遍历每个网格,绘制颜色在网格对应的像素位置上,然后通过canvas导出图片,添加到地图中。综上所述,mapboxgl的图像层不能直接添加tiff栅格数据。mapboxgl添加填充图层时,地图层次有一定程度的降低,表面数据占用的像素值太小,无法显示tiff数据。可以使用geotiff.js+ca??nvas来分析得到base64解析tiff数据时,添加到mapboxgl的图像层要注意其坐标系,波段数等信息。显示时,可以将图像层和填充层合并显示,效果更佳。参考:https://geotiffjs.github.io/g...https://github.com/stuartmatt...https://www.cnblogs.com/arxiv...原文地址:http://gisarmory.xyz/blog/index.html?blog=mapboxgl-geotiff欢迎关注《GIS兵器库》本文采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议授权。欢迎转载、使用、转载,但务必保留文章署名《GIS兵器库》(含链接:http://gisarmory.xyz/blog/),不得用于商业用途。基于本文修改的作品必须使用相同的许可发布。