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