@jorgmoritz/gis-manager 0.1.21 → 0.1.26
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/dist/{VertexDetailInfo-BoVDy22s.d.cts → VertexDetailInfo-CProWwqv.d.cts} +51 -1
- package/dist/{VertexDetailInfo-BoVDy22s.d.ts → VertexDetailInfo-CProWwqv.d.ts} +51 -1
- package/dist/index.cjs +347 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -12
- package/dist/index.d.ts +36 -12
- package/dist/index.js +347 -52
- package/dist/index.js.map +1 -1
- package/dist/vue/index.cjs +346 -51
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.d.cts +1 -1
- package/dist/vue/index.d.ts +1 -1
- package/dist/vue/index.js +346 -51
- package/dist/vue/index.js.map +1 -1
- package/package.json +1 -1
package/dist/vue/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Cesium from 'cesium';
|
|
2
|
-
import { V as VertexDetailInfo, a as VertexOperationInfo } from '../VertexDetailInfo-
|
|
2
|
+
import { V as VertexDetailInfo, a as VertexOperationInfo } from '../VertexDetailInfo-CProWwqv.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* 🎨 GisViewer 组件 - Vue3 声明式地图容器
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Cesium from 'cesium';
|
|
2
|
-
import { V as VertexDetailInfo, a as VertexOperationInfo } from '../VertexDetailInfo-
|
|
2
|
+
import { V as VertexDetailInfo, a as VertexOperationInfo } from '../VertexDetailInfo-CProWwqv.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* 🎨 GisViewer 组件 - Vue3 声明式地图容器
|
package/dist/vue/index.js
CHANGED
|
@@ -60,6 +60,8 @@ var CameraEventBus = class {
|
|
|
60
60
|
__publicField(this, "onPoseChange", new Emitter());
|
|
61
61
|
/** 视锥体形状变化事件 */
|
|
62
62
|
__publicField(this, "onFrustumShapeChange", new Emitter());
|
|
63
|
+
/** 飞机游标姿态变化事件 */
|
|
64
|
+
__publicField(this, "onCursorPoseChange", new Emitter());
|
|
63
65
|
}
|
|
64
66
|
/**
|
|
65
67
|
* 清理所有监听器
|
|
@@ -68,9 +70,20 @@ var CameraEventBus = class {
|
|
|
68
70
|
this.onFOVChange.clear();
|
|
69
71
|
this.onPoseChange.clear();
|
|
70
72
|
this.onFrustumShapeChange.clear();
|
|
73
|
+
this.onCursorPoseChange.clear();
|
|
71
74
|
}
|
|
72
75
|
};
|
|
73
|
-
var
|
|
76
|
+
var GLOBAL_KEY = "__gisManager_globalCameraEventBus__";
|
|
77
|
+
function getGlobalEventBus() {
|
|
78
|
+
if (typeof window !== "undefined") {
|
|
79
|
+
if (!window[GLOBAL_KEY]) {
|
|
80
|
+
window[GLOBAL_KEY] = new CameraEventBus();
|
|
81
|
+
}
|
|
82
|
+
return window[GLOBAL_KEY];
|
|
83
|
+
}
|
|
84
|
+
return new CameraEventBus();
|
|
85
|
+
}
|
|
86
|
+
var globalCameraEventBus = getGlobalEventBus();
|
|
74
87
|
|
|
75
88
|
// src/core/LayerManager.ts
|
|
76
89
|
var layerIdSeq = 0;
|
|
@@ -1078,7 +1091,9 @@ var SceneManager = class {
|
|
|
1078
1091
|
depth: true,
|
|
1079
1092
|
stencil: true,
|
|
1080
1093
|
antialias: true,
|
|
1081
|
-
powerPreference: "high-performance"
|
|
1094
|
+
powerPreference: "high-performance",
|
|
1095
|
+
preserveDrawingBuffer: true
|
|
1096
|
+
// 必需:允许 canvas.toDataURL() 截图
|
|
1082
1097
|
}
|
|
1083
1098
|
},
|
|
1084
1099
|
...viewerOptions
|
|
@@ -1516,8 +1531,8 @@ var CameraFOVController = class {
|
|
|
1516
1531
|
if (!this.sliderEl) return;
|
|
1517
1532
|
const sliderValue = parseFloat(this.sliderEl.value);
|
|
1518
1533
|
const sliderIndex = this.focalLengthPresets.length - 1 - sliderValue;
|
|
1519
|
-
const
|
|
1520
|
-
const fov = this.
|
|
1534
|
+
const focalLength = this.interpolateFocalLength(sliderIndex);
|
|
1535
|
+
const fov = this.focalLengthToFOV(focalLength);
|
|
1521
1536
|
this.currentFOV = fov;
|
|
1522
1537
|
this.updateDisplay();
|
|
1523
1538
|
this.emitChange();
|
|
@@ -1525,24 +1540,35 @@ var CameraFOVController = class {
|
|
|
1525
1540
|
this.sensorWidth = opts.sensorWidth ?? 36;
|
|
1526
1541
|
this.focalLengthPresets = opts.focalLengthPresets ?? [112, 56, 14, 7, 3, 1];
|
|
1527
1542
|
if (opts.minFOV === void 0 || opts.maxFOV === void 0) {
|
|
1528
|
-
const
|
|
1529
|
-
const
|
|
1530
|
-
this.maxFOV = this.
|
|
1531
|
-
this.minFOV = this.
|
|
1543
|
+
const minFocalLength = Math.min(...this.focalLengthPresets);
|
|
1544
|
+
const maxFocalLength = Math.max(...this.focalLengthPresets);
|
|
1545
|
+
this.maxFOV = this.focalLengthToFOVDirect(minFocalLength);
|
|
1546
|
+
this.minFOV = this.focalLengthToFOVDirect(maxFocalLength);
|
|
1532
1547
|
} else {
|
|
1533
1548
|
this.minFOV = opts.minFOV;
|
|
1534
1549
|
this.maxFOV = opts.maxFOV;
|
|
1535
1550
|
}
|
|
1536
|
-
this.currentFOV = opts.initialFOV ?? this.
|
|
1551
|
+
this.currentFOV = opts.initialFOV ?? this.focalLengthToFOVDirect(56);
|
|
1537
1552
|
this.useGlobalEventBus = opts.useGlobalEventBus ?? true;
|
|
1538
1553
|
this.createUI();
|
|
1554
|
+
this.setupExternalFOVListener();
|
|
1539
1555
|
}
|
|
1540
1556
|
/**
|
|
1541
|
-
*
|
|
1557
|
+
* 🆕 监听外部 FOV 变化事件(来自 UI 面板等),同步更新滑块位置
|
|
1542
1558
|
*/
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1559
|
+
setupExternalFOVListener() {
|
|
1560
|
+
if (!this.useGlobalEventBus) return;
|
|
1561
|
+
globalCameraEventBus.onFOVChange.on((event) => {
|
|
1562
|
+
if (event.source !== "controller") {
|
|
1563
|
+
this.setFOVSilent(event.fov);
|
|
1564
|
+
}
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* 焦距转换为 FOV(度)- 直接计算版本
|
|
1569
|
+
*/
|
|
1570
|
+
focalLengthToFOVDirect(focalLengthMm) {
|
|
1571
|
+
const fovRad = 2 * Math.atan(this.sensorWidth / (2 * focalLengthMm));
|
|
1546
1572
|
return fovRad * 180 / Math.PI;
|
|
1547
1573
|
}
|
|
1548
1574
|
/**
|
|
@@ -1666,7 +1692,7 @@ var CameraFOVController = class {
|
|
|
1666
1692
|
`;
|
|
1667
1693
|
this.focalLengthPresets.forEach((fl) => {
|
|
1668
1694
|
const marker = document.createElement("div");
|
|
1669
|
-
marker.textContent = `${fl}
|
|
1695
|
+
marker.textContent = `${fl}`;
|
|
1670
1696
|
marker.style.cssText = `
|
|
1671
1697
|
cursor: pointer;
|
|
1672
1698
|
padding: 2px 4px;
|
|
@@ -1681,7 +1707,7 @@ var CameraFOVController = class {
|
|
|
1681
1707
|
marker.style.background = "transparent";
|
|
1682
1708
|
});
|
|
1683
1709
|
marker.addEventListener("click", () => {
|
|
1684
|
-
this.
|
|
1710
|
+
this.setFocalLength(fl);
|
|
1685
1711
|
});
|
|
1686
1712
|
markersContainer.appendChild(marker);
|
|
1687
1713
|
});
|
|
@@ -1694,38 +1720,38 @@ var CameraFOVController = class {
|
|
|
1694
1720
|
this.emitChange();
|
|
1695
1721
|
}
|
|
1696
1722
|
/**
|
|
1697
|
-
*
|
|
1723
|
+
* 根据索引插值计算焦距值
|
|
1698
1724
|
*/
|
|
1699
|
-
|
|
1725
|
+
interpolateFocalLength(index) {
|
|
1700
1726
|
const clampedIndex = Math.max(0, Math.min(this.focalLengthPresets.length - 1, index));
|
|
1701
1727
|
if (Number.isInteger(clampedIndex)) {
|
|
1702
1728
|
return this.focalLengthPresets[clampedIndex];
|
|
1703
1729
|
}
|
|
1704
1730
|
const lowerIndex = Math.floor(clampedIndex);
|
|
1705
1731
|
const upperIndex = Math.ceil(clampedIndex);
|
|
1706
|
-
const
|
|
1707
|
-
const
|
|
1732
|
+
const lowerFL = this.focalLengthPresets[lowerIndex];
|
|
1733
|
+
const upperFL = this.focalLengthPresets[upperIndex];
|
|
1708
1734
|
const fraction = clampedIndex - lowerIndex;
|
|
1709
|
-
return
|
|
1735
|
+
return lowerFL + (upperFL - lowerFL) * fraction;
|
|
1710
1736
|
}
|
|
1711
1737
|
/**
|
|
1712
|
-
*
|
|
1738
|
+
* 根据焦距值计算对应的索引(可以是小数)
|
|
1713
1739
|
*/
|
|
1714
|
-
|
|
1715
|
-
const
|
|
1716
|
-
const
|
|
1717
|
-
const
|
|
1740
|
+
getFocalLengthIndex(focalLength) {
|
|
1741
|
+
const minFL = Math.min(...this.focalLengthPresets);
|
|
1742
|
+
const maxFL = Math.max(...this.focalLengthPresets);
|
|
1743
|
+
const clampedFL = Math.max(minFL, Math.min(maxFL, focalLength));
|
|
1718
1744
|
for (let i = 0; i < this.focalLengthPresets.length - 1; i++) {
|
|
1719
1745
|
const current = this.focalLengthPresets[i];
|
|
1720
1746
|
const next = this.focalLengthPresets[i + 1];
|
|
1721
|
-
if (current <=
|
|
1722
|
-
const fraction = (
|
|
1747
|
+
if (current <= clampedFL && clampedFL <= next || current >= clampedFL && clampedFL >= next) {
|
|
1748
|
+
const fraction = (clampedFL - current) / (next - current);
|
|
1723
1749
|
return i + fraction;
|
|
1724
1750
|
}
|
|
1725
1751
|
}
|
|
1726
1752
|
return this.focalLengthPresets.indexOf(
|
|
1727
1753
|
this.focalLengthPresets.reduce(
|
|
1728
|
-
(prev, curr) => Math.abs(curr -
|
|
1754
|
+
(prev, curr) => Math.abs(curr - clampedFL) < Math.abs(prev - clampedFL) ? curr : prev
|
|
1729
1755
|
)
|
|
1730
1756
|
);
|
|
1731
1757
|
}
|
|
@@ -1734,8 +1760,7 @@ var CameraFOVController = class {
|
|
|
1734
1760
|
*/
|
|
1735
1761
|
getClosestPresetIndex(fov) {
|
|
1736
1762
|
const focalLength = this.fovToFocalLength(fov);
|
|
1737
|
-
const
|
|
1738
|
-
const index = this.getZoomMultiplierIndex(zoomMultiplier);
|
|
1763
|
+
const index = this.getFocalLengthIndex(focalLength);
|
|
1739
1764
|
return this.focalLengthPresets.length - 1 - index;
|
|
1740
1765
|
}
|
|
1741
1766
|
/**
|
|
@@ -1743,9 +1768,8 @@ var CameraFOVController = class {
|
|
|
1743
1768
|
*/
|
|
1744
1769
|
updateDisplay() {
|
|
1745
1770
|
const focalLength = this.fovToFocalLength(this.currentFOV);
|
|
1746
|
-
const zoomMultiplier = focalLength / this.sensorWidth;
|
|
1747
1771
|
if (this.labelEl) {
|
|
1748
|
-
this.labelEl.textContent = `\
|
|
1772
|
+
this.labelEl.textContent = `\u7126\u8DDD ${Math.round(focalLength)}`;
|
|
1749
1773
|
}
|
|
1750
1774
|
}
|
|
1751
1775
|
/**
|
|
@@ -1816,6 +1840,18 @@ var CameraFOVController = class {
|
|
|
1816
1840
|
this.updateDisplay();
|
|
1817
1841
|
this.emitChange();
|
|
1818
1842
|
}
|
|
1843
|
+
/**
|
|
1844
|
+
* 🆕 静默设置 FOV(度)- 只更新滑块位置,不广播事件
|
|
1845
|
+
* 用于响应外部 FOV 变化事件,避免循环广播
|
|
1846
|
+
*/
|
|
1847
|
+
setFOVSilent(fovDeg) {
|
|
1848
|
+
this.currentFOV = Math.max(this.minFOV, Math.min(this.maxFOV, fovDeg));
|
|
1849
|
+
if (this.sliderEl) {
|
|
1850
|
+
const index = this.getClosestPresetIndex(this.currentFOV);
|
|
1851
|
+
this.sliderEl.value = String(index);
|
|
1852
|
+
}
|
|
1853
|
+
this.updateDisplay();
|
|
1854
|
+
}
|
|
1819
1855
|
/**
|
|
1820
1856
|
* 获取当前 FOV
|
|
1821
1857
|
*/
|
|
@@ -2882,6 +2918,7 @@ var AirplaneCursor = class {
|
|
|
2882
2918
|
this.opts?.onPose?.({ ...pose });
|
|
2883
2919
|
this.viewer.scene?.requestRender?.();
|
|
2884
2920
|
this.updateFrustum();
|
|
2921
|
+
this.broadcastPoseChange();
|
|
2885
2922
|
}
|
|
2886
2923
|
requestAnimationFrame(update);
|
|
2887
2924
|
};
|
|
@@ -2939,9 +2976,15 @@ var AirplaneCursor = class {
|
|
|
2939
2976
|
} catch {
|
|
2940
2977
|
}
|
|
2941
2978
|
}
|
|
2942
|
-
/**
|
|
2979
|
+
/** 获取当前姿态(包含高度信息) */
|
|
2943
2980
|
getPose() {
|
|
2944
|
-
|
|
2981
|
+
const C = this.CesiumNS;
|
|
2982
|
+
const cartographic = C.Cartographic.fromCartesian(this.pose.position);
|
|
2983
|
+
const altitude = cartographic ? cartographic.height : 0;
|
|
2984
|
+
return {
|
|
2985
|
+
...this.pose,
|
|
2986
|
+
altitude
|
|
2987
|
+
};
|
|
2945
2988
|
}
|
|
2946
2989
|
/** 获取内部实体(用于拾取识别) */
|
|
2947
2990
|
getEntity() {
|
|
@@ -3001,8 +3044,58 @@ var AirplaneCursor = class {
|
|
|
3001
3044
|
} catch {
|
|
3002
3045
|
}
|
|
3003
3046
|
this.updateFrustum();
|
|
3047
|
+
this.broadcastPoseChange();
|
|
3004
3048
|
this.viewer.scene?.requestRender?.();
|
|
3005
3049
|
}
|
|
3050
|
+
/**
|
|
3051
|
+
* 广播游标姿态变化事件到全局事件总线
|
|
3052
|
+
*/
|
|
3053
|
+
broadcastPoseChange() {
|
|
3054
|
+
try {
|
|
3055
|
+
const C = this.CesiumNS;
|
|
3056
|
+
const cartographic = C.Cartographic.fromCartesian(this.pose.position);
|
|
3057
|
+
const altitude = cartographic ? cartographic.height : 0;
|
|
3058
|
+
console.log("[AirplaneCursor] \u{1F4E1} \u5E7F\u64AD\u59FF\u6001\u53D8\u5316:", {
|
|
3059
|
+
heading: this.pose.heading,
|
|
3060
|
+
pitch: this.pose.pitch,
|
|
3061
|
+
altitude
|
|
3062
|
+
});
|
|
3063
|
+
globalCameraEventBus.onCursorPoseChange.emit({
|
|
3064
|
+
position: this.pose.position,
|
|
3065
|
+
heading: this.pose.heading,
|
|
3066
|
+
pitch: this.pose.pitch,
|
|
3067
|
+
roll: this.pose.roll,
|
|
3068
|
+
altitude,
|
|
3069
|
+
source: "cursor"
|
|
3070
|
+
});
|
|
3071
|
+
} catch (e) {
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
/**
|
|
3075
|
+
* 模拟按键按下(用于虚拟控制器)
|
|
3076
|
+
* @param key 按键名称 (w/a/s/d/q/e/c/z)
|
|
3077
|
+
* @param duration 按键持续时间(毫秒),默认 100ms
|
|
3078
|
+
*/
|
|
3079
|
+
simulateKeyPress(key, duration = 100) {
|
|
3080
|
+
const lowerKey = key.toLowerCase();
|
|
3081
|
+
const keyMap = {
|
|
3082
|
+
"c": "c",
|
|
3083
|
+
// 上升
|
|
3084
|
+
"z": "z"
|
|
3085
|
+
// 下降
|
|
3086
|
+
};
|
|
3087
|
+
const mappedKey = keyMap[lowerKey] || lowerKey;
|
|
3088
|
+
console.log("[AirplaneCursor] \u{1F3AE} simulateKeyPress:", mappedKey, "duration:", duration);
|
|
3089
|
+
console.log("[AirplaneCursor] \u{1F3AE} updateLoopRunning:", this.updateLoopRunning);
|
|
3090
|
+
this.keysPressed.add(mappedKey);
|
|
3091
|
+
if (!this.updateLoopRunning) {
|
|
3092
|
+
console.log("[AirplaneCursor] \u{1F3AE} \u542F\u52A8 updateLoop");
|
|
3093
|
+
this.startUpdateLoop();
|
|
3094
|
+
}
|
|
3095
|
+
setTimeout(() => {
|
|
3096
|
+
this.keysPressed.delete(mappedKey);
|
|
3097
|
+
}, duration);
|
|
3098
|
+
}
|
|
3006
3099
|
destroy() {
|
|
3007
3100
|
if (this.destroyed) return;
|
|
3008
3101
|
this.destroyed = true;
|
|
@@ -5065,6 +5158,31 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5065
5158
|
vertexLabelManager.updateLabelPosition(index, newPosition);
|
|
5066
5159
|
} catch {
|
|
5067
5160
|
}
|
|
5161
|
+
if (options?.onVertexDragMoveDetail) {
|
|
5162
|
+
try {
|
|
5163
|
+
let coordinates = { longitude: 0, latitude: 0, height: 0 };
|
|
5164
|
+
try {
|
|
5165
|
+
const cartographic = C.Cartographic.fromCartesian(newPosition);
|
|
5166
|
+
coordinates = {
|
|
5167
|
+
longitude: C.Math.toDegrees(cartographic.longitude),
|
|
5168
|
+
latitude: C.Math.toDegrees(cartographic.latitude),
|
|
5169
|
+
height: cartographic.height
|
|
5170
|
+
};
|
|
5171
|
+
} catch {
|
|
5172
|
+
}
|
|
5173
|
+
const displayNumber = hiddenClimbIndex === 1 && index > 1 ? index - 1 : index;
|
|
5174
|
+
const dragMoveInfo = {
|
|
5175
|
+
index,
|
|
5176
|
+
displayNumber,
|
|
5177
|
+
position: newPosition,
|
|
5178
|
+
coordinates,
|
|
5179
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
5180
|
+
};
|
|
5181
|
+
options.onVertexDragMoveDetail(dragMoveInfo);
|
|
5182
|
+
} catch (error) {
|
|
5183
|
+
console.error("Error in onVertexDragMoveDetail:", error);
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5068
5186
|
},
|
|
5069
5187
|
onVertexDragEnd: (index, finalPosition) => {
|
|
5070
5188
|
editedIndices.add(index);
|
|
@@ -5105,6 +5223,12 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5105
5223
|
getAirplaneCursor: () => airplaneCursor,
|
|
5106
5224
|
getPoseData: () => ({ headings, pitches, rolls, fovs }),
|
|
5107
5225
|
getEntity: () => entity,
|
|
5226
|
+
/** 模拟按键控制飞机游标(用于虚拟控制器) */
|
|
5227
|
+
simulateKeyPress: (key, duration) => {
|
|
5228
|
+
airplaneCursor?.simulateKeyPress(key, duration);
|
|
5229
|
+
},
|
|
5230
|
+
/** 获取游标当前姿态(包含高度) */
|
|
5231
|
+
getCursorPose: () => airplaneCursor?.getPose(),
|
|
5108
5232
|
// 🆕 快速编辑回调
|
|
5109
5233
|
getQuickEditEnabled: () => quickEditEnabled,
|
|
5110
5234
|
getQuickEditOptions: () => ({
|
|
@@ -5287,9 +5411,166 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5287
5411
|
/** 🆕 检查快速编辑模式是否启用 */
|
|
5288
5412
|
isQuickEditEnabled: () => {
|
|
5289
5413
|
return quickEditEnabled;
|
|
5290
|
-
}
|
|
5414
|
+
},
|
|
5415
|
+
// ========================
|
|
5416
|
+
// 🆕 程序化更新方法
|
|
5417
|
+
// ========================
|
|
5418
|
+
/**
|
|
5419
|
+
* 🆕 程序化更新指定航点
|
|
5420
|
+
* @param index 航点索引
|
|
5421
|
+
* @param updates 需要更新的字段
|
|
5422
|
+
* @returns 是否更新成功
|
|
5423
|
+
*/
|
|
5424
|
+
updateWaypoint: (index, updates) => {
|
|
5425
|
+
if (index < 0 || index >= positions.length) {
|
|
5426
|
+
console.warn(`[updateWaypoint] Invalid index: ${index}, valid range: 0-${positions.length - 1}`);
|
|
5427
|
+
return false;
|
|
5428
|
+
}
|
|
5429
|
+
try {
|
|
5430
|
+
let positionUpdated = false;
|
|
5431
|
+
if (updates.position) {
|
|
5432
|
+
positions[index] = updates.position;
|
|
5433
|
+
positionUpdated = true;
|
|
5434
|
+
}
|
|
5435
|
+
if (updates.altitude !== void 0 && !updates.position) {
|
|
5436
|
+
const currentPos = positions[index];
|
|
5437
|
+
const cartographic = C.Cartographic.fromCartesian(currentPos);
|
|
5438
|
+
const newPos = C.Cartesian3.fromRadians(
|
|
5439
|
+
cartographic.longitude,
|
|
5440
|
+
cartographic.latitude,
|
|
5441
|
+
updates.altitude
|
|
5442
|
+
);
|
|
5443
|
+
positions[index] = newPos;
|
|
5444
|
+
positionUpdated = true;
|
|
5445
|
+
}
|
|
5446
|
+
if (positionUpdated) {
|
|
5447
|
+
const newPos = positions[index];
|
|
5448
|
+
if (handles[index]) {
|
|
5449
|
+
try {
|
|
5450
|
+
handles[index].position = newPos;
|
|
5451
|
+
} catch {
|
|
5452
|
+
}
|
|
5453
|
+
}
|
|
5454
|
+
try {
|
|
5455
|
+
vertexLabelManager.updateLabelPosition(index, newPos);
|
|
5456
|
+
} catch {
|
|
5457
|
+
}
|
|
5458
|
+
try {
|
|
5459
|
+
createOrUpdateMarkerForIndex(index);
|
|
5460
|
+
} catch {
|
|
5461
|
+
}
|
|
5462
|
+
}
|
|
5463
|
+
if (updates.heading !== void 0) headings[index] = updates.heading;
|
|
5464
|
+
if (updates.pitch !== void 0) pitches[index] = updates.pitch;
|
|
5465
|
+
if (updates.roll !== void 0) rolls[index] = updates.roll;
|
|
5466
|
+
if (updates.fov !== void 0) {
|
|
5467
|
+
fovs[index] = updates.fov;
|
|
5468
|
+
if (index === activeIndex) {
|
|
5469
|
+
globalCameraEventBus.onFOVChange.emit({
|
|
5470
|
+
fov: updates.fov,
|
|
5471
|
+
focalLength: fovToFocalLength(updates.fov),
|
|
5472
|
+
source: "user"
|
|
5473
|
+
});
|
|
5474
|
+
}
|
|
5475
|
+
}
|
|
5476
|
+
if (index === activeIndex && airplaneCursor) {
|
|
5477
|
+
try {
|
|
5478
|
+
airplaneCursor.setPose(
|
|
5479
|
+
positions[index],
|
|
5480
|
+
headings[index] ?? 0,
|
|
5481
|
+
pitches[index] ?? -10,
|
|
5482
|
+
rolls[index] ?? 0
|
|
5483
|
+
);
|
|
5484
|
+
} catch {
|
|
5485
|
+
}
|
|
5486
|
+
}
|
|
5487
|
+
stateManager.persistToEntity(positions, headings, pitches, rolls, fovs);
|
|
5488
|
+
return true;
|
|
5489
|
+
} catch (error) {
|
|
5490
|
+
console.error("[updateWaypoint] Error:", error);
|
|
5491
|
+
return false;
|
|
5492
|
+
}
|
|
5493
|
+
},
|
|
5494
|
+
/**
|
|
5495
|
+
* 🆕 更新航点位置
|
|
5496
|
+
*/
|
|
5497
|
+
updateWaypointPosition: function(index, position) {
|
|
5498
|
+
return this.updateWaypoint(index, { position });
|
|
5499
|
+
},
|
|
5500
|
+
/**
|
|
5501
|
+
* 🆕 更新航点高度(仅垂直方向,保持经纬度不变)
|
|
5502
|
+
*/
|
|
5503
|
+
updateWaypointAltitude: function(index, altitude) {
|
|
5504
|
+
return this.updateWaypoint(index, { altitude });
|
|
5505
|
+
},
|
|
5506
|
+
/**
|
|
5507
|
+
* 🆕 更新航点偏航角
|
|
5508
|
+
*/
|
|
5509
|
+
updateWaypointHeading: function(index, heading) {
|
|
5510
|
+
return this.updateWaypoint(index, { heading });
|
|
5511
|
+
},
|
|
5512
|
+
/**
|
|
5513
|
+
* 🆕 更新航点俯仰角
|
|
5514
|
+
*/
|
|
5515
|
+
updateWaypointPitch: function(index, pitch) {
|
|
5516
|
+
return this.updateWaypoint(index, { pitch });
|
|
5517
|
+
},
|
|
5518
|
+
/**
|
|
5519
|
+
* 🆕 更新航点视野角
|
|
5520
|
+
*/
|
|
5521
|
+
updateWaypointFov: function(index, fov) {
|
|
5522
|
+
return this.updateWaypoint(index, { fov });
|
|
5523
|
+
},
|
|
5524
|
+
/**
|
|
5525
|
+
* 🆕 批量更新多个航点
|
|
5526
|
+
*/
|
|
5527
|
+
batchUpdateWaypoints: function(updates) {
|
|
5528
|
+
let allSuccess = true;
|
|
5529
|
+
for (const { index, data } of updates) {
|
|
5530
|
+
if (!this.updateWaypoint(index, data)) {
|
|
5531
|
+
allSuccess = false;
|
|
5532
|
+
}
|
|
5533
|
+
}
|
|
5534
|
+
return allSuccess;
|
|
5535
|
+
},
|
|
5536
|
+
/**
|
|
5537
|
+
* 🆕 程序化选中指定航点
|
|
5538
|
+
* 将飞机游标移动到指定航点位置,更新选中状态
|
|
5539
|
+
* @param index 航点索引
|
|
5540
|
+
* @returns 是否选中成功
|
|
5541
|
+
*/
|
|
5542
|
+
selectVertex: (index) => {
|
|
5543
|
+
if (index < 0 || index >= positions.length) {
|
|
5544
|
+
console.warn(`[selectVertex] Invalid index: ${index}, valid range: 0-${positions.length - 1}`);
|
|
5545
|
+
return false;
|
|
5546
|
+
}
|
|
5547
|
+
try {
|
|
5548
|
+
setActiveIndex(index);
|
|
5549
|
+
return true;
|
|
5550
|
+
} catch (e) {
|
|
5551
|
+
console.error("[selectVertex] Failed to select vertex:", e);
|
|
5552
|
+
return false;
|
|
5553
|
+
}
|
|
5554
|
+
},
|
|
5555
|
+
/**
|
|
5556
|
+
* 🆕 模拟按键控制飞机游标(用于虚拟控制器)
|
|
5557
|
+
* @param key 按键名称 (w/a/s/d/q/e/c/z)
|
|
5558
|
+
* @param duration 按键持续时间(毫秒)
|
|
5559
|
+
*/
|
|
5560
|
+
simulateKeyPress: (key, duration) => {
|
|
5561
|
+
airplaneCursor?.simulateKeyPress(key, duration);
|
|
5562
|
+
},
|
|
5563
|
+
/**
|
|
5564
|
+
* 🆕 获取游标当前姿态(包含高度)
|
|
5565
|
+
*/
|
|
5566
|
+
getCursorPose: () => airplaneCursor?.getPose()
|
|
5291
5567
|
};
|
|
5292
5568
|
}
|
|
5569
|
+
function fovToFocalLength(fovDeg) {
|
|
5570
|
+
const sensorWidth = 36;
|
|
5571
|
+
const fovRad = fovDeg * Math.PI / 180;
|
|
5572
|
+
return sensorWidth / (2 * Math.tan(fovRad / 2));
|
|
5573
|
+
}
|
|
5293
5574
|
|
|
5294
5575
|
// src/core/path-manager/ArrowShape.ts
|
|
5295
5576
|
var ArrowShape = class {
|
|
@@ -5686,7 +5967,6 @@ function parsePoseFromAction(action) {
|
|
|
5686
5967
|
fov: parseFloat(numbers[3])
|
|
5687
5968
|
};
|
|
5688
5969
|
}
|
|
5689
|
-
console.warn("[sinoflyAdapter] \u65E0\u6CD5\u89E3\u6790 action \u5B57\u6BB5:", action, error);
|
|
5690
5970
|
return {};
|
|
5691
5971
|
}
|
|
5692
5972
|
}
|
|
@@ -5704,15 +5984,40 @@ function parseTakeOffRefPoint(takeOffRefPoint, takeOffSecurityHeight, CesiumNS)
|
|
|
5704
5984
|
if (!takeOffRefPoint || typeof takeOffRefPoint !== "string" || takeOffRefPoint.trim() === "") {
|
|
5705
5985
|
return null;
|
|
5706
5986
|
}
|
|
5987
|
+
const C = CesiumNS;
|
|
5988
|
+
let longitude;
|
|
5989
|
+
let latitude;
|
|
5990
|
+
let height;
|
|
5991
|
+
const trimmed = takeOffRefPoint.trim();
|
|
5992
|
+
if (trimmed.includes(",")) {
|
|
5993
|
+
try {
|
|
5994
|
+
const parts = trimmed.split(",").map((p) => p.trim());
|
|
5995
|
+
if (parts.length >= 2) {
|
|
5996
|
+
latitude = parseFloat(parts[0]);
|
|
5997
|
+
longitude = parseFloat(parts[1]);
|
|
5998
|
+
height = parts.length >= 3 ? parseFloat(parts[2]) : takeOffSecurityHeight;
|
|
5999
|
+
if (isNaN(latitude) || isNaN(longitude) || isNaN(height)) {
|
|
6000
|
+
throw new Error("\u65E0\u6CD5\u89E3\u6790\u9017\u53F7\u5206\u9694\u7684\u5750\u6807\u503C");
|
|
6001
|
+
}
|
|
6002
|
+
const startPosition = C.Cartesian3.fromDegrees(longitude, latitude, height);
|
|
6003
|
+
const climbPosition = C.Cartesian3.fromDegrees(
|
|
6004
|
+
longitude,
|
|
6005
|
+
latitude,
|
|
6006
|
+
height + takeOffSecurityHeight
|
|
6007
|
+
);
|
|
6008
|
+
return {
|
|
6009
|
+
startPosition,
|
|
6010
|
+
climbPosition
|
|
6011
|
+
};
|
|
6012
|
+
}
|
|
6013
|
+
} catch (error) {
|
|
6014
|
+
}
|
|
6015
|
+
}
|
|
5707
6016
|
try {
|
|
5708
6017
|
const parsed = JSON.parse(takeOffRefPoint);
|
|
5709
6018
|
if (typeof parsed !== "object" || parsed === null) {
|
|
5710
6019
|
return null;
|
|
5711
6020
|
}
|
|
5712
|
-
const C = CesiumNS;
|
|
5713
|
-
let longitude;
|
|
5714
|
-
let latitude;
|
|
5715
|
-
let height;
|
|
5716
6021
|
if (typeof parsed.longitude === "number") {
|
|
5717
6022
|
longitude = parsed.longitude;
|
|
5718
6023
|
} else if (typeof parsed.lon === "number") {
|
|
@@ -5743,7 +6048,6 @@ function parseTakeOffRefPoint(takeOffRefPoint, takeOffSecurityHeight, CesiumNS)
|
|
|
5743
6048
|
climbPosition
|
|
5744
6049
|
};
|
|
5745
6050
|
} catch (error) {
|
|
5746
|
-
console.warn("[sinoflyAdapter] \u65E0\u6CD5\u89E3\u6790 takeOffRefPoint:", takeOffRefPoint, error);
|
|
5747
6051
|
return null;
|
|
5748
6052
|
}
|
|
5749
6053
|
}
|
|
@@ -5765,16 +6069,10 @@ function convertSinoflyWayline(data, options) {
|
|
|
5765
6069
|
if (!data.waypointInfo || !Array.isArray(data.waypointInfo)) {
|
|
5766
6070
|
throw new Error("[sinoflyAdapter] waypointInfo \u5FC5\u987B\u662F\u6570\u7EC4");
|
|
5767
6071
|
}
|
|
5768
|
-
if (data.waypointInfo.length === 0)
|
|
5769
|
-
console.warn("[sinoflyAdapter] waypointInfo \u6570\u7EC4\u4E3A\u7A7A\uFF0C\u5C06\u8FD4\u56DE\u7A7A\u7684\u822A\u70B9\u6570\u636E");
|
|
5770
|
-
}
|
|
6072
|
+
if (data.waypointInfo.length === 0) ;
|
|
5771
6073
|
if (data.waylineId === void 0 || data.waylineId === null) {
|
|
5772
6074
|
throw new Error("[sinoflyAdapter] waylineId \u4E0D\u80FD\u4E3A\u7A7A");
|
|
5773
6075
|
}
|
|
5774
|
-
console.log(`[sinoflyAdapter] \u5F00\u59CB\u8F6C\u6362\u822A\u7EBF ${data.waylineId}\uFF0C\u5305\u542B ${data.waypointInfo.length} \u4E2A\u822A\u70B9`);
|
|
5775
|
-
if (data.takeOffRefPoint) {
|
|
5776
|
-
console.log(`[sinoflyAdapter] \u68C0\u6D4B\u5230 takeOffRefPoint: ${data.takeOffRefPoint}`);
|
|
5777
|
-
}
|
|
5778
6076
|
const takeOffInfo = parseTakeOffRefPoint(
|
|
5779
6077
|
data.takeOffRefPoint,
|
|
5780
6078
|
data.takeOffSecurityHeight,
|
|
@@ -5839,7 +6137,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
5839
6137
|
if (poseFromAction.roll !== void 0) roll = poseFromAction.roll;
|
|
5840
6138
|
if (poseFromAction.fov !== void 0) fov = poseFromAction.fov;
|
|
5841
6139
|
} catch (actionError) {
|
|
5842
|
-
console.warn(`[sinoflyAdapter] \u822A\u70B9 ${idx} action \u89E3\u6790\u5931\u8D25:`, actionError);
|
|
5843
6140
|
}
|
|
5844
6141
|
}
|
|
5845
6142
|
return {
|
|
@@ -5852,7 +6149,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
5852
6149
|
// 重新分配 index,从 waypointStartIndex 开始
|
|
5853
6150
|
};
|
|
5854
6151
|
} catch (error) {
|
|
5855
|
-
console.error(`[sinoflyAdapter] \u822A\u70B9 ${idx} \u8F6C\u6362\u5931\u8D25:`, error);
|
|
5856
6152
|
throw new Error(`\u822A\u70B9 ${idx} \u8F6C\u6362\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
5857
6153
|
}
|
|
5858
6154
|
});
|
|
@@ -5860,7 +6156,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
5860
6156
|
if (!Array.isArray(waypointData)) {
|
|
5861
6157
|
throw new Error("[sinoflyAdapter] waypointData \u4E0D\u662F\u6570\u7EC4");
|
|
5862
6158
|
}
|
|
5863
|
-
console.log(`[sinoflyAdapter] \u8F6C\u6362\u5B8C\u6210\uFF0C\u5171\u751F\u6210 ${waypointData.length} \u4E2A\u822A\u70B9`);
|
|
5864
6159
|
const metadata = {
|
|
5865
6160
|
waylineId: data.waylineId,
|
|
5866
6161
|
waylineType: data.waylineType,
|