關(guān)于mapboxgl加載tiff的問(wèn)題
mapboxgl通過(guò)添加tiff圖層,解決小網(wǎng)格的fill圖層在地圖縮小時(shí)圖層不顯示問(wèn)題
緣起
近期在項(xiàng)目中遇到這么一個(gè)需求,需要在地圖上展示一組格網(wǎng)數(shù)據(jù),格網(wǎng)大小為2m*2m
,地圖api
用的mapboxgl
。起初拿到這個(gè)需要感覺(jué)很easy,在地圖上添加一個(gè)fill
圖層就好啦。把格網(wǎng)面數(shù)據(jù)添加到地圖上之后,在大比例尺下顯示正常,但是當(dāng)?shù)貓D層級(jí)小于15級(jí)時(shí),渲染出的結(jié)果會(huì)消失。
簡(jiǎn)單理一下原因,應(yīng)該是在地圖縮小后,每個(gè)網(wǎng)格所占的像素太小,所以就消失了。
mapboxgl
在處理symbol
圖層的時(shí)候,會(huì)遇到點(diǎn)位自動(dòng)避讓問(wèn)題,導(dǎo)致部分點(diǎn)位不顯示。解決方法是把layout
中的icon-allow-overlap
設(shè)置為true
,這樣就相當(dāng)于關(guān)閉了自動(dòng)避讓功能,所有點(diǎn)圖標(biāo)保持可見狀態(tài)。但是針對(duì)fill
圖層卻沒(méi)有這么一個(gè)屬性。
但是這種情況又需要查看數(shù)據(jù),要如何實(shí)現(xiàn)呢?
首先分析下數(shù)據(jù),我的原始數(shù)據(jù)是通過(guò)模型導(dǎo)出的tiff
格式的柵格數(shù)據(jù),然后在后臺(tái)根據(jù)tiff
格式數(shù)據(jù)中每個(gè)像素所在行列號(hào)以及其灰度值生成帶屬性的格網(wǎng)數(shù)據(jù),其中像素的灰度值就是在渲染時(shí)需要分類展示的值。既然原始tiff
數(shù)據(jù)的灰度值就是所用的屬性值,那是不是直接添加到地圖就好了。接下來(lái)的解決方案就是看是否能直接用mapboxgl
直接加載tiff
數(shù)據(jù),并渲染出自己想要的效果。
mapboxgl加載tiff
查看mapboxgl
文檔,可以看到mapboxgl
支持image
圖層,只需傳入url和coordinates
// 添加至地圖 map.addSource('some id', { type: 'image', url: 'https://www.mapbox.com/images/foo.png', coordinates: [ [-76.54, 39.18], [-76.52, 39.18], [-76.52, 39.17], [-76.54, 39.17] ]});
可是,當(dāng)我把地址換成tiff
數(shù)據(jù)時(shí)卻報(bào)錯(cuò)了。下面為報(bào)錯(cuò)內(nèi)容:
Could not load image because of The source image could not be decoded.. Please make sure to use a supported image type such as PNG or JPEG. Note that SVGs are not supported
可以簡(jiǎn)單理解為不支持tiff
格式。
tiff文件解析
既然mapboxgl
的image
圖層不支持tiff
格式,那是不是可以把tiff
數(shù)據(jù)導(dǎo)出成png
呢,于是使用arcmap
打開了tiff
數(shù)據(jù),導(dǎo)出數(shù)據(jù)格式也支持png
,但是在保存時(shí)又報(bào)錯(cuò)了。
經(jīng)過(guò)分析,發(fā)現(xiàn)是tiff
數(shù)據(jù)波段數(shù)量的原因,我的這份數(shù)據(jù)波段數(shù)為1,從網(wǎng)上下載了一份測(cè)試數(shù)據(jù),波段數(shù)為3,可以成功導(dǎo)出。
在查找相關(guān)解決方案的時(shí)候,看到這么個(gè)工具,geotiff.js,可以通過(guò)js
解析tiff
數(shù)據(jù)并渲染,leaflet
有個(gè)擴(kuò)展就是用的這個(gè)工具,https://github.com/stuartmatthews/leaflet-geotiff。查看geotiff.js
相關(guān)文檔,發(fā)現(xiàn)其實(shí)用起來(lái)還是挺方便的,通過(guò)簡(jiǎn)單的代碼實(shí)現(xiàn)的我的需求。
先使用geotiff.js
解析tiff
數(shù)據(jù),再配合使用canvas
繪制圖片導(dǎo)出base64
格式數(shù)據(jù),然后就可以使用添加到mapboxgl
圖層了。
核心代碼如下:
async function getData() { GeoTIFF.fromUrl(url).then(tiff => { console.log(tiff) getImage(tiff) }); } async function getImage(tiff) { const image = await tiff.getImage(); let bbox = await image.getBoundingBox(); let data = await image.readRasters({ samples: rgbBands // 波段數(shù)量,一個(gè)波段:[0],三個(gè)波段:[2,1,0] }); let base64Image = getBase64Image(data) addToMapboxgl(base64Image) } function getBase64Image(data) { let thumbnailPixelHeight = data.height let thumbnailPixelWidth = data.width let canvas = document.createElement('canvas') canvas.width = thumbnailPixelWidth canvas.height = thumbnailPixelHeight let ctx = canvas.getContext("2d") let totalPixelCount = 0 for (let y = 0; y < thumbnailPixelHeight; y++) { for (let x = 0; x < thumbnailPixelWidth; x++) { let colour = 'rgb(0, 0, 0, 0)' // let the default be no data (transparent) // 根據(jù)灰度值所在范圍渲染顏色 if (data[0][totalPixelCount] > 0) { if (data[0][totalPixelCount] > 50 && data[0][totalPixelCount] <= 55) { colour = `rgb(15, 255, 0, 1)` } else if (data[0][totalPixelCount] > 55 && data[0][totalPixelCount] <= 60) { colour = `rgb(155, 255, 0, 1)` } else if (data[0][totalPixelCount] > 60 && data[0][totalPixelCount] <= 65) { colour = `rgb(255, 255, 0, 1)` } else { colour = `rgb(255, 255, 0, 1)` } } ctx.fillStyle = colour ctx.fillRect(x, y, 1, 1) totalPixelCount++ } } let canvasImage = canvas.toDataURL("image/png") return canvasImage } // 將圖片添加到地圖 function addToMapboxgl(image) { map.addSource('tiff-source', { "type": "image", "url": image, "coordinates": [ [114.425597191307, 38.1091563484708], [114.538187627939, 38.1091563484708], [114.538187627939, 37.9627378349512], [114.425597191307, 37.9627378349512] ] }); map.addLayer({ id: 'tiff-layer', 'type': 'raster', 'source': 'tiff-source', 'paint': { 'raster-fade-duration': 0 } }); }
本以為到這里問(wèn)題已經(jīng)解決,但是在查看地圖時(shí),發(fā)現(xiàn)圖片圖層數(shù)據(jù)疊加到底圖有不小的偏移。
經(jīng)過(guò)一番對(duì)比分析,發(fā)現(xiàn)原來(lái)是tiff
數(shù)據(jù)的坐標(biāo)系與地圖坐標(biāo)系不一致的導(dǎo)致的。我拿到的tiff
數(shù)據(jù)坐標(biāo)系為西安80的投影坐標(biāo)系,在展示時(shí)配置的為wgs84
地理坐標(biāo)系,所以會(huì)有偏差。既然是坐標(biāo)系問(wèn)題,那就通過(guò)工具對(duì)tiff
文件做下投影轉(zhuǎn)換。這里用的是arcmap
,打開ArcToolbox–>Data Management Tools–>Projections and Transformations–>Raster–>Project Raster
轉(zhuǎn)換之后會(huì)發(fā)現(xiàn),數(shù)據(jù)的行列值也會(huì)發(fā)生變化,也就是tiff
圖片的大小和形狀都有所變化。
轉(zhuǎn)換前:
轉(zhuǎn)換后:
使用轉(zhuǎn)換后的數(shù)據(jù)再次解析,然后疊加到地圖,位置完全匹配。
最終展示方案
通過(guò)嘗試發(fā)現(xiàn),單獨(dú)的圖片展示時(shí),由于圖片分辨率固定,當(dāng)?shù)貓D等級(jí)放大到一定程度圖片會(huì)被放大很多導(dǎo)致圖片模糊不清,展示效果不理想;單獨(dú)的格網(wǎng)面展示時(shí),當(dāng)?shù)貓D等級(jí)縮小到一定程度,面圖層則會(huì)消失,也就是文章開頭提到的問(wèn)題。
綜上,根據(jù)自己的格網(wǎng)數(shù)據(jù)大小,判斷在哪個(gè)等級(jí)格網(wǎng)面數(shù)據(jù)會(huì)消失,小于這個(gè)等級(jí)使用圖片展示,大于這個(gè)等級(jí)用格網(wǎng)面展示,就可以完美的展示出想要的效果。
處理前效果:
處理后效果:
以上為有tiff
柵格數(shù)據(jù)情況的解決方案,針對(duì)于只有格網(wǎng)面數(shù)據(jù),而沒(méi)有tiff
柵格數(shù)據(jù)的情況要怎么解決呢?
如果在這組格網(wǎng)數(shù)據(jù)中,每個(gè)網(wǎng)格的屬性中有他所在原始tiff
數(shù)據(jù)的像素位置,以及原始tiff
數(shù)據(jù)像素大小,就可以寫一個(gè)類似上文中的getBase64Image方法,遍歷每個(gè)網(wǎng)格,在網(wǎng)格對(duì)應(yīng)的像素位置上繪制顏色,然后再通過(guò)canvas
導(dǎo)出圖片添加到地圖。
總結(jié)
mapboxgl
的image
圖層無(wú)法直接添加tiff柵格數(shù)據(jù)mapboxgl
添加fill
圖層時(shí),地圖層級(jí)縮小到一定程度,面數(shù)據(jù)所占像素值過(guò)小無(wú)法顯示tiff
數(shù)據(jù)可以使用geotiff.js+canvas
解析,得到base64
的圖片,添加到mapboxgl
的image
圖層- 在解析
tiff
數(shù)據(jù)時(shí),需注意它的坐標(biāo)系、波段個(gè)數(shù)等信息 - 在做展示時(shí)可以
image
圖層和fill
圖層結(jié)合展示,效果較好
參考資料:
- https://geotiffjs.github.io/geotiff.js/
- https://github.com/stuartmatthews/leaflet-geotiff
- https://www.cnblogs.com/arxive/p/6746570.html
到此這篇關(guān)于mapboxgl加載tiff的文章就介紹到這了,更多相關(guān)mapboxgl加載tiff內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決maven第一次創(chuàng)建項(xiàng)目太慢的問(wèn)題
Maven是 Apache 下的一個(gè)純 Java 開發(fā)的開源項(xiàng)目,是一個(gè)項(xiàng)目構(gòu)建和管理的工具;它提供了幫助管理 構(gòu)建、文檔、報(bào)告、依賴、scms、發(fā)布、分發(fā)的方法。這篇文章主要介紹了maven第一次創(chuàng)建項(xiàng)目太慢的解決方法,需要的朋友可以參考下2020-02-02語(yǔ)言編程花絮內(nèi)建構(gòu)建順序示例詳解
這篇文章主要為大家介紹了語(yǔ)言編程花絮內(nèi)建構(gòu)建順序示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Elasticsearch設(shè)置密碼的方法與驗(yàn)證
在Elasticsearch中設(shè)置密碼是為了保護(hù)您的數(shù)據(jù)安全,下面這篇文章主要給大家介紹了關(guān)于Elasticsearch設(shè)置密碼方法與驗(yàn)證的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07網(wǎng)頁(yè)報(bào)錯(cuò)"Form?elements?must?have?labels"的處理方法
這篇文章主要給大家介紹了關(guān)于網(wǎng)頁(yè)報(bào)錯(cuò)"Form?elements?must?have?labels"的處理方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-06-06VSCode + WSL 2 + Ruby環(huán)境搭建圖文詳解
這篇文章主要介紹了VSCode + WSL 2 + Ruby環(huán)境搭建,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06網(wǎng)址(URL)支持的最大長(zhǎng)度是多少?最大支持多少個(gè)字符?
這篇文章主要介紹了網(wǎng)址(URL)支持的最大長(zhǎng)度是多少?最大支持多少個(gè)字符?本文總結(jié)了IIS、apache服務(wù)器及瀏覽器軟件Internet Explorer、Firefox、Opera、chrome等主流的瀏覽器軟件支持情況,需要的朋友可以參考下2015-07-07