|
|
@@ -479,7 +479,65 @@ export default {
|
|
|
overlays.push(polyline);
|
|
|
|
|
|
const totalPoints = segmentPath.length;
|
|
|
- const indices = this.pickEvenlySpacedIndices(totalPoints, 8);
|
|
|
+
|
|
|
+ // --- 核心优化:全路段物理距离均匀放置方向箭头 ---
|
|
|
+ // 1. 计算整条 segmentPath 的总物理距离及每个点的累计距离
|
|
|
+ const pathDistances = [0];
|
|
|
+ let totalPathDist = 0;
|
|
|
+ for (let j = 0; j < totalPoints - 1; j++) {
|
|
|
+ const d = this.calcApproxDistance(segmentPath[j], segmentPath[j+1]);
|
|
|
+ totalPathDist += d;
|
|
|
+ pathDistances.push(totalPathDist);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 设定标准间距:约每 0.0018 度 (约 200 米) 放置一个箭头
|
|
|
+ const targetSpacing = 0.0018;
|
|
|
+ let currentTargetDist = targetSpacing / 2; // 第一个箭头放在 1/2 间距处,让分布更美观
|
|
|
+
|
|
|
+ while (currentTargetDist < totalPathDist) {
|
|
|
+ // 3. 寻找对应 targetDist 的路径位置 (线性插值)
|
|
|
+ let foundIdx = 0;
|
|
|
+ for (let j = 0; j < pathDistances.length - 1; j++) {
|
|
|
+ if (currentTargetDist >= pathDistances[j] && currentTargetDist <= pathDistances[j + 1]) {
|
|
|
+ foundIdx = j;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const p1 = segmentPath[foundIdx];
|
|
|
+ const p2 = segmentPath[foundIdx + 1];
|
|
|
+ if (p1 && p2) {
|
|
|
+ // 在 p1 和 p2 之间线性插值
|
|
|
+ const ratio = (currentTargetDist - pathDistances[foundIdx]) / (pathDistances[foundIdx + 1] - pathDistances[foundIdx]);
|
|
|
+ const lng1 = p1.lng || (Array.isArray(p1) ? Number(p1[0]) : 0);
|
|
|
+ const lat1 = p1.lat || (Array.isArray(p1) ? Number(p1[1]) : 0);
|
|
|
+ const lng2 = p2.lng || (Array.isArray(p2) ? Number(p2[0]) : 0);
|
|
|
+ const lat2 = p2.lat || (Array.isArray(p2) ? Number(p2[1]) : 0);
|
|
|
+
|
|
|
+ const midLng = lng1 + (lng2 - lng1) * ratio;
|
|
|
+ const midLat = lat1 + (lat2 - lat1) * ratio;
|
|
|
+
|
|
|
+ const bearing = this.calcBearingDeg({ lng: lng1, lat: lat1 }, { lng: lng2, lat: lat2 });
|
|
|
+ const rotation = bearing - 90;
|
|
|
+
|
|
|
+ const directionMarker = new this.AMap.Marker({
|
|
|
+ position: [midLng, midLat],
|
|
|
+ content: `
|
|
|
+ <div style="transform: rotate(${rotation}deg); width: 20px; height: 10px; display: flex; align-items: center; pointer-events: none; opacity: 0.85;">
|
|
|
+ <img src="${require('@/assets/map/direction.png')}" style="width: 100%; height: auto;" />
|
|
|
+ </div>
|
|
|
+ `,
|
|
|
+ offset: new this.AMap.Pixel(-10, -5),
|
|
|
+ zIndex: 20,
|
|
|
+ bubble: true
|
|
|
+ });
|
|
|
+ overlays.push(directionMarker);
|
|
|
+ }
|
|
|
+ currentTargetDist += targetSpacing;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 为圆点保留原来的分布 logic (不受箭头影响)
|
|
|
+ const indices = this.pickEvenlySpacedIndices(totalPoints, 6);
|
|
|
|
|
|
// 为第一个和最后一个圆点设置特殊类型
|
|
|
for (let i = 0; i < indices.length; i++) {
|
|
|
@@ -604,9 +662,13 @@ export default {
|
|
|
const latRad = ((a.lat + b.lat) / 2) * Math.PI / 180;
|
|
|
const dx = (b.lng - a.lng) * Math.cos(latRad);
|
|
|
const dy = (b.lat - a.lat);
|
|
|
- let deg = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
|
- if (deg < 0) deg += 360;
|
|
|
- return deg;
|
|
|
+
|
|
|
+ // 使用地理方位角公式:0度为北,顺时针增加
|
|
|
+ // atan2(dy, dx) 返回数学角度(0为东,逆时针)
|
|
|
+ // geographic_bearing = (90 - math_angle + 360) % 360
|
|
|
+ const mathAngle = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
|
+ let bearing = (90 - mathAngle + 360) % 360;
|
|
|
+ return bearing;
|
|
|
},
|
|
|
|
|
|
calcAngleDiffDeg(a, b) {
|