OpenLayers 精确经过三个点的曲线绘制

OpenLayers 精确经过三个点的曲线绘制

根据您的需求,我将提供一个使用 OpenLayers 绘制精确经过三个指定点的曲线解决方案。对于三个点的情况,我们可以使用 二次贝塞尔曲线三次样条插值,确保曲线精确通过所有控制点。

实现方案

下面是一个完整的实现,使用二次贝塞尔曲线算法生成平滑曲线,确保曲线精确通过所有三个控制点:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>OpenLayers 精确经过三个点的曲线</title><script src="https://cdn.jsdelivr.net/npm/ol@7.3.0/dist/ol.js"></script><link href="https://cdn.jsdelivr.net/npm/ol@7.3.0/ol.css" rel="stylesheet"><style>.map {width: 100%;height: 500px;}</style>
</head>
<body><div id="map" class="map"></div><script>// 1. 指定要经过的三个顶点(经纬度坐标)const controlPoints = [[116.3, 39.9],    // 北京[118.8, 37.5],    // 青岛[121.4, 31.2]     // 上海];// 2. 坐标转换工具const transformToMercator = (points) => points.map(point => ol.proj.transform(point, 'EPSG:4326', 'EPSG:3857'));// 3. 二次贝塞尔曲线算法(关键函数)function quadraticBezierCurve(start, control, end, segments = 50) {const result = [];for (let t = 0; t <= 1; t += 1 / segments) {// 二次贝塞尔公式: B(t) = (1-t)²P0 + 2(1-t)tP1 + t²P2const x = Math.pow(1 - t, 2) * start[0] + 2 * (1 - t) * t * control[0] + Math.pow(t, 2) * end[0];const y = Math.pow(1 - t, 2) * start[1] + 2 * (1 - t) * t * control[1] + Math.pow(t, 2) * end[1];result.push([x, y]);}return result;}// 4. 计算控制点位置(确保曲线经过三个点)function calculateControlPoint(p0, p1, p2) {// 控制点位置计算方法:// 假设中间点p1是曲线上的点,则控制点C的位置可以通过以下公式计算:// p1 = 0.5² * p0 + 2 * 0.5 * 0.5 * C + 0.5² * p2// 解得:C = 2 * p1 - 0.5 * (p0 + p2)return [2 * p1[0] - 0.5 * (p0[0] + p2[0]),2 * p1[1] - 0.5 * (p0[1] + p2[1])];}// 5. 创建地图与渲染const map = new ol.Map({target: 'map',layers: [new ol.layer.Tile({ source: new ol.source.OSM() })],view: new ol.View({center: ol.proj.transform([119, 34], 'EPSG:4326', 'EPSG:3857'),zoom: 5})});// 6. 转换坐标并计算贝塞尔曲线const mercatorPoints = transformToMercator(controlPoints);const start = mercatorPoints[0];const middle = mercatorPoints[1];const end = mercatorPoints[2];// 计算控制点const controlPoint = calculateControlPoint(start, middle, end);// 生成贝塞尔曲线const curvePoints = quadraticBezierCurve(start, controlPoint, end, 100);// 7. 创建曲线要素与样式const curveFeature = new ol.Feature({geometry: new ol.geom.LineString(curvePoints)});curveFeature.setStyle(new ol.style.Style({stroke: new ol.style.Stroke({color: 'rgba(255, 0, 0, 0.8)',width: 4,lineCap: 'round',lineJoin: 'round'})}));// 8. 添加控制点标记const vectorSource = new ol.source.Vector();vectorSource.addFeature(curveFeature);controlPoints.forEach((point, index) => {const mercatorPoint = transformToMercator([point])[0];vectorSource.addFeature(new ol.Feature({geometry: new ol.geom.Point(mercatorPoint),style: new ol.style.Style({image: new ol.style.Circle({radius: 8,fill: new ol.style.Fill({ color: 'blue' }),stroke: new ol.style.Stroke({ color: 'white', width: 2 })}),text: new ol.style.Text({text: `${index + 1}`,font: '14px Arial',fill: new ol.style.Fill({ color: 'black' }),offsetY: -15})})}));});// 9. 添加控制点标记(显示计算出的控制点)vectorSource.addFeature(new ol.Feature({geometry: new ol.geom.Point(controlPoint),style: new ol.style.Style({image: new ol.style.Circle({radius: 6,fill: new ol.style.Fill({ color: 'rgba(0, 128, 0, 0.6)' }),stroke: new ol.style.Stroke({ color: 'white', width: 1 })}),text: new ol.style.Text({text: '控制点',font: '12px Arial',fill: new ol.style.Fill({ color: 'black' }),offsetY: 15})})}));map.addLayer(new ol.layer.Vector({ source: vectorSource }));</script>
</body>
</html>

核心技术解析

  1. 二次贝塞尔曲线算法

    • 对于三个点的情况,二次贝塞尔曲线是最适合的选择
    • 曲线公式:B(t) = (1-t)²P0 + 2(1-t)tP1 + t²P2,其中P0和P2是起点和终点,P1是控制点
  2. 控制点计算

    • 为了确保曲线经过中间点,我们通过数学方法计算出合适的控制点位置
    • 控制点公式:C = 2 * P1 - 0.5 * (P0 + P2),其中P1是需要经过的中间点
  3. 曲线精度控制

    • segments 参数控制曲线的分段数
    • 值越大,曲线越平滑,但计算量也会增加

使用与调整

  1. 修改控制点

    • 编辑 controlPoints 数组,修改三个经纬度坐标点
    • 必须提供三个点才能生成曲线
  2. 调整曲线平滑度

    • 修改 quadraticBezierCurve 函数中的 segments 参数
    • 默认值为100,可根据需要增加或减少
  3. 样式定制

    • 修改曲线的颜色、宽度和线型
    • 调整控制点标记的大小和颜色
      在这里插入图片描述

这种方法生成的曲线能够精确经过所有三个指定的点,同时保持整体的平滑性,非常适合需要精确路径的地理可视化应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80265.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django缓存框架API

这里写自定义目录标题 访问缓存django.core.cache.cachesdjango.core.cache.cache 基本用法cache.set(key, value, timeoutDEFAULT_TIMEOUT, versionNone)cache.get(key, defaultNone, versionNone)cache.add(key, value, timeoutDEFAULT_TIMEOUT, versionNone)cache.get_or_se…

Linux系统管理与编程17:自动化部署ftp服务

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 #virtual用户管理&#xff1a;passerbyA、captain和admin三个虚拟用户 # passerbyA只能看&#xff0c;captain可看读写上传&#xff0c;但不能删除。admin全部权限 [rootshell shell]…

2025python学习笔记

一.Python语言基础入门 第一章 01.初识Python Python的起源&#xff1a; 1989年&#xff0c;为了打发圣诞节假期&#xff0c;Gudio van Rossum吉多范罗苏姆&#xff08;龟叔&#xff09;决心开发一个新的解释程序&#xff08;Python维形&#xff09;1991年&#xff0c;第一个…

STM32单片机的快速成长路径规划

一、基础准备阶段&#xff08;1-2周&#xff09; C语言核心技能 重点掌握&#xff1a;指针操作、结构体、枚举、位操作、函数指针&#xff08;回调函数基础&#xff09;实践项目&#xff1a;通过51单片机或STM8完成LED控制、按键检测等基础项目&#xff0c;熟悉寄存器配置和调试…

torch.nn.init.uniform_

nn.init.uniform_ 是 PyTorch 中用于初始化张量&#xff08;tensor&#xff09;的一个函数&#xff0c;它的作用是将张量的值填充为从均匀分布中采样的随机数。 详细说明&#xff1a; 函数&#xff1a; torch.nn.init.uniform_(tensor, a0., b1.)tensor&#xff1a;需要被初始…

Spring MVC中跨域问题处理

在Spring MVC中处理跨域问题可以通过以下几种方式实现&#xff0c;确保前后端能够正常通信&#xff1a; 方法一&#xff1a;使用 CrossOrigin 注解 适用于局部控制跨域配置&#xff0c;直接在Controller或方法上添加注解。 示例代码&#xff1a; RestController CrossOrigin…

基本句子结构

以下是英语句子五种基本结构的详细解释&#xff0c;并附上系动词的全面分类及示例&#xff1a; ​1. 主谓结构&#xff08;SV&#xff09;​ ​结构&#xff1a;主语&#xff08;Subject&#xff09; 不及物动词&#xff08;Intransitive Verb&#xff09;​核心&#xff1a;…

游戏引擎学习第264天:将按钮添加到分析器

回顾并为今天的工作做铺垫 随着时间的推移&#xff0c;我们的分析器&#xff08;profiler&#xff09;变得越来越强大。我通常会问大家是否记得我们要做什么&#xff0c;今天我们要做的似乎是按钮相关的功能。 今天的目标是实现按钮功能。我们从昨天留下的地方继续&#xff0…

大节点是选择自建机房还是托管机房

选择PCDN大节点自建机房还是托管机房&#xff0c;需综合考量资金实力、技术能力、运维需求、业务规模及合规要求。以下为具体分析&#xff1a; 自建机房的适用场景与考量因素 资金与技术门槛高 自建机房需投入服务器、存储、网络设备等硬件&#xff0c;以及机房建设、电力、散…

【SpringBoot】SpringBoot中使用AOP实现日志记录功能

前言一、AOP基本概念二、项目准备三、实现日志记录切面1、创建自定义日志注解2、实现日志切面3、配置AOP 四、使用示例1. 在Controller中使用2. 在Service中使用 六、高级配置1. 日志内容格式化2. 异步日志记录3. 日志脱敏处理 七、代理类生成的核心逻辑问题1&#xff1a; 既然…

linux中的常用命令(一)

目录 常用的快捷键 1- tab键:命令或者路径提示及补全&#xff1b; 2-ctrlc:放弃当前输入&#xff0c;终止当前任务或程序 3-ctrll;清屏 4-ctrlinsert:复制 5-鼠标右键:粘贴&#xff1b; 6-altc:断开连接/ctrlshift r 重新连接 7-alt1/2/3/等&#xff1a;切换回话窗口 8-上下键…

Pycharm(十九)深度学习

一、深度学习概述 1.1 什么是深度学习 深度学习是机器学习中的一种特殊方法,它使用称为神经网络的复杂结构,特别是“深层”的神经网络,来学习和做出预测。深度学习特别适合处理大规模和高维度的数据,如图像、声音和文本。深度学习、机器学习和人工智能之间的关系如下图所…

多视图密集对应学习:细粒度3D分割的自监督革命

原文标题&#xff1a;Multi-view Dense Correspondence Learning (MvDeCor) 引言 在计算机视觉与图形学领域&#xff0c;3D形状分割一直是一个基础且具有挑战性的任务。如何在标注稀缺的情况下&#xff0c;实现对3D模型的细粒度分割&#xff1f;近期&#xff0c;斯坦福大学视觉…

Vue——前端vue3项目使用汉字转拼音

在 Vue3 项目中&#xff0c;可以通过以下 第三方 JavaScript 包 实现汉字转拼音。这些包均兼容 Vue3&#xff0c;且无需依赖后端处理&#xff1a; 推荐方案 1. pinyin-pro 特点&#xff1a;功能强大、支持多音字、声调、拼音匹配、轻量级&#xff08;~20KB&#xff09;。安装…

批量统计PDF页数,统计图像属性

软件介绍&#xff1a; 1、支持批量统计PDF、doc\docx、xls\xlsx页数 2、支持统计指定格式文件数量&#xff08;不填格式就是全部&#xff09; 3、支持统计JPG、JPEG、PNG图像属性 4、支持统计多页TIF页数、属性 5、支持统计PDF、JPG画幅 统计图像属性 「托马斯的文件助手」…

LeetCode 每日一题 2025/5/5-2025/5/11

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 5/5 790. 多米诺和托米诺平铺5/6 1920. 基于排列构建数组5/7 3341. 到达最后一个房间的最少时间 I5/8 3342. 到达最后一个房间的最少时间 II5/9 3343. 统计平衡排列的数目5…

pytest自动化测试执行环境切换的两种解决方案

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、痛点分析 在实际企业的项目中&#xff0c;自动化测试的代码往往需要在不同的环境中进行切换&#xff0c;比如多套测试环境、预上线环境、UAT环境、线上环…

visual studio 2015 安装闪退问题

参考链接&#xff1a; VS2012安装时启动界面一闪而过问题解决办法 visual studio 2015 安装闪退问题

RocketMQ Kafka区别

架构 ZooKeeper&#xff1a;管理 Broker 注册、分区 Leader 选举及消费者组状态。Broker&#xff1a;存储 Partition数据&#xff0c;每个 Partition 为独立日志文件。Producer/Consumer&#xff1a;通过 ZooKeeper获取路由信息&#xff0c;实现消息分发与消费。 NameServer&am…

MySQL进阶篇2_SQL优化、锁

文章目录 1 SQL优化1.1插入数据优化1.2主键优化页分裂页合并主键设计原则 1.3order by设计优化1.4group by设计优化小理解 1.5limit设计优化顺序IO和随机IO小疑惑 1.6count设计优化1.7update优化关于隐式事务事务的DML操作 锁全局锁表级锁表锁元数据锁意向锁 行级锁锁的释放条件…