基于Lealfet.js展示Turf.js生成的平滑曲线实践
目录
前言
一、问题的由来
1、创建网页框架
2、创建map对象
3、构建点位,生成路线
二、Turf.js平滑曲线改造
1、官网方法介绍
2、0.4弯曲度曲线
3、0.85弯曲度曲线
4、0.1度弯曲曲线
5、综合对比
总结
前言
在很多的关于路线的gis应用中,我们经常会有展示路线的需求,比如采集关键点位的经纬度,最后连接成一条轨迹线。不知道各位朋友有没有遇到这种需求,如果只是在地图上采集一些关键点,得到的线经常是比较生硬的,尤其是在拐点的时候,展示效果更加的明显。形如下面的这种效果。
那么有没有什么办法能让这些拐点练成的曲线实际效果看上去更加平滑呢?有的小伙会说,可以在数据采集阶段尽可能多的采集多的点位信息,通过更多点位的采集,形成一条更加平滑的曲线。从技术的角度来说,这种方式是可以的,只要将点采集的更多,那么练成的曲线一定是更加平滑的。但是这样会增加采集的工作量。有没有办法在现有的成果之上来进行数据的平滑处理呢?
本博客给出一种解决方案,熟悉webgis开发的朋友一定知道多种解决方案。那么本文分享一款webgis的解决方案,基于Turf.js组件来动态生成平滑曲线,然后在webgis框架中进行展示。对于不熟悉或者没用过turf.js的小伙伴起到抛砖引玉的作用。对于想在Webgis中开发类似应用的小伙伴来说,可以看看这篇博客。
一、问题的由来
众所周知,线对象是由多个点对象组合而来,把多个点两两相连即可连成一条线。因此,这里我们首先模拟构造一条虚拟的游览线路。然后使用turf.js组件生成不同程度的平滑曲线。
为了展示最原始的线对象,我们采用Leaflet作为地图展示组件,再一起回顾一下Leaflet当中如何进行地图展示,以及集成Turf.js组件。
1、创建网页框架
首先创建一个html页面。在页面中我们需要引入Leaflet.css和Leaflet.js两个基础组件,同时引入Turf.js这个组件。关键代码如下:
<!DOCTYPE html>
<html>
<head>
<title>基于Leaflet和Turf生成平滑曲线实践</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
<link rel="stylesheet" href="/2d/leaflet/leaflet.css" />
<script src="/2d/leaflet/leaflet.js?v=1.0.0"></script>
<!-- 使用unpkg -->
<script src="https://unpkg.com/@turf/turf/turf.min.js"></script>
<style>
#map {
margin: 0;
padding: 0;
position: absolute;
width: 99%;
height: 98%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
</script>
</body>
</html>
2、创建map对象
在创建了基础的网页模板之后,再来定义map对象。以此在界面上绑定地图展示容器。代码如下:
var mymap = L.map('map').setView([29.052934, 104.0625], 6);
var tileLayer = L.tileLayer('http://localhost:8086/data/xxgc/q0403/{z}/{x}/{y}.png', {
maxZoom: 7,
minZoom:0
});
tileLayer.addTo(mymap);
3、构建点位,生成路线
这里仅为了演示效果,使用演示数据。虚拟场景为,构建一个自驾路线,从云南的保山市出发,依次经过攀枝花、昆明、成都、重庆、贵阳、长沙、赣州,最终到达福建的福州。以上城市的经纬度信息如下:
var cityPoint = new Array();
cityPoint.push([99.116482, 25.078402]);//保山
cityPoint.push([101.708392, 26.50289]);//攀枝花
cityPoint.push([102.780718, 24.915559]);//昆明
cityPoint.push([104.098757, 30.594412]);//成都
cityPoint.push([106.559098, 29.452047]);//重庆
cityPoint.push([106.515163, 26.461228]);//贵阳
cityPoint.push([112.929622, 28.141659]);//长沙
cityPoint.push([114.956049, 25.713705]);//赣州
cityPoint.push([119.344081, 26.027307]);//福州
然后,我们将这些点位数据连成一条线,在地图上展示出来。
var linestring = turf.lineString(cityPoint, {name: 'line 1'});
L.geoJSON(linestring,{style:{color:"blue",wight:2,fill:false}}).addTo(mymap);
先来看一下原始的曲线效果,请注意各个拐点的实际效果。通过以下结果可以看到,原始的路线展示确实不够平滑。
二、Turf.js平滑曲线改造
首先对turf.js对于平滑曲线改造的方法进行一个简单的介绍。首先来看一下Turf.js官网对多线段平滑的方法说明。
1、官网方法介绍
turf.js是使用bezierSpline()进行多线段平滑的构建支持的。其原理是接受一条线,通过应用贝塞尔样条算法返回一个弯曲的版本。关于白塞尔曲线的的创建原理,有兴趣的朋友可以去查询相关搜索引擎。里面还是有一点知识点的。
我们先来看一下这个方法:
bezierSpline方法参数
参数 | 类型 | 描述 |
---|---|---|
line | Feature <LineString> | input LineString |
options | Object | 可选参数:见下文 |
options选项
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
resolution | number | 10000 | 点之间的时间(毫秒) |
sharpness | number | 0.85 | 衡量样条路径应该有多弯曲的一个度量 |
方法的返回值是Feature <LineString> - 弯曲的线。
2、0.4弯曲度曲线
了解了上面的方法后,在我们的应用当中调用生成方法。弯曲度的设置这里,首先我们设置成0.4,来看一下在0.4的弯曲度下,生成的平滑曲线是什么效果。
var curved = turf.bezierSpline(linestring,{sharpness:0.4,resolution:10000});//0.4的弯曲度
L.geoJSON(curved,{style:{color:"red",wight:2,fill:false}}).addTo(mymap);
为了与原始的路线进行差异对比,我们将0.4弯曲度的路线设置为红色。在浏览器中查看实际效果。很明显可以看到,与原始路线相比,整条路线看起来平滑多了。
3、0.85弯曲度曲线
在弯曲度0.4的情况下,曲线已经明显发生光滑。来看一下0.85的弯曲度下是什么效果。
L.geoJSON(turf.bezierSpline(linestring,{sharpness:0.85,resolution:10000}),{style:{color:"green",wight:2,fill:false}}).addTo(mymap);//0.85的弯曲度
我们发现0.85的曲线,其弯曲度处理的更大了,与实际效果有一定的差异。
4、0.1度弯曲曲线
最后再来看一下0.1度弯曲的曲线是什么效果。
L.geoJSON(turf.bezierSpline(linestring,{sharpness:0.1,resolution:10000}),{style:{color:"yellow",wight:2,fill:false}}).addTo(mymap);//0.1的弯曲度
5、综合对比
为了比较不同弯曲度下,曲线的平滑程度。为了直观的展示效果,将三种平滑度同时叠加。
通过效果可以看到,弯曲度系数越大,曲线的平滑程度也是比较大。黄色表示0.1的弯曲度,红色表示0.4的弯曲度,绿色表示0.85的弯曲度。
序号 | 弯曲度 | 实际效果 |
1 | 0.1 | 与原始拟合 |
2 | 0.4 | 有一定弯曲 |
3 | 0.85 | 弯曲较大 |
最后给出完整的示例代码,请注意在运行时替换本地图源地址。
<!DOCTYPE html>
<html>
<head>
<title>基于Leaflet和Turf生成平滑曲线实践</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
<link rel="stylesheet" href="/2d/leaflet/leaflet.css" />
<script src="/2d/leaflet/leaflet.js?v=1.0.0"></script>
<!-- 使用unpkg -->
<script src="https://unpkg.com/@turf/turf/turf.min.js"></script>
<style>
#map {
margin: 0;
padding: 0;
position: absolute;
width: 99%;
height: 98%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var mymap = L.map('map').setView([29.052934, 104.0625], 6);
var tileLayer = L.tileLayer('http://localhost:8086/data/xxgc/q0403/{z}/{x}/{y}.png', {
maxZoom: 7,
minZoom:0
});
tileLayer.addTo(mymap);
var cityPoint = new Array();
cityPoint.push([99.116482, 25.078402]);
cityPoint.push([101.708392, 26.50289]);
cityPoint.push([102.780718, 24.915559]);
cityPoint.push([104.098757, 30.594412]);
cityPoint.push([106.559098, 29.452047]);
cityPoint.push([106.515163, 26.461228]);
cityPoint.push([112.929622, 28.141659]);
cityPoint.push([114.956049, 25.713705]);
cityPoint.push([119.344081, 26.027307]);
var linestring = turf.lineString(cityPoint, {name: 'line 1'});
L.geoJSON(linestring,{style:{color:"blue",wight:2,fill:false}}).addTo(mymap);
var curved = turf.bezierSpline(linestring,{sharpness:0.4,resolution:10000});//0.4的弯曲度
L.geoJSON(curved,{style:{color:"red",wight:2,fill:false}}).addTo(mymap);
L.geoJSON(turf.bezierSpline(linestring,{sharpness:0.85,resolution:10000}),{style:{color:"green",wight:2,fill:false}}).addTo(mymap);//0.85的弯曲度
L.geoJSON(turf.bezierSpline(linestring,{sharpness:0.1,resolution:10000}),{style:{color:"yellow",wight:2,fill:false}}).addTo(mymap);//0.1的弯曲度
</script>
</body>
</html>
总结
以上就是本文的主要内容,那么本文分享一款webgis的解决方案,基于Turf.js组件来动态生成平滑曲线,然后在webgis框架中进行展示。对于不熟悉或者没用过turf.js的小伙伴起到抛砖引玉的作用。如果您对在webgis中如何展示平滑曲线有一定的处理需求,不妨来看看这篇博客。行文仓促,难免有不当之处,欢迎各位小伙伴,各位专家批评指正。