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

class ArcLine { constructor(from, to, num = 100) { this.from = from; this.to = to; this.num = num; return this.getPointList(); } getPointList() { const { from, to } = this const 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.num const 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; } }
示例使用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, }); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。