当前位置: 首页 > news >正文

二阶贝塞尔曲线生成弧线

概述

本文分享一个二阶贝塞尔曲线曲线生成弧线的算法。

效果

image.png

实现

1. 封装方法

class ArcLine {constructor(from, to, num = 100) {this.from = from;this.to = to;this.num = num;return this.getPointList();}getPointList() {const { from, to } = thisconst ctrlPoint = this.getOffsetPoint(from, to);const points = this.create2PBezier(from, ctrlPoint, to)return points}getOffsetPoint(start, end) {const distance = this.getDistance(start, end) / 2; //除以3?let angle, dX, dY;const mp = [start[0], start[1]];const deltaAngle = - Math.PI / 8; //偏移0.2弧度if (start[0] != end[0] && start[1] != end[1]) { //斜率存在const k = (end[1] - start[1]) / (end[0] - start[0]);angle = Math.atan(k);} else if (start[0] == end[0]) { //垂直线angle = (start[1] <= end[1] ? 1 : -1) * Math.PI / 2;} else { //水平线angle = 0;}if (start[0] <= end[0]) {angle -= deltaAngle;dX = Math.round(Math.cos(angle) * distance);dY = Math.round(Math.sin(angle) * distance);mp[0] += dX;mp[1] += dY;} else {angle += deltaAngle;dX = Math.round(Math.cos(angle) * distance);dY = Math.round(Math.sin(angle) * distance);mp[0] -= dX;mp[1] -= dY;}return mp;}getDistance(p1, p2) {return Math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]));}bezier2P(p0, p1, p2, t) {const P0 = p0 * Math.pow(1 - t, 2);const P1 = p1 * 2 * t * (1 - t);const P2 = p2 * t * t;return P0 + P1 + P2;}getBezierNowPoint2P(p0, p1, p2, num, tick) {return {x: this.bezier2P(p0[0], p1[0], p2[0], num * tick),y: this.bezier2P(p0[1], p1[1], p2[1], num * tick),};}create2PBezier(p0, p1, p2) {const num = this.numconst t = 1 / (num - 1);const points = [];for (let i = 0; i < num; i++) {const point = this.getBezierNowPoint2P(p0, p1, p2, i, t);points.push([point.x, point.y]);}return points;}
}

2. 前端调用

示例使用openlayers实现。

let vetSource = new ol.source.Vector({features: [],
});
let vectorLayer = new ol.layer.Vector({source: vetSource,style: new ol.style.Style({stroke: new ol.style.Stroke({color: "#f00",width: 2,}),}),
});
map.addLayer(vectorLayer)function addAllLines() {let features = [];for (let i = 0; i < pointData.length; i++) {const after = pointData[i];const from = [101.797439042302, 36.5937248286007];const to = [after.lon, after.lat].map(Number);let points = new ArcLine(from, to);points = points.map((p) => ol.proj.fromLonLat(p));lineData.push(points);features.push(new ol.Feature({geometry: new ol.geom.LineString(points),}));}vetSource.addFeatures(features);map.getView().animate({center: [12474607.173951693, 4278483.982819865],zoom: 3.8,});
}
http://www.lryc.cn/news/279279.html

相关文章:

  • FilterQuery过滤查询
  • java多线程(并发)夯实之路-线程池深入浅出
  • 数据库-列的类型-字符串char类型
  • 大话 JavaScript(Speaking JavaScript):第二十一章到第二十五章
  • ICMP协议
  • 环信服务端下载消息文件---菜鸟教程
  • 创建型模式 | 建造者模式
  • MVC设计模式
  • WSL (2103) ERROR: CreateProcessEntryCommon:493: chdir 错误解决
  • 【二、自动化测试】为什么要做自动化测试?哪种项目适合做自动化?
  • 用ChatGPT来造一个ChatGPT:计算机领域智能问答系统实践(2)
  • Ubuntu开机自动挂载硬盘
  • vue3基础:单文件组件介绍
  • OCR字符识别:开始批量识别身份证信息
  • php多小区智慧物业管理系统源码带文字安装教程
  • 解决虚拟机的网络图标不见之问题
  • 【Spring类路径Bean定义信息扫描】
  • Ubuntu上安装VMware+win11系统手册
  • 2024年1月12日:清爽无糖rio留下唇齿之间的香甜
  • 群晖Synology Drive同步文件时过滤指定文件夹“dist“, “node_modules“
  • 小程序中滚动字幕
  • MySQL中约束是什么?
  • 若依在表格中如何将字典的键值转为中文
  • 用笨办法-刻意练习来提高自己的编程能力
  • FineBI报表页面大屏小屏自适应显示问题
  • NAND Separate Command Address (SCA) 接口命令解读
  • Git的简单使用说明
  • 少儿编程 2023年12月电子学会图形化编程等级考试Scratch二级真题解析(判断题)
  • 前端面试 -- vue系列
  • open3d相关操作总结