@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/index.js
CHANGED
|
@@ -11,7 +11,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
11
11
|
// package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "@jorgmoritz/gis-manager",
|
|
14
|
-
version: "0.1.
|
|
14
|
+
version: "0.1.25"};
|
|
15
15
|
|
|
16
16
|
// src/utils/version.ts
|
|
17
17
|
var version = package_default.version;
|
|
@@ -104,6 +104,8 @@ var CameraEventBus = class {
|
|
|
104
104
|
__publicField(this, "onPoseChange", new Emitter());
|
|
105
105
|
/** 视锥体形状变化事件 */
|
|
106
106
|
__publicField(this, "onFrustumShapeChange", new Emitter());
|
|
107
|
+
/** 飞机游标姿态变化事件 */
|
|
108
|
+
__publicField(this, "onCursorPoseChange", new Emitter());
|
|
107
109
|
}
|
|
108
110
|
/**
|
|
109
111
|
* 清理所有监听器
|
|
@@ -112,9 +114,20 @@ var CameraEventBus = class {
|
|
|
112
114
|
this.onFOVChange.clear();
|
|
113
115
|
this.onPoseChange.clear();
|
|
114
116
|
this.onFrustumShapeChange.clear();
|
|
117
|
+
this.onCursorPoseChange.clear();
|
|
115
118
|
}
|
|
116
119
|
};
|
|
117
|
-
var
|
|
120
|
+
var GLOBAL_KEY = "__gisManager_globalCameraEventBus__";
|
|
121
|
+
function getGlobalEventBus() {
|
|
122
|
+
if (typeof window !== "undefined") {
|
|
123
|
+
if (!window[GLOBAL_KEY]) {
|
|
124
|
+
window[GLOBAL_KEY] = new CameraEventBus();
|
|
125
|
+
}
|
|
126
|
+
return window[GLOBAL_KEY];
|
|
127
|
+
}
|
|
128
|
+
return new CameraEventBus();
|
|
129
|
+
}
|
|
130
|
+
var globalCameraEventBus = getGlobalEventBus();
|
|
118
131
|
|
|
119
132
|
// src/core/LayerManager.ts
|
|
120
133
|
var layerIdSeq = 0;
|
|
@@ -1122,7 +1135,9 @@ var SceneManager = class {
|
|
|
1122
1135
|
depth: true,
|
|
1123
1136
|
stencil: true,
|
|
1124
1137
|
antialias: true,
|
|
1125
|
-
powerPreference: "high-performance"
|
|
1138
|
+
powerPreference: "high-performance",
|
|
1139
|
+
preserveDrawingBuffer: true
|
|
1140
|
+
// 必需:允许 canvas.toDataURL() 截图
|
|
1126
1141
|
}
|
|
1127
1142
|
},
|
|
1128
1143
|
...viewerOptions
|
|
@@ -1560,8 +1575,8 @@ var CameraFOVController = class {
|
|
|
1560
1575
|
if (!this.sliderEl) return;
|
|
1561
1576
|
const sliderValue = parseFloat(this.sliderEl.value);
|
|
1562
1577
|
const sliderIndex = this.focalLengthPresets.length - 1 - sliderValue;
|
|
1563
|
-
const
|
|
1564
|
-
const fov = this.
|
|
1578
|
+
const focalLength = this.interpolateFocalLength(sliderIndex);
|
|
1579
|
+
const fov = this.focalLengthToFOV(focalLength);
|
|
1565
1580
|
this.currentFOV = fov;
|
|
1566
1581
|
this.updateDisplay();
|
|
1567
1582
|
this.emitChange();
|
|
@@ -1569,24 +1584,35 @@ var CameraFOVController = class {
|
|
|
1569
1584
|
this.sensorWidth = opts.sensorWidth ?? 36;
|
|
1570
1585
|
this.focalLengthPresets = opts.focalLengthPresets ?? [112, 56, 14, 7, 3, 1];
|
|
1571
1586
|
if (opts.minFOV === void 0 || opts.maxFOV === void 0) {
|
|
1572
|
-
const
|
|
1573
|
-
const
|
|
1574
|
-
this.maxFOV = this.
|
|
1575
|
-
this.minFOV = this.
|
|
1587
|
+
const minFocalLength = Math.min(...this.focalLengthPresets);
|
|
1588
|
+
const maxFocalLength = Math.max(...this.focalLengthPresets);
|
|
1589
|
+
this.maxFOV = this.focalLengthToFOVDirect(minFocalLength);
|
|
1590
|
+
this.minFOV = this.focalLengthToFOVDirect(maxFocalLength);
|
|
1576
1591
|
} else {
|
|
1577
1592
|
this.minFOV = opts.minFOV;
|
|
1578
1593
|
this.maxFOV = opts.maxFOV;
|
|
1579
1594
|
}
|
|
1580
|
-
this.currentFOV = opts.initialFOV ?? this.
|
|
1595
|
+
this.currentFOV = opts.initialFOV ?? this.focalLengthToFOVDirect(56);
|
|
1581
1596
|
this.useGlobalEventBus = opts.useGlobalEventBus ?? true;
|
|
1582
1597
|
this.createUI();
|
|
1598
|
+
this.setupExternalFOVListener();
|
|
1583
1599
|
}
|
|
1584
1600
|
/**
|
|
1585
|
-
*
|
|
1601
|
+
* 🆕 监听外部 FOV 变化事件(来自 UI 面板等),同步更新滑块位置
|
|
1586
1602
|
*/
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1603
|
+
setupExternalFOVListener() {
|
|
1604
|
+
if (!this.useGlobalEventBus) return;
|
|
1605
|
+
globalCameraEventBus.onFOVChange.on((event) => {
|
|
1606
|
+
if (event.source !== "controller") {
|
|
1607
|
+
this.setFOVSilent(event.fov);
|
|
1608
|
+
}
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* 焦距转换为 FOV(度)- 直接计算版本
|
|
1613
|
+
*/
|
|
1614
|
+
focalLengthToFOVDirect(focalLengthMm) {
|
|
1615
|
+
const fovRad = 2 * Math.atan(this.sensorWidth / (2 * focalLengthMm));
|
|
1590
1616
|
return fovRad * 180 / Math.PI;
|
|
1591
1617
|
}
|
|
1592
1618
|
/**
|
|
@@ -1710,7 +1736,7 @@ var CameraFOVController = class {
|
|
|
1710
1736
|
`;
|
|
1711
1737
|
this.focalLengthPresets.forEach((fl) => {
|
|
1712
1738
|
const marker = document.createElement("div");
|
|
1713
|
-
marker.textContent = `${fl}
|
|
1739
|
+
marker.textContent = `${fl}`;
|
|
1714
1740
|
marker.style.cssText = `
|
|
1715
1741
|
cursor: pointer;
|
|
1716
1742
|
padding: 2px 4px;
|
|
@@ -1725,7 +1751,7 @@ var CameraFOVController = class {
|
|
|
1725
1751
|
marker.style.background = "transparent";
|
|
1726
1752
|
});
|
|
1727
1753
|
marker.addEventListener("click", () => {
|
|
1728
|
-
this.
|
|
1754
|
+
this.setFocalLength(fl);
|
|
1729
1755
|
});
|
|
1730
1756
|
markersContainer.appendChild(marker);
|
|
1731
1757
|
});
|
|
@@ -1738,38 +1764,38 @@ var CameraFOVController = class {
|
|
|
1738
1764
|
this.emitChange();
|
|
1739
1765
|
}
|
|
1740
1766
|
/**
|
|
1741
|
-
*
|
|
1767
|
+
* 根据索引插值计算焦距值
|
|
1742
1768
|
*/
|
|
1743
|
-
|
|
1769
|
+
interpolateFocalLength(index) {
|
|
1744
1770
|
const clampedIndex = Math.max(0, Math.min(this.focalLengthPresets.length - 1, index));
|
|
1745
1771
|
if (Number.isInteger(clampedIndex)) {
|
|
1746
1772
|
return this.focalLengthPresets[clampedIndex];
|
|
1747
1773
|
}
|
|
1748
1774
|
const lowerIndex = Math.floor(clampedIndex);
|
|
1749
1775
|
const upperIndex = Math.ceil(clampedIndex);
|
|
1750
|
-
const
|
|
1751
|
-
const
|
|
1776
|
+
const lowerFL = this.focalLengthPresets[lowerIndex];
|
|
1777
|
+
const upperFL = this.focalLengthPresets[upperIndex];
|
|
1752
1778
|
const fraction = clampedIndex - lowerIndex;
|
|
1753
|
-
return
|
|
1779
|
+
return lowerFL + (upperFL - lowerFL) * fraction;
|
|
1754
1780
|
}
|
|
1755
1781
|
/**
|
|
1756
|
-
*
|
|
1782
|
+
* 根据焦距值计算对应的索引(可以是小数)
|
|
1757
1783
|
*/
|
|
1758
|
-
|
|
1759
|
-
const
|
|
1760
|
-
const
|
|
1761
|
-
const
|
|
1784
|
+
getFocalLengthIndex(focalLength) {
|
|
1785
|
+
const minFL = Math.min(...this.focalLengthPresets);
|
|
1786
|
+
const maxFL = Math.max(...this.focalLengthPresets);
|
|
1787
|
+
const clampedFL = Math.max(minFL, Math.min(maxFL, focalLength));
|
|
1762
1788
|
for (let i = 0; i < this.focalLengthPresets.length - 1; i++) {
|
|
1763
1789
|
const current = this.focalLengthPresets[i];
|
|
1764
1790
|
const next = this.focalLengthPresets[i + 1];
|
|
1765
|
-
if (current <=
|
|
1766
|
-
const fraction = (
|
|
1791
|
+
if (current <= clampedFL && clampedFL <= next || current >= clampedFL && clampedFL >= next) {
|
|
1792
|
+
const fraction = (clampedFL - current) / (next - current);
|
|
1767
1793
|
return i + fraction;
|
|
1768
1794
|
}
|
|
1769
1795
|
}
|
|
1770
1796
|
return this.focalLengthPresets.indexOf(
|
|
1771
1797
|
this.focalLengthPresets.reduce(
|
|
1772
|
-
(prev, curr) => Math.abs(curr -
|
|
1798
|
+
(prev, curr) => Math.abs(curr - clampedFL) < Math.abs(prev - clampedFL) ? curr : prev
|
|
1773
1799
|
)
|
|
1774
1800
|
);
|
|
1775
1801
|
}
|
|
@@ -1778,8 +1804,7 @@ var CameraFOVController = class {
|
|
|
1778
1804
|
*/
|
|
1779
1805
|
getClosestPresetIndex(fov) {
|
|
1780
1806
|
const focalLength = this.fovToFocalLength(fov);
|
|
1781
|
-
const
|
|
1782
|
-
const index = this.getZoomMultiplierIndex(zoomMultiplier);
|
|
1807
|
+
const index = this.getFocalLengthIndex(focalLength);
|
|
1783
1808
|
return this.focalLengthPresets.length - 1 - index;
|
|
1784
1809
|
}
|
|
1785
1810
|
/**
|
|
@@ -1787,9 +1812,8 @@ var CameraFOVController = class {
|
|
|
1787
1812
|
*/
|
|
1788
1813
|
updateDisplay() {
|
|
1789
1814
|
const focalLength = this.fovToFocalLength(this.currentFOV);
|
|
1790
|
-
const zoomMultiplier = focalLength / this.sensorWidth;
|
|
1791
1815
|
if (this.labelEl) {
|
|
1792
|
-
this.labelEl.textContent = `\
|
|
1816
|
+
this.labelEl.textContent = `\u7126\u8DDD ${Math.round(focalLength)}`;
|
|
1793
1817
|
}
|
|
1794
1818
|
}
|
|
1795
1819
|
/**
|
|
@@ -1860,6 +1884,18 @@ var CameraFOVController = class {
|
|
|
1860
1884
|
this.updateDisplay();
|
|
1861
1885
|
this.emitChange();
|
|
1862
1886
|
}
|
|
1887
|
+
/**
|
|
1888
|
+
* 🆕 静默设置 FOV(度)- 只更新滑块位置,不广播事件
|
|
1889
|
+
* 用于响应外部 FOV 变化事件,避免循环广播
|
|
1890
|
+
*/
|
|
1891
|
+
setFOVSilent(fovDeg) {
|
|
1892
|
+
this.currentFOV = Math.max(this.minFOV, Math.min(this.maxFOV, fovDeg));
|
|
1893
|
+
if (this.sliderEl) {
|
|
1894
|
+
const index = this.getClosestPresetIndex(this.currentFOV);
|
|
1895
|
+
this.sliderEl.value = String(index);
|
|
1896
|
+
}
|
|
1897
|
+
this.updateDisplay();
|
|
1898
|
+
}
|
|
1863
1899
|
/**
|
|
1864
1900
|
* 获取当前 FOV
|
|
1865
1901
|
*/
|
|
@@ -2926,6 +2962,7 @@ var AirplaneCursor = class {
|
|
|
2926
2962
|
this.opts?.onPose?.({ ...pose });
|
|
2927
2963
|
this.viewer.scene?.requestRender?.();
|
|
2928
2964
|
this.updateFrustum();
|
|
2965
|
+
this.broadcastPoseChange();
|
|
2929
2966
|
}
|
|
2930
2967
|
requestAnimationFrame(update);
|
|
2931
2968
|
};
|
|
@@ -2983,9 +3020,15 @@ var AirplaneCursor = class {
|
|
|
2983
3020
|
} catch {
|
|
2984
3021
|
}
|
|
2985
3022
|
}
|
|
2986
|
-
/**
|
|
3023
|
+
/** 获取当前姿态(包含高度信息) */
|
|
2987
3024
|
getPose() {
|
|
2988
|
-
|
|
3025
|
+
const C = this.CesiumNS;
|
|
3026
|
+
const cartographic = C.Cartographic.fromCartesian(this.pose.position);
|
|
3027
|
+
const altitude = cartographic ? cartographic.height : 0;
|
|
3028
|
+
return {
|
|
3029
|
+
...this.pose,
|
|
3030
|
+
altitude
|
|
3031
|
+
};
|
|
2989
3032
|
}
|
|
2990
3033
|
/** 获取内部实体(用于拾取识别) */
|
|
2991
3034
|
getEntity() {
|
|
@@ -3045,8 +3088,58 @@ var AirplaneCursor = class {
|
|
|
3045
3088
|
} catch {
|
|
3046
3089
|
}
|
|
3047
3090
|
this.updateFrustum();
|
|
3091
|
+
this.broadcastPoseChange();
|
|
3048
3092
|
this.viewer.scene?.requestRender?.();
|
|
3049
3093
|
}
|
|
3094
|
+
/**
|
|
3095
|
+
* 广播游标姿态变化事件到全局事件总线
|
|
3096
|
+
*/
|
|
3097
|
+
broadcastPoseChange() {
|
|
3098
|
+
try {
|
|
3099
|
+
const C = this.CesiumNS;
|
|
3100
|
+
const cartographic = C.Cartographic.fromCartesian(this.pose.position);
|
|
3101
|
+
const altitude = cartographic ? cartographic.height : 0;
|
|
3102
|
+
console.log("[AirplaneCursor] \u{1F4E1} \u5E7F\u64AD\u59FF\u6001\u53D8\u5316:", {
|
|
3103
|
+
heading: this.pose.heading,
|
|
3104
|
+
pitch: this.pose.pitch,
|
|
3105
|
+
altitude
|
|
3106
|
+
});
|
|
3107
|
+
globalCameraEventBus.onCursorPoseChange.emit({
|
|
3108
|
+
position: this.pose.position,
|
|
3109
|
+
heading: this.pose.heading,
|
|
3110
|
+
pitch: this.pose.pitch,
|
|
3111
|
+
roll: this.pose.roll,
|
|
3112
|
+
altitude,
|
|
3113
|
+
source: "cursor"
|
|
3114
|
+
});
|
|
3115
|
+
} catch (e) {
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
/**
|
|
3119
|
+
* 模拟按键按下(用于虚拟控制器)
|
|
3120
|
+
* @param key 按键名称 (w/a/s/d/q/e/c/z)
|
|
3121
|
+
* @param duration 按键持续时间(毫秒),默认 100ms
|
|
3122
|
+
*/
|
|
3123
|
+
simulateKeyPress(key, duration = 100) {
|
|
3124
|
+
const lowerKey = key.toLowerCase();
|
|
3125
|
+
const keyMap = {
|
|
3126
|
+
"c": "c",
|
|
3127
|
+
// 上升
|
|
3128
|
+
"z": "z"
|
|
3129
|
+
// 下降
|
|
3130
|
+
};
|
|
3131
|
+
const mappedKey = keyMap[lowerKey] || lowerKey;
|
|
3132
|
+
console.log("[AirplaneCursor] \u{1F3AE} simulateKeyPress:", mappedKey, "duration:", duration);
|
|
3133
|
+
console.log("[AirplaneCursor] \u{1F3AE} updateLoopRunning:", this.updateLoopRunning);
|
|
3134
|
+
this.keysPressed.add(mappedKey);
|
|
3135
|
+
if (!this.updateLoopRunning) {
|
|
3136
|
+
console.log("[AirplaneCursor] \u{1F3AE} \u542F\u52A8 updateLoop");
|
|
3137
|
+
this.startUpdateLoop();
|
|
3138
|
+
}
|
|
3139
|
+
setTimeout(() => {
|
|
3140
|
+
this.keysPressed.delete(mappedKey);
|
|
3141
|
+
}, duration);
|
|
3142
|
+
}
|
|
3050
3143
|
destroy() {
|
|
3051
3144
|
if (this.destroyed) return;
|
|
3052
3145
|
this.destroyed = true;
|
|
@@ -5109,6 +5202,31 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5109
5202
|
vertexLabelManager.updateLabelPosition(index, newPosition);
|
|
5110
5203
|
} catch {
|
|
5111
5204
|
}
|
|
5205
|
+
if (options?.onVertexDragMoveDetail) {
|
|
5206
|
+
try {
|
|
5207
|
+
let coordinates = { longitude: 0, latitude: 0, height: 0 };
|
|
5208
|
+
try {
|
|
5209
|
+
const cartographic = C.Cartographic.fromCartesian(newPosition);
|
|
5210
|
+
coordinates = {
|
|
5211
|
+
longitude: C.Math.toDegrees(cartographic.longitude),
|
|
5212
|
+
latitude: C.Math.toDegrees(cartographic.latitude),
|
|
5213
|
+
height: cartographic.height
|
|
5214
|
+
};
|
|
5215
|
+
} catch {
|
|
5216
|
+
}
|
|
5217
|
+
const displayNumber = hiddenClimbIndex === 1 && index > 1 ? index - 1 : index;
|
|
5218
|
+
const dragMoveInfo = {
|
|
5219
|
+
index,
|
|
5220
|
+
displayNumber,
|
|
5221
|
+
position: newPosition,
|
|
5222
|
+
coordinates,
|
|
5223
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
5224
|
+
};
|
|
5225
|
+
options.onVertexDragMoveDetail(dragMoveInfo);
|
|
5226
|
+
} catch (error) {
|
|
5227
|
+
console.error("Error in onVertexDragMoveDetail:", error);
|
|
5228
|
+
}
|
|
5229
|
+
}
|
|
5112
5230
|
},
|
|
5113
5231
|
onVertexDragEnd: (index, finalPosition) => {
|
|
5114
5232
|
editedIndices.add(index);
|
|
@@ -5149,6 +5267,12 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5149
5267
|
getAirplaneCursor: () => airplaneCursor,
|
|
5150
5268
|
getPoseData: () => ({ headings, pitches, rolls, fovs }),
|
|
5151
5269
|
getEntity: () => entity,
|
|
5270
|
+
/** 模拟按键控制飞机游标(用于虚拟控制器) */
|
|
5271
|
+
simulateKeyPress: (key, duration) => {
|
|
5272
|
+
airplaneCursor?.simulateKeyPress(key, duration);
|
|
5273
|
+
},
|
|
5274
|
+
/** 获取游标当前姿态(包含高度) */
|
|
5275
|
+
getCursorPose: () => airplaneCursor?.getPose(),
|
|
5152
5276
|
// 🆕 快速编辑回调
|
|
5153
5277
|
getQuickEditEnabled: () => quickEditEnabled,
|
|
5154
5278
|
getQuickEditOptions: () => ({
|
|
@@ -5331,9 +5455,166 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5331
5455
|
/** 🆕 检查快速编辑模式是否启用 */
|
|
5332
5456
|
isQuickEditEnabled: () => {
|
|
5333
5457
|
return quickEditEnabled;
|
|
5334
|
-
}
|
|
5458
|
+
},
|
|
5459
|
+
// ========================
|
|
5460
|
+
// 🆕 程序化更新方法
|
|
5461
|
+
// ========================
|
|
5462
|
+
/**
|
|
5463
|
+
* 🆕 程序化更新指定航点
|
|
5464
|
+
* @param index 航点索引
|
|
5465
|
+
* @param updates 需要更新的字段
|
|
5466
|
+
* @returns 是否更新成功
|
|
5467
|
+
*/
|
|
5468
|
+
updateWaypoint: (index, updates) => {
|
|
5469
|
+
if (index < 0 || index >= positions.length) {
|
|
5470
|
+
console.warn(`[updateWaypoint] Invalid index: ${index}, valid range: 0-${positions.length - 1}`);
|
|
5471
|
+
return false;
|
|
5472
|
+
}
|
|
5473
|
+
try {
|
|
5474
|
+
let positionUpdated = false;
|
|
5475
|
+
if (updates.position) {
|
|
5476
|
+
positions[index] = updates.position;
|
|
5477
|
+
positionUpdated = true;
|
|
5478
|
+
}
|
|
5479
|
+
if (updates.altitude !== void 0 && !updates.position) {
|
|
5480
|
+
const currentPos = positions[index];
|
|
5481
|
+
const cartographic = C.Cartographic.fromCartesian(currentPos);
|
|
5482
|
+
const newPos = C.Cartesian3.fromRadians(
|
|
5483
|
+
cartographic.longitude,
|
|
5484
|
+
cartographic.latitude,
|
|
5485
|
+
updates.altitude
|
|
5486
|
+
);
|
|
5487
|
+
positions[index] = newPos;
|
|
5488
|
+
positionUpdated = true;
|
|
5489
|
+
}
|
|
5490
|
+
if (positionUpdated) {
|
|
5491
|
+
const newPos = positions[index];
|
|
5492
|
+
if (handles[index]) {
|
|
5493
|
+
try {
|
|
5494
|
+
handles[index].position = newPos;
|
|
5495
|
+
} catch {
|
|
5496
|
+
}
|
|
5497
|
+
}
|
|
5498
|
+
try {
|
|
5499
|
+
vertexLabelManager.updateLabelPosition(index, newPos);
|
|
5500
|
+
} catch {
|
|
5501
|
+
}
|
|
5502
|
+
try {
|
|
5503
|
+
createOrUpdateMarkerForIndex(index);
|
|
5504
|
+
} catch {
|
|
5505
|
+
}
|
|
5506
|
+
}
|
|
5507
|
+
if (updates.heading !== void 0) headings[index] = updates.heading;
|
|
5508
|
+
if (updates.pitch !== void 0) pitches[index] = updates.pitch;
|
|
5509
|
+
if (updates.roll !== void 0) rolls[index] = updates.roll;
|
|
5510
|
+
if (updates.fov !== void 0) {
|
|
5511
|
+
fovs[index] = updates.fov;
|
|
5512
|
+
if (index === activeIndex) {
|
|
5513
|
+
globalCameraEventBus.onFOVChange.emit({
|
|
5514
|
+
fov: updates.fov,
|
|
5515
|
+
focalLength: fovToFocalLength(updates.fov),
|
|
5516
|
+
source: "user"
|
|
5517
|
+
});
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
if (index === activeIndex && airplaneCursor) {
|
|
5521
|
+
try {
|
|
5522
|
+
airplaneCursor.setPose(
|
|
5523
|
+
positions[index],
|
|
5524
|
+
headings[index] ?? 0,
|
|
5525
|
+
pitches[index] ?? -10,
|
|
5526
|
+
rolls[index] ?? 0
|
|
5527
|
+
);
|
|
5528
|
+
} catch {
|
|
5529
|
+
}
|
|
5530
|
+
}
|
|
5531
|
+
stateManager.persistToEntity(positions, headings, pitches, rolls, fovs);
|
|
5532
|
+
return true;
|
|
5533
|
+
} catch (error) {
|
|
5534
|
+
console.error("[updateWaypoint] Error:", error);
|
|
5535
|
+
return false;
|
|
5536
|
+
}
|
|
5537
|
+
},
|
|
5538
|
+
/**
|
|
5539
|
+
* 🆕 更新航点位置
|
|
5540
|
+
*/
|
|
5541
|
+
updateWaypointPosition: function(index, position) {
|
|
5542
|
+
return this.updateWaypoint(index, { position });
|
|
5543
|
+
},
|
|
5544
|
+
/**
|
|
5545
|
+
* 🆕 更新航点高度(仅垂直方向,保持经纬度不变)
|
|
5546
|
+
*/
|
|
5547
|
+
updateWaypointAltitude: function(index, altitude) {
|
|
5548
|
+
return this.updateWaypoint(index, { altitude });
|
|
5549
|
+
},
|
|
5550
|
+
/**
|
|
5551
|
+
* 🆕 更新航点偏航角
|
|
5552
|
+
*/
|
|
5553
|
+
updateWaypointHeading: function(index, heading) {
|
|
5554
|
+
return this.updateWaypoint(index, { heading });
|
|
5555
|
+
},
|
|
5556
|
+
/**
|
|
5557
|
+
* 🆕 更新航点俯仰角
|
|
5558
|
+
*/
|
|
5559
|
+
updateWaypointPitch: function(index, pitch) {
|
|
5560
|
+
return this.updateWaypoint(index, { pitch });
|
|
5561
|
+
},
|
|
5562
|
+
/**
|
|
5563
|
+
* 🆕 更新航点视野角
|
|
5564
|
+
*/
|
|
5565
|
+
updateWaypointFov: function(index, fov) {
|
|
5566
|
+
return this.updateWaypoint(index, { fov });
|
|
5567
|
+
},
|
|
5568
|
+
/**
|
|
5569
|
+
* 🆕 批量更新多个航点
|
|
5570
|
+
*/
|
|
5571
|
+
batchUpdateWaypoints: function(updates) {
|
|
5572
|
+
let allSuccess = true;
|
|
5573
|
+
for (const { index, data } of updates) {
|
|
5574
|
+
if (!this.updateWaypoint(index, data)) {
|
|
5575
|
+
allSuccess = false;
|
|
5576
|
+
}
|
|
5577
|
+
}
|
|
5578
|
+
return allSuccess;
|
|
5579
|
+
},
|
|
5580
|
+
/**
|
|
5581
|
+
* 🆕 程序化选中指定航点
|
|
5582
|
+
* 将飞机游标移动到指定航点位置,更新选中状态
|
|
5583
|
+
* @param index 航点索引
|
|
5584
|
+
* @returns 是否选中成功
|
|
5585
|
+
*/
|
|
5586
|
+
selectVertex: (index) => {
|
|
5587
|
+
if (index < 0 || index >= positions.length) {
|
|
5588
|
+
console.warn(`[selectVertex] Invalid index: ${index}, valid range: 0-${positions.length - 1}`);
|
|
5589
|
+
return false;
|
|
5590
|
+
}
|
|
5591
|
+
try {
|
|
5592
|
+
setActiveIndex(index);
|
|
5593
|
+
return true;
|
|
5594
|
+
} catch (e) {
|
|
5595
|
+
console.error("[selectVertex] Failed to select vertex:", e);
|
|
5596
|
+
return false;
|
|
5597
|
+
}
|
|
5598
|
+
},
|
|
5599
|
+
/**
|
|
5600
|
+
* 🆕 模拟按键控制飞机游标(用于虚拟控制器)
|
|
5601
|
+
* @param key 按键名称 (w/a/s/d/q/e/c/z)
|
|
5602
|
+
* @param duration 按键持续时间(毫秒)
|
|
5603
|
+
*/
|
|
5604
|
+
simulateKeyPress: (key, duration) => {
|
|
5605
|
+
airplaneCursor?.simulateKeyPress(key, duration);
|
|
5606
|
+
},
|
|
5607
|
+
/**
|
|
5608
|
+
* 🆕 获取游标当前姿态(包含高度)
|
|
5609
|
+
*/
|
|
5610
|
+
getCursorPose: () => airplaneCursor?.getPose()
|
|
5335
5611
|
};
|
|
5336
5612
|
}
|
|
5613
|
+
function fovToFocalLength(fovDeg) {
|
|
5614
|
+
const sensorWidth = 36;
|
|
5615
|
+
const fovRad = fovDeg * Math.PI / 180;
|
|
5616
|
+
return sensorWidth / (2 * Math.tan(fovRad / 2));
|
|
5617
|
+
}
|
|
5337
5618
|
|
|
5338
5619
|
// src/core/path-manager/ArrowShape.ts
|
|
5339
5620
|
var ArrowShape = class {
|
|
@@ -5730,7 +6011,6 @@ function parsePoseFromAction(action) {
|
|
|
5730
6011
|
fov: parseFloat(numbers[3])
|
|
5731
6012
|
};
|
|
5732
6013
|
}
|
|
5733
|
-
console.warn("[sinoflyAdapter] \u65E0\u6CD5\u89E3\u6790 action \u5B57\u6BB5:", action, error);
|
|
5734
6014
|
return {};
|
|
5735
6015
|
}
|
|
5736
6016
|
}
|
|
@@ -5748,15 +6028,40 @@ function parseTakeOffRefPoint(takeOffRefPoint, takeOffSecurityHeight, CesiumNS)
|
|
|
5748
6028
|
if (!takeOffRefPoint || typeof takeOffRefPoint !== "string" || takeOffRefPoint.trim() === "") {
|
|
5749
6029
|
return null;
|
|
5750
6030
|
}
|
|
6031
|
+
const C = CesiumNS;
|
|
6032
|
+
let longitude;
|
|
6033
|
+
let latitude;
|
|
6034
|
+
let height;
|
|
6035
|
+
const trimmed = takeOffRefPoint.trim();
|
|
6036
|
+
if (trimmed.includes(",")) {
|
|
6037
|
+
try {
|
|
6038
|
+
const parts = trimmed.split(",").map((p) => p.trim());
|
|
6039
|
+
if (parts.length >= 2) {
|
|
6040
|
+
latitude = parseFloat(parts[0]);
|
|
6041
|
+
longitude = parseFloat(parts[1]);
|
|
6042
|
+
height = parts.length >= 3 ? parseFloat(parts[2]) : takeOffSecurityHeight;
|
|
6043
|
+
if (isNaN(latitude) || isNaN(longitude) || isNaN(height)) {
|
|
6044
|
+
throw new Error("\u65E0\u6CD5\u89E3\u6790\u9017\u53F7\u5206\u9694\u7684\u5750\u6807\u503C");
|
|
6045
|
+
}
|
|
6046
|
+
const startPosition = C.Cartesian3.fromDegrees(longitude, latitude, height);
|
|
6047
|
+
const climbPosition = C.Cartesian3.fromDegrees(
|
|
6048
|
+
longitude,
|
|
6049
|
+
latitude,
|
|
6050
|
+
height + takeOffSecurityHeight
|
|
6051
|
+
);
|
|
6052
|
+
return {
|
|
6053
|
+
startPosition,
|
|
6054
|
+
climbPosition
|
|
6055
|
+
};
|
|
6056
|
+
}
|
|
6057
|
+
} catch (error) {
|
|
6058
|
+
}
|
|
6059
|
+
}
|
|
5751
6060
|
try {
|
|
5752
6061
|
const parsed = JSON.parse(takeOffRefPoint);
|
|
5753
6062
|
if (typeof parsed !== "object" || parsed === null) {
|
|
5754
6063
|
return null;
|
|
5755
6064
|
}
|
|
5756
|
-
const C = CesiumNS;
|
|
5757
|
-
let longitude;
|
|
5758
|
-
let latitude;
|
|
5759
|
-
let height;
|
|
5760
6065
|
if (typeof parsed.longitude === "number") {
|
|
5761
6066
|
longitude = parsed.longitude;
|
|
5762
6067
|
} else if (typeof parsed.lon === "number") {
|
|
@@ -5787,7 +6092,6 @@ function parseTakeOffRefPoint(takeOffRefPoint, takeOffSecurityHeight, CesiumNS)
|
|
|
5787
6092
|
climbPosition
|
|
5788
6093
|
};
|
|
5789
6094
|
} catch (error) {
|
|
5790
|
-
console.warn("[sinoflyAdapter] \u65E0\u6CD5\u89E3\u6790 takeOffRefPoint:", takeOffRefPoint, error);
|
|
5791
6095
|
return null;
|
|
5792
6096
|
}
|
|
5793
6097
|
}
|
|
@@ -5809,16 +6113,10 @@ function convertSinoflyWayline(data, options) {
|
|
|
5809
6113
|
if (!data.waypointInfo || !Array.isArray(data.waypointInfo)) {
|
|
5810
6114
|
throw new Error("[sinoflyAdapter] waypointInfo \u5FC5\u987B\u662F\u6570\u7EC4");
|
|
5811
6115
|
}
|
|
5812
|
-
if (data.waypointInfo.length === 0)
|
|
5813
|
-
console.warn("[sinoflyAdapter] waypointInfo \u6570\u7EC4\u4E3A\u7A7A\uFF0C\u5C06\u8FD4\u56DE\u7A7A\u7684\u822A\u70B9\u6570\u636E");
|
|
5814
|
-
}
|
|
6116
|
+
if (data.waypointInfo.length === 0) ;
|
|
5815
6117
|
if (data.waylineId === void 0 || data.waylineId === null) {
|
|
5816
6118
|
throw new Error("[sinoflyAdapter] waylineId \u4E0D\u80FD\u4E3A\u7A7A");
|
|
5817
6119
|
}
|
|
5818
|
-
console.log(`[sinoflyAdapter] \u5F00\u59CB\u8F6C\u6362\u822A\u7EBF ${data.waylineId}\uFF0C\u5305\u542B ${data.waypointInfo.length} \u4E2A\u822A\u70B9`);
|
|
5819
|
-
if (data.takeOffRefPoint) {
|
|
5820
|
-
console.log(`[sinoflyAdapter] \u68C0\u6D4B\u5230 takeOffRefPoint: ${data.takeOffRefPoint}`);
|
|
5821
|
-
}
|
|
5822
6120
|
const takeOffInfo = parseTakeOffRefPoint(
|
|
5823
6121
|
data.takeOffRefPoint,
|
|
5824
6122
|
data.takeOffSecurityHeight,
|
|
@@ -5883,7 +6181,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
5883
6181
|
if (poseFromAction.roll !== void 0) roll = poseFromAction.roll;
|
|
5884
6182
|
if (poseFromAction.fov !== void 0) fov = poseFromAction.fov;
|
|
5885
6183
|
} catch (actionError) {
|
|
5886
|
-
console.warn(`[sinoflyAdapter] \u822A\u70B9 ${idx} action \u89E3\u6790\u5931\u8D25:`, actionError);
|
|
5887
6184
|
}
|
|
5888
6185
|
}
|
|
5889
6186
|
return {
|
|
@@ -5896,7 +6193,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
5896
6193
|
// 重新分配 index,从 waypointStartIndex 开始
|
|
5897
6194
|
};
|
|
5898
6195
|
} catch (error) {
|
|
5899
|
-
console.error(`[sinoflyAdapter] \u822A\u70B9 ${idx} \u8F6C\u6362\u5931\u8D25:`, error);
|
|
5900
6196
|
throw new Error(`\u822A\u70B9 ${idx} \u8F6C\u6362\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
5901
6197
|
}
|
|
5902
6198
|
});
|
|
@@ -5904,7 +6200,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
5904
6200
|
if (!Array.isArray(waypointData)) {
|
|
5905
6201
|
throw new Error("[sinoflyAdapter] waypointData \u4E0D\u662F\u6570\u7EC4");
|
|
5906
6202
|
}
|
|
5907
|
-
console.log(`[sinoflyAdapter] \u8F6C\u6362\u5B8C\u6210\uFF0C\u5171\u751F\u6210 ${waypointData.length} \u4E2A\u822A\u70B9`);
|
|
5908
6203
|
const metadata = {
|
|
5909
6204
|
waylineId: data.waylineId,
|
|
5910
6205
|
waylineType: data.waylineType,
|