缘起

近期在项目中遇到这么一个需求,需要在地图上展示一组格网数据,格网大小为2m*2m,地图api用的mapboxgl。起初拿到这个需要感觉很easy,在地图上添加一个fill图层就好啦。把格网面数据添加到地图上之后,在大比例尺下显示正常,但是当地图层级小于15级时,渲染出的结果会消失。

简单理一下原因,应该是在地图缩小后,每个网格所占的像素太小,所以就消失了。

mapboxgl在处理symbol图层的时候,会遇到点位自动避让问题,导致部分点位不显示。解决方法是把layout中的icon-allow-overlap设置为true,这样就相当于关闭了自动避让功能,所有点图标保持可见状态。但是针对fill图层却没有这么一个属性。

但是这种情况又需要查看数据,要如何实现呢?

首先分析下数据,我的原始数据是通过模型导出的tiff格式的栅格数据,然后在后台根据tiff格式数据中每个像素所在行列号以及其灰度值生成带属性的格网数据,其中像素的灰度值就是在渲染时需要分类展示的值。既然原始tiff数据的灰度值就是所用的属性值,那是不是直接添加到地图就好了。接下来的解决方案就是看是否能直接用mapboxgl直接加载tiff数据,并渲染出自己想要的效果。

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]
]});

可是,当我把地址换成tiff数据时却报错了。下面为报错内容:

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

可以简单理解为不支持tiff格式。

tiff文件解析

既然mapboxglimage图层不支持tiff格式,那是不是可以把tiff数据导出成png呢,于是使用arcmap打开了tiff数据,导出数据格式也支持png,但是在保存时又报错了。

经过分析,发现是tiff数据波段数量的原因,我的这份数据波段数为1,从网上下载了一份测试数据,波段数为3,可以成功导出。

在查找相关解决方案的时候,看到这么个工具,geotiff.js,可以通过js解析tiff数据并渲染,leaflet有个扩展就是用的这个工具,https://github.com/stuartmatthews/leaflet-geotiff。查看geotiff.js相关文档,发现其实用起来还是挺方便的,通过简单的代码实现的我的需求。

先使用geotiff.js解析tiff数据,再配合使用canvas绘制图片导出base64格式数据,然后就可以使用添加到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 // 波段数量,一个波段:[0],三个波段:[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)
// 根据灰度值所在范围渲染颜色
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
}
});
}

本以为到这里问题已经解决,但是在查看地图时,发现图片图层数据叠加到底图有不小的偏移。

经过一番对比分析,发现原来是tiff数据的坐标系与地图坐标系不一致的导致的。我拿到的tiff数据坐标系为西安80的投影坐标系,在展示时配置的为wgs84地理坐标系,所以会有偏差。既然是坐标系问题,那就通过工具对tiff文件做下投影转换。这里用的是arcmap,打开ArcToolbox–>Data Management Tools–>Projections and Transformations–>Raster–>Project Raster

转换之后会发现,数据的行列值也会发生变化,也就是tiff图片的大小和形状都有所变化。

转换前:

转换后:

使用转换后的数据再次解析,然后叠加到地图,位置完全匹配。

最终展示方案

通过尝试发现,单独的图片展示时,由于图片分辨率固定,当地图等级放大到一定程度图片会被放大很多导致图片模糊不清,展示效果不理想;单独的格网面展示时,当地图等级缩小到一定程度,面图层则会消失,也就是文章开头提到的问题。

综上,根据自己的格网数据大小,判断在哪个等级格网面数据会消失,小于这个等级使用图片展示,大于这个等级用格网面展示,就可以完美的展示出想要的效果。

处理前效果:

处理后效果:

以上为有tiff栅格数据情况的解决方案,针对于只有格网面数据,而没有tiff栅格数据的情况要怎么解决呢?

如果在这组格网数据中,每个网格的属性中有他所在原始tiff数据的像素位置,以及原始tiff数据像素大小,就可以写一个类似上文中的getBase64Image方法,遍历每个网格,在网格对应的像素位置上绘制颜色,然后再通过canvas导出图片添加到地图。

总结

  1. mapboxglimage图层无法直接添加tiff栅格数据
  2. mapboxgl添加fill图层时,地图层级缩小到一定程度,面数据所占像素值过小无法显示
  3. tiff数据可以使用geotiff.js+canvas解析,得到base64的图片,添加到mapboxglimage图层
  4. 在解析tiff数据时,需注意它的坐标系、波段个数等信息
  5. 在做展示时可以image图层和fill图层结合展示,效果较好

参考资料:

  1. https://geotiffjs.github.io/geotiff.js/
  2. https://github.com/stuartmatthews/leaflet-geotiff
  3. https://www.cnblogs.com/arxive/p/6746570.html

原文地址:http://gisarmory.xyz/blog/index.html?blog=mapboxgl-geotiff

欢迎关注《GIS兵器库

本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名《GIS兵器库》(包含链接:  http://gisarmory.xyz/blog/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

mapboxgl加载tiff的更多相关文章

  1. Flex 加载tiff

    gis系统常常要加载tiff,因为好多土地证书,各种文件都是扫描件,如果你是用as来写的前台,怎么加载呢,顺便说下用插件AlternaTIFF也是可以得不过浏览器加载这么多插件是不太好的. 首先TIF ...

  2. Flex 加载 wmf,svg

    最近做gis系统发现要在flex加载wmf图片.我记得flash的loader只能是png,gis,jpg.wmf格式居然是window出的,flash居然不支持我也是醉了,没办法,只能后台转格式,首 ...

  3. geotrellis使用(二十三)动态加载时间序列数据

    目录 前言 实现方法 总结 一.前言        今天要介绍的绝对是华丽的干货.比如我们从互联网上下载到了一系列(每天或者月平均等)的MODIS数据,我们怎么能够对比同一区域不同时间的数据情况,采用 ...

  4. ios UIWebView 在开发中加载文件

    UIWebView 在实际应用中加载文件的时候,有两种情况, 1. 实行在线预览 , 2. 下载到本地,再查看 如果是第一种情况: NSURL *url = [NSURL URLWithString: ...

  5. C#中使用FreeImage库加载Bmp、JPG、PNG、PCX、TGA、PSD等25种格式的图像(源码)。

    其实我一直都是喜欢自己去做图像格式的解码的(目前我自己解码的图像格式大概有15种),但是写本文主要原因是基于CSDN的这个帖子的: http://bbs.csdn.net/topics/3905104 ...

  6. 快速加载DXF、DWG格式文件控件ABViewer

    ABViewer是一种高品质,低成本,高效率的多功能设计及工程文档管理应用程序. ABViewer为您提供专业的cad文件浏览和编辑工具. 支持多种格式,如:DWG格式, DXF, DWF, Hewl ...

  7. ArcGIS Engine中数据的加载 (转)

    1.加载Shapefile数据 1 IWorkspaceFactory pWorkspaceFactory; 2 IFeatureWorkspace pFeatureWorkspace; 3 IFea ...

  8. Arc Engine下数据的加载处理

    1.加载Shapefile数据 IWorkspaceFactory pWorkspaceFactory; IFeatureWorkspace pFeatureWorkspace; IFeatureLa ...

  9. ArcGIS Engine中加载数据

    ArcGIS Engine中加载数据 http://blog.csdn.net/gisstar/article/details/4206822   分类: AE开发积累2009-05-21 16:49 ...

随机推荐

  1. Office共享协作方法——Office共享的正确打开方式、office365白嫖

    OFFICE共享协作方法: 1.OFFICE365激活<推荐.一劳永逸.体验最新版office,协作体验更佳> 一部分用户自带的Office可以用KMS直接激活,那就ok了,注意激活前关闭 ...

  2. IDEA中web项目打成war包并在本地tomcat部署(超细版)

    准备工作:相关软件及插件IDEA(2021.1.3).tomcat(8.5.50)且在IDEA中调用tomcat运行时没有任何错误的,如何下载安装百度都有详细的介绍,这里就不过多的介绍了,版本不同操作 ...

  3. Excel用户如何打破内卷?只需要一个新软件,就能突破excel天花板

    还在死磕Excel吗?到底值不值得? 你看看,现在有多少excel培训班和培训课?网上各种EXCEL使用技巧教程也是满天飞.很多人为了提升Excel技能,不遗余力学习各种函数用法.VBA用法等等,最近 ...

  4. P2532 [AHOI2012]【一本通提高组合数学】树屋阶梯

    [AHOI2012]树屋阶梯 题目描述 输入格式 一个正整数N( 1 ≤ N ≤ 500 1\le N \le 500 1≤N≤500),表示阶梯的高度. 输出格式 一个正整数,表示搭建方法的个数.( ...

  5. rust里的内存对齐

    内存对齐主要遵循下面三个原则: 结构体变量的起始地址能够被其最宽的成员大小整除 结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节 结构体总体大小能够被最宽的成 ...

  6. 安卓手机如何无线连接adb?

    一般情况,大家adb调试手机,都是通过数据线的,但这样又是不太方便,所以我们可以通过WLAN来adb. 我的是华为手机,进入:设置-关于手机,连续点击版本号,唤出开发者模式.然后去返回设置-系统和更新 ...

  7. Python 支付宝红包二维码制作步骤分享

    本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! 支付宝红包二维码制作步骤分享 2022. ...

  8. Macos系统编译percona及部分函数在Macos系统上运算差异

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 本文来源:原创投稿 GreatSQL社区原创内容未经授权不得随意使用,转载请联系 ...

  9. JS的简介

    JS式JavaScript的简称,它是一门弱语言,它可以实现让网页动起来 JS的构成 核心(ECMAScript) 文档对象模型(DOM)-- Document Object  Module 浏览器对 ...

  10. 若依3.6.0使用Mybatis-plus分页失效以及完美替换Pagehelper

    一.前言 小编最近在经历后端框架的迁移,虽然不是小编来做,但是有个分页的情况让小编和一个同事去搞. 说一下小编这边的需求: 原来框架使用Mybatis-plus进行分页,要更换的新框架若依是使用Pag ...