如何用 OpenLayers 实现线段平滑?一文详解

关注我,带你一起学GIS ^

注:当前使用的是 ol [9.2.4] 版本,天地图使用的key请到天地图官网申请,并替换为自己的key

前言

在地理信息系统(GIS)和地图开发中,线段的平滑处理是提升数据可视化效果和用户体验的重要环节。OpenLayers 作为一款强大的开源地图库,提供了丰富的几何操作功能,其中线段平滑不仅能优化地图数据的显示效果,还能减少冗余节点、提升渲染性能。本文将深入探讨 OpenLayers 中线段平滑的核心原理、实现方法以及实际应用场景,帮助开发者掌握这一关键技术,打造更加流畅、美观的地图应用。

本文来源于OpenLayers官方例子,详情可参考官网:https://openlayers.org/en/v9.2.4/examples/chaikin.html

1. 前期准备

对于非模块化开发方式,直接通过 CDN 引入 chaikin-smooth 时会报错 require is not defined

通常是因为该库是为 Node.js 环境设计的,使用了 CommonJS 的 require 语法,而不是为浏览器环境设计的 UMD 或 ES 模块格式,所以不能直接引用。

可行的修改方式是将代码下载到本地,创建平滑方法,然后通过js引用。

// 数组复制
const copy = function (out, a) {
    out[0] = a[0]
    out[1] = a[1]
    return out
}
// chaikin-smooth平滑算法
function smooth(input, output) {
    if (!Array.isArray(output))
        output = []

    if (input.length > 0)
        output.push(copy([0, 0], input[0]))
    for (var i = 0; i < input.length - 1; i++) {
        var p0 = input[i]
        var p1 = input[i + 1]
        var p0x = p0[0],
            p0y = p0[1],
            p1x = p1[0],
            p1y = p1[1]

        var Q = [0.75 * p0x + 0.25 * p1x, 0.75 * p0y + 0.25 * p1y]
        var R = [0.25 * p0x + 0.75 * p1x, 0.25 * p0y + 0.75 * p1y]
        output.push(Q)
        output.push(R)
    }
    if (input.length > 1)
        output.push(copy([0, 0], input[input.length - 1]))
    return output
}

GitHub仓库地址:https://github.com/Experience-Monks/chaikin-smooth/blob/master/index.js

2. 创建绘制控件

通过Style类添加绘制对象样式,设置在绘制过程中几何线段的可视化效果。

// 图层以及绘制样式
const style = new ol.style.Style({
    fill: new ol.style.Fill({
        color: "#9b65ff30"
    }),
    stroke: new ol.style.Stroke({
        color: "yellow",
        width: 2.5,
    }),
    image: new ol.style.Circle({
        fill: new ol.style.Fill({
            color: "blue"
        }),
        radius: 2.5,
        stroke: new ol.style.Stroke({
            color: "blue",
            width: 1.5,
        }),
    })
})

创建矢量数据源和矢量图层以及绘制交互控件,并将其添加到地图中。在绘制对象中,只需将参数type设置为”LineString”即可绘制线段。

// 添加绘制图层
const vectorSource = new ol.source.Vector({ wrapX: false })
const vectorLayer = new ol.layer.Vector({
    source: vectorSource,
    style
})
map.addLayer(vectorLayer)
// 添加绘制交互控件
const drawInteraction = new ol.interaction.Draw({
    type"LineString",
    source: vectorSource,
    style: style
})
map.addInteraction(drawInteraction)

3. 线段平滑

在平滑函数中根据平滑值返回平滑坐标,然后监听交互控件绘制完成事件,在其中调用线段平滑方法,并设置要素平滑坐标。

const smoothInput = document.querySelector(".smoothInput")
const smoothNum = document.querySelector(".smoothNum")
smoothInput.addEventListener("change"function (event) {
    const value = event.target.value
    smoothNum.innerText = value
})
// 平滑函数
function makeSmooth(path, numInterations) {
    numInterations = Math.min(Math.max(numInterations, 1), 10)
    // 输出平滑坐标
    while (numInterations > 0) {
        path = smooth(path)
        numInterations--
    }
    return path
}
// 监听绘制完成事件
drawInteraction.on("drawend", event => {
    feat = event.feature
    const geometry = feat.getGeometry()
    const coordinates = geometry.getCoordinates()
    const smoothPath = makeSmooth(coordinates, parseInt(smoothInput.value, 10) || 5)
    // 设置平滑坐标
    geometry.setCoordinates(smoothPath)
})

OpenLayers示例数据下载,请在公众号后台回复:ol数据

全国信息化工程师-GIS 应用水平考试资料,请在公众号后台回复:GIS考试

GIS之路公众号已经接入了智能助手,欢迎大家前来提问。

欢迎访问我的博客网站-长谈GIShttp://shanhaitalk.com

都看到这了,不要忘记点赞、收藏+关注 

本号不定时更新有关 GIS开发  相关内容,欢迎关注 

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部