使用Shapefile-js读取shp文件并使用WebGL绘制
1. 引言
坐标数据是空间数据文件的核心,空间数据的数据量往往是很大的。数据可视化是GIS的一个核心应用,绘制海量的坐标数据始终是一个考验设备性能的难题,使用GPU进行绘制可有效减少CPU的负载,提升绘制时的速度
shapefile是空间数据文件常用的格式,Shapefile-js提供了编写简单的JavaScript程序以读取ESRI Shapefile 以及关联的属性文件的功能,它可以在网页端使用,也可在Node.js环境下使用
Shapefile-js的GitHub地址:calvinmetcalf/shapefile-js: Convert a Shapefile to GeoJSON. Not many caveats. (github.com)
本文基于JavaScript语言,使用Shapefile-js库来读取shp文件,并使用WebGL绘制空间数据
2. 数据准备
数据为2015年中国省级行政边界数据(province),来源为:中国科学院资源环境科学与数据中心 (resdc.cn)
下图为数据的主要信息:
3. shp解析
原始的shp文件包含多个文件:
- shp文件
- dbf文件
- prj文件
- ......
方便起见,笔者把它们打包为一个zip文件,文件名为province.zip
,当然,这一步非必须
根据GitHub的示例,很简单就可以解析shp为json:
<script src='https://unpkg.com/shpjs@latest/dist/shp.js'> </script>
<script>
shp('http://127.0.0.1:5500/province/province.zip').then(function (data) {
console.log(data)
}
</script>
进行绘制需要读取shp文件的四至范围和每个Geometry的坐标数据,这里笔者使用OpenLayers进行加载GeoJSON
不妨使用OpenLayers绘制一下地图,读取四至范围:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- openlayers cdn -->
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.14.1/build/ol.js"></script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.14.1/css/ol.css">
</head>
<body>
<div id="map" style="height: 800px;"></div>
<script src='https://unpkg.com/shpjs@latest/dist/shp.js'> </script>
<script>
shp('http://127.0.0.1:5500/province/province.zip').then(function (data) {
console.log(data)
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Vector({
source: new ol.source.Vector({
features: new ol.format.GeoJSON().readFeatures(data, {
featureProjection: 'EPSG:3857'
})
}),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#f00',
width: 2
})
})
}),
],
view: new ol.View({
center: ol.proj.fromLonLat([104.114129, 37.550339]),
zoom: 3
})
});
console.log(map.getAllLayers()[1].getSource())
});
</script>
</body>
</html>
结果图如下:
4. WebGL绘制
WebGL详细的绘制流程可以参考:基于JavaScript的OpenGL 01 之Hello Triangle - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)
使用OpenGL绘制shp文件可以参考:使用Shapefile C Library读取shp文件并使用OpenGL绘制 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)
本文所使用的方法是每个Geometry绑定一个VAO和VBO,然后进行绘制
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src='https://unpkg.com/shpjs@latest/dist/shp.js'> </script>
<!-- openlayers cdn -->
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.14.1/build/ol.js"></script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.14.1/css/ol.css">
<style>
html,
body,
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas></canvas>
<script>
var canvas = document.querySelector('canvas');
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
var gl = canvas.getContext('webgl');
if (!gl) {
console.log('WebGL not supported, falling back to experimental-webgl');
}
gl.clearColor(0.2, 0.3, 0.3, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, `
attribute vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
`);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(vertexShader));
gl.deleteShader(vertexShader);
}
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, `
#version 100
void main()
{
gl_FragColor = vec4(1.0, 0.5, 0.2, 1.0);
}
`);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(fragmentShader));
gl.deleteShader(fragmentShader);
}
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
}
gl.useProgram(shaderProgram);
shp('http://127.0.0.1:5500/province/province.zip').then(function (data) {
console.log(data)
var features = new ol.format.GeoJSON().readFeatures(data, {
featureProjection: 'EPSG:3857'
})
var source = new ol.source.Vector({
features: features
})
console.log(source)
var minx, miny, maxx, maxy;
[minx, miny, maxx, maxy] = source.getExtent();
console.log(minx, miny, maxx, maxy)
for (let i = 0; i < features.length; i++) {
const feature = features[i];
const geometry = feature.getGeometry();
const coordinate = geometry.getCoordinates()[0];
let lineString = []
for (let j = 0; j < coordinate.length; j++) {
const point = coordinate[j];
let x = (point[0] - minx) / (maxx - minx) * 2 - 1;
let y = (point[1] - miny) / (maxy - miny) * 2 - 1;
lineString.push(x, y, 0.0);
}
const lineStringBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, lineStringBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(lineString), gl.STATIC_DRAW);
gl.vertexAttribPointer(gl.getAttribLocation(shaderProgram, 'aPos'), 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(0)
gl.drawArrays(gl.LINE_STRIP, 0, lineString.length / 3);
}
})
</script>
</body>
</html>
绘制结果图如下:
5. 参考资料
[1]calvinmetcalf/shapefile-js: Convert a Shapefile to GeoJSON. Not many caveats. (github.com)
[2]OpenLayers v6.14.1 API - Index
[3]使用Shapefile C Library读取shp文件并使用OpenGL绘制 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)
[4]基于JavaScript的OpenGL 01 之Hello Triangle - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)
使用Shapefile-js读取shp文件并使用WebGL绘制的更多相关文章
- 运用shapefile.js解析Shp文件
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...
- 手工创建tomcat应用,以及实现js读取本地文件内容
手工创建tomcat应用: 1.在webapps下面新建应用目录文件夹 2.在文件夹下创建或是从其他应用中复制:META-INF,WEB-INF这两个文件夹, 其中META-INF清空里面,WEB-I ...
- C#读取shp文件并获取图形保存到sde要素类中(不使用ESRI的类库,纯c#实现)
说明:首先要将sde要素类发布成对应的要素服务,通过对要素服务的操作,实现数据在sde要素类中的增删 //向服务器发出请求 public string getPostData(string postS ...
- Js读取XML文件为List结构
习惯了C#的List集合,对于Javascript没有list 极为不舒服,在一个利用Js读取XML文件的Demo中,决定自己构建List对象,将数据存入List. 第一步,Js读取XML文件知识 X ...
- IE下JS读取xml文件示例代码
JS读取xml文件具体步骤为:创建DOM对象.加载xml文件(仅适用于IE)附示例代码,感兴趣的朋友可以参考下,希望对大家有所帮助使用javascript脚本读取xml文件,这里暂只考虑IE浏览器st ...
- jQuery、JS读取xml文件里的内容(JS先通过document.implementation.createDocument方法将xml转换成document对象,jQuery将读取到的xml转成table)
xml文件:test.xml <?xml version="1.0"?> <note> <to>George</to> <fr ...
- GeoJson的生成与解析,JSON解析,Java读写geojson,geotools读取shp文件,Geotools中Geometry对象与GeoJson的相互转换
GeoJson的生成与解析 一.wkt格式的geometry转成json格式 二.json格式转wkt格式 三.json格式的数据进行解析 四.Java读写geojson 五.geotools读取sh ...
- js 读取xml文件
读取xml文件 [原创 2007-6-20 17:35:37] 字号:大 中 小 js中读取xml文件,简单的例子: <html><head><script> ...
- JS读取.properties文件的方法
假设有JavaScript文件叫做:readproperties.js,这个文件需要读取config.properties这个配置文件,步骤如下: 1. 下载插件jquery.i18n.proper ...
- JS读取XML文件数据并以table显示数据(兼容IE火狐)
先看xml文件: <?xml version="1.0" standalone="yes"?> <student> <stuinf ...
随机推荐
- MySQL视图-触发器
目录 一:视图 1.什么是视图? 2.为什么要用视图? 3.如何使用视图 4.反复拼接的繁琐(引入视图的作用) 5.解决方法 二:视图的应用 1.创建视图的格式: 2.查询视图层 3.查询Navica ...
- 可视化软件Navicat,python操作MySQL
可视化软件Navicat 第三方开发的用来充当数据库客户端的简单快捷的操作界面 无论第三方软件有多么的花里胡哨,底层的本质还是SQL 能够操作数据库的第三方可视化软件有很多,其中针对MySQL最出名的 ...
- 重学c#系列—— 反射深入一点点[三十三]
前言 在上一章中介绍了什么是反射: https://www.cnblogs.com/aoximin/p/16440966.html 正文 上一节讲述反射的基本原理和为什么要用反射,还用反射的优缺点这些 ...
- 从工具到实践:如何在GitHub上保障开源项目安全?
1998年,Christine Peterson创造了 "开源软件"这个词.她解释道:"这是刻意为之,为了让其他人更容易理解这个领域".同年,O'Reilly组 ...
- 经典 backbone 总结
目录 目录 VGG ResNet Inceptionv3 Resnetv2 ResNeXt Darknet53 DenseNet CSPNet VoVNet 一些结论 参考资料 VGG VGG网络结构 ...
- LeetCode-02 两数相加(Add Two Numbers)
描述 给出两个非空的链表用来表示两个非负的整数.其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和. 您 ...
- [Untiy]贪吃蛇大作战(四)——游戏主界面
游戏主界面: 由于这个场景比较复杂,需要分几个部分实现: 1.游戏背景 首先我们的游戏场景上包括了一个大的背景图片,之外再包围一个红色的区域.中间的区域才是可活动的区域,周围通过碰撞检测盒来检测是否有 ...
- 《机器人SLAM导航核心技术与实战》第1季:第4章_机器人传感器
<机器人SLAM导航核心技术与实战>第1季:第4章_机器人传感器 视频讲解 [第1季]4.第4章_机器人传感器-视频讲解 [第1季]4.1.第4章_机器人传感器_惯性测量单元-视频讲解 [ ...
- 用溪流 WarKey 辅助红警开局快捷操作
背景 自从发现红警除了 ddraw 补丁可以在最新的系统里玩后,就开始怀旧了.但是由于手残,遇到别人抢地盘基本上直接崩了.偶然有一次发现像 08 这样的高手点 30 个坦克使用工具的.那么,我开局用工 ...
- Crossplane - 比 Terraform 更先进的云基础架构管理平台?
️URL: https://crossplane.io/ Description: 将云基础架构和服务组成自定义平台 API 简介 在 11 月的 KCD 上海现场,听了一场阿里云的工程师关于他们自己 ...