@aibee/crc-bmap 0.8.41 → 0.8.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/bmap.cjs.min.js +38 -38
- package/lib/bmap.esm.js +261 -131
- package/lib/bmap.esm.min.js +38 -38
- package/lib/bmap.min.js +38 -38
- package/lib/src/loader/CrLoader/index.js +1 -0
- package/lib/src/operations/selection/selection.d.ts +1 -0
- package/lib/src/operations/selection/selection.js +5 -1
- package/lib/src/plugins/car-inertial-position/car-inertial-position.d.ts +5 -0
- package/lib/src/plugins/car-inertial-position/car-inertial-position.js +45 -12
- package/lib/src/plugins/car-inertial-position/utils.d.ts +1 -1
- package/lib/src/plugins/car-inertial-position/utils.js +69 -34
- package/lib/src/plugins/nav-path/nav-path.d.ts +1 -1
- package/lib/src/plugins/nav-path/nav-path.js +3 -2
- package/lib/src/plugins/nav-path/path.worker.js +2 -2
- package/lib/src/plugins/navigation/position-navigation.js +9 -7
- package/lib/src/utils/road2.d.ts +2 -1
- package/lib/src/utils/road2.js +85 -9
- package/package.json +1 -1
|
@@ -61,11 +61,15 @@ export class Selection extends EventDispatcher {
|
|
|
61
61
|
this.unRegistryEvent();
|
|
62
62
|
}
|
|
63
63
|
constructor(context){
|
|
64
|
-
super(), this.context = context, this._list = new Set(), this.downPoint = null, this.isMultipleSelect = false, this.onPointerDown = (e)=>{
|
|
64
|
+
super(), this.context = context, this._list = new Set(), this.downPoint = null, this.downTime = 0, this.isMultipleSelect = false, this.onPointerDown = (e)=>{
|
|
65
|
+
if (Date.now() - this.downTime < 200) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
65
68
|
this.downPoint = {
|
|
66
69
|
x: e.offsetX,
|
|
67
70
|
y: e.offsetY
|
|
68
71
|
};
|
|
72
|
+
this.downTime = Date.now();
|
|
69
73
|
}, this.onPointerUp = (e)=>{
|
|
70
74
|
if (!this.downPoint) {
|
|
71
75
|
return;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EventDispatcher } from "three";
|
|
2
2
|
import { Compass } from "./compass";
|
|
3
|
+
import { Timer } from "../../utils";
|
|
3
4
|
export interface CarPosition {
|
|
4
5
|
position: [number, number];
|
|
5
6
|
time: number;
|
|
@@ -23,10 +24,14 @@ export declare class CarInertialPosition extends EventDispatcher<CarInertialPosi
|
|
|
23
24
|
history: CarPosition[];
|
|
24
25
|
compass: Compass;
|
|
25
26
|
compassAngle: number;
|
|
27
|
+
timer: Timer;
|
|
28
|
+
positionTimer: number | null;
|
|
29
|
+
autoCleanTimer: number | null;
|
|
26
30
|
constructor();
|
|
27
31
|
startCompass(): void;
|
|
28
32
|
setPosition(position: CarPosition['position'], time: number): void;
|
|
29
33
|
setBeaconPosition(position: CarPosition['position'], time: number): void;
|
|
34
|
+
startPositionTimer(): void;
|
|
30
35
|
getPosition(): CarPosInfo;
|
|
31
36
|
dispose(): void;
|
|
32
37
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { EventDispatcher } from "three";
|
|
3
3
|
import { Compass } from "./compass";
|
|
4
4
|
import { calculateLineDirection, predictFuturePosition, predictFutureSpeed, transformSpeed } from "./utils";
|
|
5
|
+
import { getLength, Timer } from "../../utils";
|
|
5
6
|
export class CarInertialPosition extends EventDispatcher {
|
|
6
7
|
startCompass() {
|
|
7
8
|
this.compass.start();
|
|
@@ -12,15 +13,23 @@ export class CarInertialPosition extends EventDispatcher {
|
|
|
12
13
|
time,
|
|
13
14
|
type: "vision"
|
|
14
15
|
});
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
this.history
|
|
16
|
+
const MAX_DISTANCE = 20; // 保留最近20米的点
|
|
17
|
+
for(let i = 0; i < this.history.length; i++){
|
|
18
|
+
const item = this.history[i];
|
|
19
|
+
const distance = getLength(item.position, position);
|
|
20
|
+
if (distance > MAX_DISTANCE) {
|
|
21
|
+
this.history.shift();
|
|
22
|
+
i--;
|
|
23
|
+
} else {
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
18
26
|
}
|
|
19
27
|
const posInfo = this.getPosition();
|
|
20
28
|
this.dispatchEvent({
|
|
21
29
|
type: "change-pos",
|
|
22
30
|
value: posInfo
|
|
23
31
|
});
|
|
32
|
+
this.startPositionTimer();
|
|
24
33
|
}
|
|
25
34
|
setBeaconPosition(position, time) {
|
|
26
35
|
this.history.push({
|
|
@@ -33,6 +42,26 @@ export class CarInertialPosition extends EventDispatcher {
|
|
|
33
42
|
type: "change-pos",
|
|
34
43
|
value: posInfo
|
|
35
44
|
});
|
|
45
|
+
this.startPositionTimer();
|
|
46
|
+
}
|
|
47
|
+
startPositionTimer() {
|
|
48
|
+
if (this.positionTimer) {
|
|
49
|
+
this.timer.clearInterval(this.positionTimer);
|
|
50
|
+
}
|
|
51
|
+
if (this.autoCleanTimer) {
|
|
52
|
+
this.timer.clearTimeout(this.autoCleanTimer);
|
|
53
|
+
}
|
|
54
|
+
this.positionTimer = this.timer.setInterval(()=>{
|
|
55
|
+
const posInfo = this.getPosition();
|
|
56
|
+
this.dispatchEvent({
|
|
57
|
+
type: "change-pos",
|
|
58
|
+
value: posInfo
|
|
59
|
+
});
|
|
60
|
+
}, 20);
|
|
61
|
+
this.autoCleanTimer = this.timer.setTimeout(()=>{
|
|
62
|
+
this.positionTimer && this.timer.clearInterval(this.positionTimer);
|
|
63
|
+
this.positionTimer = null;
|
|
64
|
+
}, 1000);
|
|
36
65
|
}
|
|
37
66
|
getPosition() {
|
|
38
67
|
if (this.history.length === 0) {
|
|
@@ -55,11 +84,17 @@ export class CarInertialPosition extends EventDispatcher {
|
|
|
55
84
|
speed: 0
|
|
56
85
|
};
|
|
57
86
|
}
|
|
87
|
+
// 计算角度只用视觉的结果
|
|
58
88
|
const visionHistory = this.history.filter((item)=>item.type === "vision");
|
|
59
89
|
// 推导到当前时间距离最后一个定位点的时间
|
|
60
90
|
const angle = calculateLineDirection(visionHistory.map((history)=>history.position));
|
|
61
91
|
if (angle !== null) {
|
|
62
|
-
this.
|
|
92
|
+
this.compassAngle = angle;
|
|
93
|
+
this.dispatchEvent({
|
|
94
|
+
type: "change-compass",
|
|
95
|
+
value: angle
|
|
96
|
+
});
|
|
97
|
+
// this.compass.setAbsoluteCompass(angle, lastHistory.time);
|
|
63
98
|
}
|
|
64
99
|
const lastTime = lastHistory.time;
|
|
65
100
|
const deltaTime = Date.now() - lastTime;
|
|
@@ -76,15 +111,13 @@ export class CarInertialPosition extends EventDispatcher {
|
|
|
76
111
|
}
|
|
77
112
|
dispose() {
|
|
78
113
|
this.compass.stop();
|
|
114
|
+
this.timer.dispose();
|
|
79
115
|
}
|
|
80
116
|
constructor(){
|
|
81
|
-
super(), this.history = [], this.compass = new Compass(), this.compassAngle = 0;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
value
|
|
87
|
-
});
|
|
88
|
-
});
|
|
117
|
+
super(), this.history = [], this.compass = new Compass(), this.compassAngle = 0, this.timer = new Timer(), this.positionTimer = null, this.autoCleanTimer = null;
|
|
118
|
+
// this.compass.addEventListener("compass", ({ value }) => {
|
|
119
|
+
// this.compassAngle = value;
|
|
120
|
+
// this.dispatchEvent({ type: "change-compass", value })
|
|
121
|
+
// })
|
|
89
122
|
}
|
|
90
123
|
}
|
|
@@ -1,36 +1,79 @@
|
|
|
1
|
-
import { Vector2 } from "three";
|
|
1
|
+
import { BufferGeometry, Line, LineBasicMaterial, Vector2, Vector3 } from "three";
|
|
2
|
+
// 计算最小二乘法的斜率 (m) 和截距 (b)
|
|
3
|
+
function linearFit(points) {
|
|
4
|
+
const n = points.length;
|
|
5
|
+
let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
|
|
6
|
+
// 计算 Σx, Σy, Σxy, Σx²
|
|
7
|
+
points.forEach((p)=>{
|
|
8
|
+
sumX += p[0];
|
|
9
|
+
sumY += p[1];
|
|
10
|
+
sumXY += p[0] * p[1];
|
|
11
|
+
sumX2 += p[0] * p[0];
|
|
12
|
+
});
|
|
13
|
+
// 计算斜率 m 和 截距 b
|
|
14
|
+
const m = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
|
|
15
|
+
const b = (sumY - m * sumX) / n;
|
|
16
|
+
return {
|
|
17
|
+
m,
|
|
18
|
+
b
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
// 计算拟合直线的起点和终点
|
|
22
|
+
function getLineEndpoints(m, b, points) {
|
|
23
|
+
const startX = points[0][0];
|
|
24
|
+
const endX = points.slice(-1)[0][0];
|
|
25
|
+
// 根据x计算y值
|
|
26
|
+
const startY = m * startX + b;
|
|
27
|
+
const endY = m * endX + b;
|
|
28
|
+
return {
|
|
29
|
+
start: [
|
|
30
|
+
startX,
|
|
31
|
+
startY
|
|
32
|
+
],
|
|
33
|
+
end: [
|
|
34
|
+
endX,
|
|
35
|
+
endY
|
|
36
|
+
]
|
|
37
|
+
};
|
|
38
|
+
}
|
|
2
39
|
/**
|
|
3
|
-
* 计算一组点位的斜率和方向
|
|
40
|
+
* 计算一组点位的斜率和方向 拟合成一条直线 然后选择一个起点终点
|
|
4
41
|
* @param points
|
|
5
42
|
* @returns
|
|
6
43
|
*/ export function calculateLineDirection(points) {
|
|
7
|
-
|
|
8
|
-
if (n < 2) {
|
|
44
|
+
if (points.length < 2) {
|
|
9
45
|
return null;
|
|
10
46
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const angle = 360 - (radians / Math.PI * 180 - 90 + 360) % 360;
|
|
21
|
-
angles.push(angle);
|
|
22
|
-
}
|
|
23
|
-
const filteredAngles = removeOutliers(angles);
|
|
24
|
-
if (!filteredAngles.length) {
|
|
47
|
+
// 过滤掉相同的点
|
|
48
|
+
const filteredPoints = points.filter((item, index)=>{
|
|
49
|
+
const ps = [
|
|
50
|
+
...points
|
|
51
|
+
];
|
|
52
|
+
ps.splice(index, 1);
|
|
53
|
+
return ps.every((point)=>point[0] !== item[0] && point[1] !== item[1]);
|
|
54
|
+
});
|
|
55
|
+
if (filteredPoints.length < 2) {
|
|
25
56
|
return null;
|
|
26
57
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
58
|
+
const { m, b } = linearFit(filteredPoints);
|
|
59
|
+
const { start, end } = getLineEndpoints(m, b, filteredPoints);
|
|
60
|
+
const radians = new Vector2().subVectors(new Vector2(end[0], end[1]), new Vector2(start[0], start[1])).angle() // 于X轴的正方向的夹角 逆时针方向
|
|
61
|
+
;
|
|
62
|
+
// 这个是顺时针的角度 于Y轴正方向的夹角
|
|
63
|
+
const angle = 360 - (radians / Math.PI * 180 - 90 + 360) % 360;
|
|
64
|
+
const geometry = new BufferGeometry();
|
|
65
|
+
const center = window.map.buildingCenter;
|
|
66
|
+
if (center) {
|
|
67
|
+
geometry.setFromPoints([
|
|
68
|
+
new Vector3(start[0] - center[0], start[1] - center[1], 10),
|
|
69
|
+
new Vector3(end[0] - center[0], end[1] - center[1], 10)
|
|
70
|
+
]);
|
|
71
|
+
const line = new Line(geometry, new LineBasicMaterial({
|
|
72
|
+
color: 0x00ffff
|
|
73
|
+
}));
|
|
74
|
+
window.map.context.scene.add(line);
|
|
75
|
+
}
|
|
76
|
+
return angle;
|
|
34
77
|
}
|
|
35
78
|
/**
|
|
36
79
|
* 计算速度,单位是m/ms km/s
|
|
@@ -63,9 +106,7 @@ import { Vector2 } from "three";
|
|
|
63
106
|
* @param timeIntervalMs
|
|
64
107
|
* @returns
|
|
65
108
|
*/ export function predictFutureSpeed(positions, timeIntervalMs) {
|
|
66
|
-
console.log("timeIntervalMs", timeIntervalMs);
|
|
67
109
|
const speeds = calculateInstantaneousSpeed(positions);
|
|
68
|
-
console.log("speeds", speeds);
|
|
69
110
|
const n = speeds.length;
|
|
70
111
|
if (n === 0) {
|
|
71
112
|
return 0; // 如果没有速度数据,返回0
|
|
@@ -77,13 +118,11 @@ import { Vector2 } from "three";
|
|
|
77
118
|
if (n > 1) {
|
|
78
119
|
const speedDifferences = speeds.slice(1).map((speed, index)=>speed - speeds[index]);
|
|
79
120
|
const time = positions.slice(1).reduce((sum, cur, index)=>sum + (cur.time - positions[index].time), 0);
|
|
80
|
-
console.log("time", time);
|
|
81
121
|
if (!time) {
|
|
82
122
|
return 0;
|
|
83
123
|
}
|
|
84
124
|
acceleration = speedDifferences.reduce((sum, value)=>sum + value, 0) / time;
|
|
85
125
|
}
|
|
86
|
-
console.log("acceleration", acceleration);
|
|
87
126
|
// 预测未来速度 m/ms
|
|
88
127
|
const futureSpeed = Math.max(currentSpeed + acceleration * timeIntervalMs, 0);
|
|
89
128
|
return futureSpeed;
|
|
@@ -105,18 +144,14 @@ import { Vector2 } from "three";
|
|
|
105
144
|
* @returns
|
|
106
145
|
*/ export function predictFuturePosition(lastPosition, speed, angle, time) {
|
|
107
146
|
// 将角度转换为弧度
|
|
108
|
-
const angleInRadians = angle * (Math.PI / 180);
|
|
147
|
+
const angleInRadians = (angle + 90) % 360 * (Math.PI / 180);
|
|
109
148
|
const distance = speed * time;
|
|
110
|
-
console.log("angle speed", speed, distance);
|
|
111
149
|
const vec = new Vector2(lastPosition[0], lastPosition[1]);
|
|
112
150
|
// 计算角度在x和y方向的分量
|
|
113
151
|
const vX = Math.cos(angleInRadians);
|
|
114
152
|
const vY = Math.sin(angleInRadians);
|
|
115
153
|
const dir = new Vector2(vX, vY);
|
|
116
154
|
vec.add(dir.normalize().multiplyScalar(distance));
|
|
117
|
-
// // 计算未来位置
|
|
118
|
-
// const futureX = lastPosition[0] + vX * time;
|
|
119
|
-
// const futureY = lastPosition[1] + vY * time;
|
|
120
155
|
return [
|
|
121
156
|
vec.x,
|
|
122
157
|
vec.y
|
|
@@ -16,7 +16,7 @@ export declare class NavPath extends EventDispatcher<EventMap> {
|
|
|
16
16
|
initRoadStatus: boolean;
|
|
17
17
|
constructor();
|
|
18
18
|
setRoadData(roadData: RoadData2[], facilities: Facility[]): Promise<void>;
|
|
19
|
-
getPath(start: Start2, end: End2, type?: RouteType2, permission?: number): Promise<PathData>;
|
|
19
|
+
getPath(start: Start2, end: End2, type?: RouteType2, permission?: number, travelDirection?: number): Promise<PathData>;
|
|
20
20
|
getDirectionPath(points: [number, number][]): Promise<DirectionPathData[]>;
|
|
21
21
|
dispose(): Promise<void>;
|
|
22
22
|
}
|
|
@@ -23,7 +23,7 @@ export class NavPath extends EventDispatcher {
|
|
|
23
23
|
});
|
|
24
24
|
})();
|
|
25
25
|
}
|
|
26
|
-
getPath(start, end, type = "", permission) {
|
|
26
|
+
getPath(start, end, type = "", permission, travelDirection) {
|
|
27
27
|
var _this = this;
|
|
28
28
|
return _async_to_generator(function*() {
|
|
29
29
|
return new Promise((resolve, reject)=>{
|
|
@@ -33,7 +33,8 @@ export class NavPath extends EventDispatcher {
|
|
|
33
33
|
start,
|
|
34
34
|
end,
|
|
35
35
|
type,
|
|
36
|
-
permission
|
|
36
|
+
permission,
|
|
37
|
+
travelDirection
|
|
37
38
|
}).then((data)=>{
|
|
38
39
|
if (!data) {
|
|
39
40
|
reject("no-path");
|
|
@@ -6,8 +6,8 @@ toWebWorker({
|
|
|
6
6
|
onSetRoadInfo ({ roadData, facilities }) {
|
|
7
7
|
roadNetwork.initRoute(roadData, facilities);
|
|
8
8
|
},
|
|
9
|
-
onGetPath ({ start, end, type, permission }) {
|
|
10
|
-
return roadNetwork.getPath(start, end, type, permission);
|
|
9
|
+
onGetPath ({ start, end, type, permission, travelDirection }) {
|
|
10
|
+
return roadNetwork.getPath(start, end, type, permission, travelDirection);
|
|
11
11
|
},
|
|
12
12
|
onGetDirectionPath (points) {
|
|
13
13
|
return getDirectPath(points);
|
|
@@ -258,8 +258,7 @@ export class PositionNavigation extends EventDispatcher {
|
|
|
258
258
|
let dir = PathDirection.FRONT;
|
|
259
259
|
let crossName = (curRoutePath == null ? void 0 : (_curRoutePath_pointInfos_index = curRoutePath.pointInfos[index]) == null ? void 0 : _curRoutePath_pointInfos_index.crossName) || "";
|
|
260
260
|
let distance = 0;
|
|
261
|
-
|
|
262
|
-
while(dir === PathDirection.FRONT && distance < this.options.directionEmitThreshold && Date.now() - t < 5){
|
|
261
|
+
while(dir === PathDirection.FRONT && index <= curRoutePathPoints.length){
|
|
263
262
|
const p1 = curRoutePathPoints[index];
|
|
264
263
|
const p2 = curRoutePathPoints[index + 1];
|
|
265
264
|
const p3 = curRoutePathPoints[index + 2];
|
|
@@ -271,9 +270,12 @@ export class PositionNavigation extends EventDispatcher {
|
|
|
271
270
|
const l = getLength(p1, position);
|
|
272
271
|
if (l < 5) {
|
|
273
272
|
dir = PathDirection.START;
|
|
273
|
+
} else {
|
|
274
|
+
dir = PathDirection.FRONT;
|
|
275
|
+
index += 1;
|
|
274
276
|
}
|
|
275
277
|
} else {
|
|
276
|
-
distance += getLength(
|
|
278
|
+
distance += getLength(p1, p2);
|
|
277
279
|
if (!p3) {
|
|
278
280
|
dir = PathDirection.END;
|
|
279
281
|
} else {
|
|
@@ -322,10 +324,10 @@ export class PositionNavigation extends EventDispatcher {
|
|
|
322
324
|
return null;
|
|
323
325
|
}
|
|
324
326
|
let { dir, distance: nextDirDistance, crossName } = nextDirInfo;
|
|
325
|
-
if (dir === PathDirection.END && nextDirDistance > 15) {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
327
|
+
// if (dir === PathDirection.END && nextDirDistance > 15) {
|
|
328
|
+
// // 请直行
|
|
329
|
+
// dir = PathDirection.FRONT;
|
|
330
|
+
// }
|
|
329
331
|
// 剩余 5 米不管是不是拐弯都提示到达目的地
|
|
330
332
|
if (curRouteRemainDistance <= 10) {
|
|
331
333
|
dir = PathDirection.END;
|
package/lib/src/utils/road2.d.ts
CHANGED
|
@@ -275,9 +275,10 @@ export declare class RoadNetwork2 {
|
|
|
275
275
|
* @param end 终点
|
|
276
276
|
* @param type '' 最短路径 escalator 扶梯优先 straightLadder 直梯优先
|
|
277
277
|
* @param permission 0 无权限 1 通行卡
|
|
278
|
+
* @param travelDirection 行驶方向 从Y轴正方向的顺时针角度
|
|
278
279
|
* @returns
|
|
279
280
|
*/
|
|
280
|
-
getPath(start: Start2, end: End2, type?: RouteType2, permission?: number): "start-error" | "end-error" | "no-start" | "no-end" | PathData2 | null | undefined;
|
|
281
|
+
getPath(start: Start2, end: End2, type?: RouteType2, permission?: number, travelDirection?: number): "start-error" | "end-error" | "no-start" | "no-end" | PathData2 | null | undefined;
|
|
281
282
|
private getRoutePath;
|
|
282
283
|
private getBasePath;
|
|
283
284
|
private getEscalatorPath;
|
package/lib/src/utils/road2.js
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
8
8
|
import Graph from "node-dijkstra";
|
|
9
9
|
import { getLength, getPathLength } from "./coordinate";
|
|
10
|
-
import { cloneDeep } from "lodash";
|
|
10
|
+
import { cloneDeep, isNil } from "lodash";
|
|
11
|
+
import { Vector2 } from "three";
|
|
11
12
|
const SPLIT_FLG = "___";
|
|
12
13
|
export class RoadNetwork2 {
|
|
13
14
|
isFacilityByType(type) {
|
|
@@ -640,8 +641,9 @@ export class RoadNetwork2 {
|
|
|
640
641
|
* @param end 终点
|
|
641
642
|
* @param type '' 最短路径 escalator 扶梯优先 straightLadder 直梯优先
|
|
642
643
|
* @param permission 0 无权限 1 通行卡
|
|
644
|
+
* @param travelDirection 行驶方向 从Y轴正方向的顺时针角度
|
|
643
645
|
* @returns
|
|
644
|
-
*/ getPath(start, end, type = "", permission) {
|
|
646
|
+
*/ getPath(start, end, type = "", permission, travelDirection) {
|
|
645
647
|
if (!this.checkStart(start)) {
|
|
646
648
|
return "start-error";
|
|
647
649
|
}
|
|
@@ -656,7 +658,7 @@ export class RoadNetwork2 {
|
|
|
656
658
|
if (!transformedEnd) {
|
|
657
659
|
return "no-end";
|
|
658
660
|
}
|
|
659
|
-
let getPathFn
|
|
661
|
+
let getPathFn;
|
|
660
662
|
switch(type){
|
|
661
663
|
case "escalator":
|
|
662
664
|
getPathFn = this.getEscalatorPath.bind(this);
|
|
@@ -673,7 +675,7 @@ export class RoadNetwork2 {
|
|
|
673
675
|
}
|
|
674
676
|
if (transformedEnd.id) {
|
|
675
677
|
// 有明确的目的地了 直接规划路线
|
|
676
|
-
return getPathFn(transformedStart, transformedEnd, permission);
|
|
678
|
+
return getPathFn(transformedStart, transformedEnd, permission, travelDirection);
|
|
677
679
|
} else if (transformedEnd.facility) {
|
|
678
680
|
// 寻找最近的设施 如果传入了目的地楼层,只找对应楼层的设施
|
|
679
681
|
const facilityIds = this.facilities.filter((item)=>+item.type_id === +end.facility).map((item)=>item.id);
|
|
@@ -690,7 +692,7 @@ export class RoadNetwork2 {
|
|
|
690
692
|
const paths = facilityPoints.map((item)=>getPathFn(transformedStart, {
|
|
691
693
|
floor: item.floor,
|
|
692
694
|
id: item.id
|
|
693
|
-
}, permission)).filter((item)=>!!item);
|
|
695
|
+
}, permission, travelDirection)).filter((item)=>!!item);
|
|
694
696
|
// 寻找最近的路线
|
|
695
697
|
return paths.reduce((obj, cur)=>{
|
|
696
698
|
const distance = cur[0].consume;
|
|
@@ -869,10 +871,82 @@ export class RoadNetwork2 {
|
|
|
869
871
|
const tempRoute = new Graph(tempMap);
|
|
870
872
|
return this.getRoutePath(start, end, tempRoute);
|
|
871
873
|
}
|
|
872
|
-
// 规划正寻路线
|
|
873
|
-
getForwardPath(start, end, permission) {
|
|
874
|
+
// 规划正寻路线 travelDirection 行驶方向 从Y轴正方向的顺时针角度
|
|
875
|
+
getForwardPath(start, end, permission, travelDirection) {
|
|
876
|
+
const removedLine = new Map();
|
|
877
|
+
const removeBackLine = (backPoints)=>{
|
|
878
|
+
const map = this.forwardRoute.graph.get(startPointId);
|
|
879
|
+
backPoints.forEach((key)=>{
|
|
880
|
+
const distance = map.get(key);
|
|
881
|
+
if (!isNil(distance)) {
|
|
882
|
+
removedLine.set(key, distance);
|
|
883
|
+
map.delete(key);
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
};
|
|
887
|
+
const restoreBackLine = ()=>{
|
|
888
|
+
const map = this.forwardRoute.graph.get(startPointId);
|
|
889
|
+
removedLine.forEach((distance, key)=>{
|
|
890
|
+
map.set(key, distance);
|
|
891
|
+
});
|
|
892
|
+
};
|
|
893
|
+
const startPointId = `${start.floor}${SPLIT_FLG}${start.id}`;
|
|
894
|
+
if (!isNil(travelDirection)) {
|
|
895
|
+
// 如果有方向,要把起点位置的非行进方向的其他点删掉,规划完路线之后在加回去
|
|
896
|
+
const nextPoints = this.forwardLineMap.get(startPointId);
|
|
897
|
+
// 只有在这个点的连线多于一个点的时候才有其他方向的点
|
|
898
|
+
const startPoint = this.pointMap.get(startPointId);
|
|
899
|
+
if (startPoint && (nextPoints == null ? void 0 : nextPoints.size) && nextPoints.size > 1) {
|
|
900
|
+
const startVector2 = new Vector2(startPoint.cds[0], startPoint.cds[1]);
|
|
901
|
+
// 计算一下每个点的角度,如果有角度小于60度的就保留,删除其他的点
|
|
902
|
+
// 如果没有就保留角度最小的一个点,其他的点删除
|
|
903
|
+
const pointAngle = new Map();
|
|
904
|
+
nextPoints.forEach((value, key)=>{
|
|
905
|
+
const nextPoint = this.pointMap.get(key);
|
|
906
|
+
if (nextPoint) {
|
|
907
|
+
// 360 - ((radians / Math.PI) * 180 - 90 + 360) % 360;
|
|
908
|
+
const nextVector2 = new Vector2(nextPoint.cds[0], nextPoint.cds[1]);
|
|
909
|
+
// 和X轴的夹角的逆时针方向
|
|
910
|
+
const radiansX = new Vector2().subVectors(nextVector2, startVector2).angle();
|
|
911
|
+
// 和Y轴的夹角 顺时针方向
|
|
912
|
+
const angleY = 360 - (radiansX / Math.PI * 180 - 90 + 360) % 360;
|
|
913
|
+
pointAngle.set(key, angleY);
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
const lessThan60Keys = Array.from(pointAngle).filter(([key, value])=>Math.abs(value - travelDirection) <= 60).map(([key])=>key);
|
|
917
|
+
if (lessThan60Keys.length) {
|
|
918
|
+
// 删除其他大于60度的点
|
|
919
|
+
lessThan60Keys.forEach((key)=>pointAngle.delete(key));
|
|
920
|
+
removeBackLine([
|
|
921
|
+
...pointAngle.keys()
|
|
922
|
+
]);
|
|
923
|
+
} else {
|
|
924
|
+
// 找到差值最小的点
|
|
925
|
+
const min = Array.from(pointAngle).reduce((res, cur)=>{
|
|
926
|
+
const diff = Math.abs(cur[1] - travelDirection);
|
|
927
|
+
if (diff < res.diff) {
|
|
928
|
+
return {
|
|
929
|
+
diff,
|
|
930
|
+
key: cur[0]
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
return res;
|
|
934
|
+
}, {
|
|
935
|
+
diff: Infinity,
|
|
936
|
+
key: ''
|
|
937
|
+
});
|
|
938
|
+
// 删除其他的点
|
|
939
|
+
pointAngle.delete(min.key);
|
|
940
|
+
removeBackLine([
|
|
941
|
+
...pointAngle.keys()
|
|
942
|
+
]);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
874
946
|
if (!permission) {
|
|
875
|
-
|
|
947
|
+
const path = this.getRoutePath(start, end, this.forwardRoute);
|
|
948
|
+
restoreBackLine();
|
|
949
|
+
return path;
|
|
876
950
|
}
|
|
877
951
|
// 创建一个临时图
|
|
878
952
|
const tempMap = cloneDeep(this.forwardRoute.graph);
|
|
@@ -887,7 +961,9 @@ export class RoadNetwork2 {
|
|
|
887
961
|
]
|
|
888
962
|
]));
|
|
889
963
|
const tempRoute = new Graph(tempMap);
|
|
890
|
-
|
|
964
|
+
const path = this.getRoutePath(start, end, tempRoute);
|
|
965
|
+
restoreBackLine();
|
|
966
|
+
return path;
|
|
891
967
|
}
|
|
892
968
|
clear() {
|
|
893
969
|
this.roadInfo = [];
|