deeptwins-engine-3d 0.1.1 → 0.1.2

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/LICENSE CHANGED
@@ -1,21 +1,6 @@
1
- MIT License
2
-
3
- Copyright (c) sdzl
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ COPYRIGHT NOTICE & COMMERCIAL LICENSE
2
+ Copyright (c) 2025 sdzl. All rights reserved.
3
+ This software is proprietary and commercial. Unauthorized use, copying, modification,
4
+ or redistribution is strictly prohibited without a valid license agreement.
5
+ For licensing and pricing information, please contact:
6
+ Email: shenduzhilian@gmail.com
package/README.md CHANGED
@@ -2,38 +2,3 @@
2
2
  map for 3d
3
3
 
4
4
  ## Usage
5
-
6
- TODO
7
-
8
- ## Options
9
-
10
- TODO
11
-
12
- ## Development
13
-
14
- ```bash
15
- # install dependencies
16
- $ npm install
17
-
18
- # develop library by docs demo
19
- $ npm start
20
-
21
- # build library source code
22
- $ npm run build
23
-
24
- # build library source code in watch mode
25
- $ npm run build:watch
26
-
27
- # build docs
28
- $ npm run docs:build
29
-
30
- # Locally preview the production build.
31
- $ npm run docs:preview
32
-
33
- # check your project for potential problems
34
- $ npm run doctor
35
- ```
36
-
37
- ## LICENSE
38
-
39
- MIT
@@ -6,7 +6,7 @@ interface Position {
6
6
  lng: number;
7
7
  lat: number;
8
8
  alt: number;
9
- timestamp?: number;
9
+ timestamp: number;
10
10
  }
11
11
  export default class ModelRoamRealTime {
12
12
  readonly _map: any;
@@ -17,17 +17,21 @@ export default class ModelRoamRealTime {
17
17
  private readonly _onPositionUpdate;
18
18
  modelLayer: any;
19
19
  polylineLayer: any;
20
+ historyPolylineLayer: any;
20
21
  private _lastFrameTime;
21
22
  private _stepAccumulator;
22
23
  private _frameCount;
23
24
  private _fps;
24
- private _time;
25
25
  private receivedPositions;
26
26
  private completedSegments;
27
27
  private currentSegment;
28
28
  private futureSegments;
29
29
  private currentPointIndex;
30
30
  private segmentCounter;
31
+ private TRAIL_POSITIONS_THRESHOLD;
32
+ private historyTrailPositions;
33
+ private trailDataUpdated;
34
+ private trailShowState;
31
35
  private _eventPostUpdate;
32
36
  private modelMatrix;
33
37
  private hpRoll;
@@ -83,23 +87,27 @@ export default class ModelRoamRealTime {
83
87
  * 初始化轨迹线Entity
84
88
  */
85
89
  private initTrailLine;
90
+ /**
91
+ * 创建历史轨迹线Entity
92
+ */
93
+ private createHistoryTrailLine;
86
94
  /**
87
95
  * 获取轨迹线位置点
88
96
  * 返回:已完成路径段的起始点和结束点 + 当前路径段已飞行的插值点
89
97
  */
90
98
  private getTrailLinePositions;
91
99
  /**
92
- * 更新轨迹线 - 现在由CallbackProperty自动更新
100
+ * 检查并移动数据到历史轨迹
93
101
  */
94
- private updateTrailLine;
102
+ private checkAndMoveToHistory;
95
103
  /**
96
- * 获取当前状态信息
104
+ * 标记已经移动到历史的路径段
97
105
  */
98
- getStatus(): any;
106
+ private markCompletedSegmentsAsMovedToHistory;
99
107
  /**
100
- * 获取详细的飞行信息
108
+ * 更新轨迹线 - 现在由CallbackProperty自动更新
101
109
  */
102
- getFlightDetails(): any;
110
+ private updateTrailLine;
103
111
  /**
104
112
  * 计算模型朝向
105
113
  * @param start 起始点
@@ -130,7 +138,7 @@ export default class ModelRoamRealTime {
130
138
  */
131
139
  setFollowFirst(options: any): void;
132
140
  /**
133
- * 设置第一人称视角
141
+ * 设置第三人称视角
134
142
  */
135
143
  setFollowThird(options: any): void;
136
144
  /**
@@ -141,6 +149,15 @@ export default class ModelRoamRealTime {
141
149
  * 飞行定位到模型
142
150
  */
143
151
  private _flyToModel;
152
+ /**
153
+ * 显示隐藏飞行轨迹
154
+ * */
155
+ showPolylineLayer(isShow: boolean): void;
156
+ /**
157
+ * 强制更新轨迹数据
158
+ * 用于确保轨迹数据的连续性
159
+ */
160
+ forceUpdateTrailData(): void;
144
161
  /**
145
162
  * 监听
146
163
  */
@@ -1,4 +1,10 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
5
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
6
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
7
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
2
8
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
3
9
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
10
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -14,7 +20,7 @@ import * as Cesium from 'deeptwins-cesium';
14
20
  import { cloneDeep, merge } from 'lodash';
15
21
  import { v4 as uuidv4 } from 'uuid';
16
22
  import * as constant from "../constant";
17
- import { colorString } from "../tool/utils";
23
+ import PolylineEntity from "../graphicLayer/PolylineEntity";
18
24
 
19
25
  /**
20
26
  * 位置信息
@@ -48,15 +54,14 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
48
54
  _defineProperty(this, "modelLayer", void 0);
49
55
  // 轨迹layer
50
56
  _defineProperty(this, "polylineLayer", void 0);
57
+ // 历史轨迹layer
58
+ _defineProperty(this, "historyPolylineLayer", void 0);
51
59
  // 上一帧时间
52
60
  _defineProperty(this, "_lastFrameTime", performance.now());
53
61
  // 累加器
54
62
  _defineProperty(this, "_stepAccumulator", 0);
55
63
  _defineProperty(this, "_frameCount", 0);
56
64
  _defineProperty(this, "_fps", 'N/A');
57
- // 重新设计的数据结构
58
- // 上个点位的时间
59
- _defineProperty(this, "_time", performance.now());
60
65
  // 接收到的原始位置数据
61
66
  _defineProperty(this, "receivedPositions", []);
62
67
  // 已完成飞行的路径段
@@ -69,6 +74,14 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
69
74
  _defineProperty(this, "currentPointIndex", 0);
70
75
  // 路径段计数器
71
76
  _defineProperty(this, "segmentCounter", 0);
77
+ // 轨迹线数据量阈值
78
+ _defineProperty(this, "TRAIL_POSITIONS_THRESHOLD", 1000);
79
+ // 历史轨迹位置点
80
+ _defineProperty(this, "historyTrailPositions", []);
81
+ // 轨迹数据更新标志
82
+ _defineProperty(this, "trailDataUpdated", false);
83
+ // 轨迹显示状态
84
+ _defineProperty(this, "trailShowState", true);
72
85
  // 帧率更新的事件
73
86
  _defineProperty(this, "_eventPostUpdate", void 0);
74
87
  // 模型参数
@@ -102,8 +115,9 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
102
115
  _defineProperty(this, "updateModel", function () {
103
116
  var currentTime = performance.now();
104
117
  _this._frameCount++;
105
- if (currentTime - _this._lastFrameTime > 1000) {
106
- _this._fps = _this._frameCount;
118
+ var elapsed = currentTime - _this._lastFrameTime;
119
+ if (elapsed > 60) {
120
+ _this._fps = Math.min(Math.round(_this._frameCount * 1000 / elapsed), _this._map.targetFrameRate);
107
121
  _this._frameCount = 0;
108
122
  _this._lastFrameTime = currentTime;
109
123
  }
@@ -114,6 +128,7 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
114
128
  // 检查当前路径段是否完成
115
129
  if (_this.currentPointIndex >= _this.currentSegment.interpolatedPoints.length) {
116
130
  _this.completeCurrentSegment();
131
+ _this._stepAccumulator += 1;
117
132
  return;
118
133
  }
119
134
  var currentPos = _this.currentSegment.interpolatedPoints[_this.currentPointIndex];
@@ -130,6 +145,9 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
130
145
  // 初始化轨迹线(如果还未创建)
131
146
  _this.updateTrailLine();
132
147
 
148
+ // 重置轨迹数据更新标志
149
+ _this.trailDataUpdated = false;
150
+
133
151
  // 更新模型位置
134
152
  if (_this.modelLayer) {
135
153
  // 只有位置真正发生变化时才更新矩阵
@@ -149,19 +167,18 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
149
167
  _this.updateCameraView();
150
168
  }
151
169
  }
152
- _this.currentPointIndex++;
153
170
  if (_this._fps === 'N/A') {
154
171
  _this.currentPointIndex++;
155
172
  } else {
156
- // 每帧应飞的“点数”(允许小数)
157
- var exactStep = _this._map.targetFrameRate / _this._fps;
173
+ // 每帧应飞的"点数"(允许小数)
174
+ var exactStep = _this._fps ? _this._map.targetFrameRate / _this._fps : 1;
158
175
  // 累加步长
159
176
  _this._stepAccumulator += exactStep;
160
- // 取整:当前帧应飞的“完整点数”
177
+ // 取整:当前帧应飞的"完整点数"
161
178
  var step = Math.max(1, Math.floor(_this._stepAccumulator));
162
179
  // 剩余留给下帧
163
- _this._stepAccumulator -= step;
164
- _this.currentPointIndex = _this.currentPointIndex + step;
180
+ _this._stepAccumulator -= Math.min(step, _this._stepAccumulator);
181
+ _this.currentPointIndex += step;
165
182
  }
166
183
  });
167
184
  if (!map) {
@@ -179,6 +196,11 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
179
196
  this.polylineOptions = merge(constant.DEFAULT_POLYLINE_PRIMITIVE_OPTIONS(), cloneDeep(polyline || {}));
180
197
  this.flyTo = flyTo || false;
181
198
  this._onPositionUpdate = onPositionUpdate;
199
+
200
+ // 初始化轨迹显示状态
201
+ if (this.polylineOptions && typeof this.polylineOptions.show === 'boolean') {
202
+ this.trailShowState = this.polylineOptions.show;
203
+ }
182
204
  }
183
205
 
184
206
  /**
@@ -193,7 +215,7 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
193
215
 
194
216
  // 添加时间戳
195
217
  if (!newPosition.timestamp) {
196
- newPosition.timestamp = new Date().getTime();
218
+ newPosition.timestamp = performance.now();
197
219
  }
198
220
 
199
221
  // 如果是第一次接收数据,初始化模型
@@ -240,9 +262,7 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
240
262
  var endC3 = Cesium.Cartesian3.fromDegrees(endPos.lng, endPos.lat, endPos.alt);
241
263
 
242
264
  // 计算飞行时间
243
- var newTime = performance.now();
244
- var flightTime = (newTime - this._time) / 1000;
245
- this._time = newTime;
265
+ var flightTime = (endPos.timestamp - startPos.timestamp) / 1000;
246
266
 
247
267
  // 计算插值点
248
268
  var interpolatedPoints = this._getInterPosition(startC3, endC3, flightTime);
@@ -251,7 +271,8 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
251
271
  endPos: endPos,
252
272
  interpolatedPoints: interpolatedPoints,
253
273
  segmentIndex: this.segmentCounter++,
254
- isCompleted: false
274
+ isCompleted: false,
275
+ isMovedToHistory: false
255
276
  };
256
277
 
257
278
  // 如果当前没有正在飞行的路径段,则设为当前段
@@ -309,7 +330,7 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
309
330
  }
310
331
 
311
332
  // 计算总的插值点数 用最大帧率*时间计算点位
312
- var numberOfPoints = Math.max(10, Math.floor(flightTime * this._map.targetFrameRate));
333
+ var numberOfPoints = Math.max(2, Math.floor(flightTime * this._map.targetFrameRate) - 1);
313
334
 
314
335
  // 计算时间步长
315
336
  var timeStep = 1.0 / (numberOfPoints - 1);
@@ -422,18 +443,47 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
422
443
  key: "initTrailLine",
423
444
  value: function initTrailLine() {
424
445
  var _this3 = this;
446
+ var mergeStyle = merge(constant.DEFAULT_POLYLINE_OPTIONS(), cloneDeep(this.polylineOptions || {}));
447
+ var currStyle = PolylineEntity.handleOptions(mergeStyle);
425
448
  // 创建轨迹线Entity,使用callback动态更新位置
426
449
  this.polylineLayer = this._map.entities.add({
427
450
  id: uuidv4(),
428
- polyline: {
451
+ polyline: _objectSpread({
429
452
  positions: new Cesium.CallbackProperty(function () {
430
- return _this3.getTrailLinePositions();
431
- }, false),
432
- width: this.polylineOptions.width || 2,
433
- material: colorString(this.polylineOptions.color || Cesium.Color.YELLOW),
434
- clampToGround: false
435
- }
453
+ // 即使轨迹隐藏,也要更新数据
454
+ var positions = _this3.getTrailLinePositions();
455
+ _this3.trailDataUpdated = true;
456
+ return positions;
457
+ }, false)
458
+ }, currStyle)
436
459
  });
460
+
461
+ // 设置初始显示状态
462
+ if (this.polylineLayer) {
463
+ this.polylineLayer.polyline.show = this.trailShowState;
464
+ }
465
+ }
466
+
467
+ /**
468
+ * 创建历史轨迹线Entity
469
+ */
470
+ }, {
471
+ key: "createHistoryTrailLine",
472
+ value: function createHistoryTrailLine() {
473
+ var mergeStyle = merge(constant.DEFAULT_POLYLINE_OPTIONS(), cloneDeep(this.polylineOptions || {}));
474
+ var currStyle = PolylineEntity.handleOptions(mergeStyle);
475
+ // 创建历史轨迹线Entity,使用静态位置
476
+ this.historyPolylineLayer = this._map.entities.add({
477
+ id: uuidv4(),
478
+ polyline: _objectSpread({
479
+ positions: this.historyTrailPositions
480
+ }, currStyle)
481
+ });
482
+
483
+ // 同步当前轨迹线的显示状态
484
+ if (this.polylineLayer) {
485
+ this.historyPolylineLayer.polyline.show = this.polylineLayer.polyline.show;
486
+ }
437
487
  }
438
488
 
439
489
  /**
@@ -450,10 +500,10 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
450
500
  return positions;
451
501
  }
452
502
 
453
- // 添加已完成路径段的起始点和结束点
503
+ // 添加已完成路径段的起始点和结束点(只处理未移动到历史的路径段)
454
504
  if (Array.isArray(this.completedSegments)) {
455
505
  this.completedSegments.forEach(function (segment) {
456
- if (segment.startPos && segment.endPos) {
506
+ if (segment.startPos && segment.endPos && !segment.isMovedToHistory) {
457
507
  // 添加起始点(如果这是第一个路径段或者与上一个路径段不重复)
458
508
  if (positions.length === 0) {
459
509
  positions.push(Cesium.Cartesian3.fromDegrees(segment.startPos.lng, segment.startPos.lat, segment.startPos.alt));
@@ -464,6 +514,9 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
464
514
  });
465
515
  }
466
516
 
517
+ // 检查数据量是否超过阈值,如果超过则将部分数据移到历史轨迹
518
+ this.checkAndMoveToHistory(positions);
519
+
467
520
  // 如果当前有正在飞行的路径段,添加已飞行过的插值点
468
521
  if (this.currentSegment && Array.isArray(this.currentSegment.interpolatedPoints) && this.currentPointIndex >= 0) {
469
522
  // 如果还没有添加过任何点,先添加当前路径段的起始点
@@ -480,92 +533,76 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
480
533
  }
481
534
 
482
535
  /**
483
- * 更新轨迹线 - 现在由CallbackProperty自动更新
536
+ * 检查并移动数据到历史轨迹
484
537
  */
485
538
  }, {
486
- key: "updateTrailLine",
487
- value: function updateTrailLine() {
488
- // 由于使用了CallbackProperty和getTrailLinePositions方法
489
- // 轨迹线会自动更新显示:所有原始位置点 + 当前段已飞行的插值点
490
- if (!this.polylineLayer && this.receivedPositions.length >= 2) {
491
- this.initTrailLine();
539
+ key: "checkAndMoveToHistory",
540
+ value: function checkAndMoveToHistory(currentPositions) {
541
+ if (currentPositions.length > this.TRAIL_POSITIONS_THRESHOLD) {
542
+ var _this$historyTrailPos;
543
+ // 将所有超过阈值的点移动到历史轨迹
544
+ var positionsToHistory = currentPositions.slice(0, this.TRAIL_POSITIONS_THRESHOLD);
545
+
546
+ // 从当前轨迹中移除这些点
547
+ currentPositions.splice(0, this.TRAIL_POSITIONS_THRESHOLD);
548
+
549
+ // 标记已经移动到历史的路径段
550
+ this.markCompletedSegmentsAsMovedToHistory();
551
+ (_this$historyTrailPos = this.historyTrailPositions).push.apply(_this$historyTrailPos, _toConsumableArray(positionsToHistory));
552
+
553
+ // 如果历史轨迹图层不存在,创建它
554
+ if (!this.historyPolylineLayer) {
555
+ this.createHistoryTrailLine();
556
+ } else {
557
+ // 更新历史轨迹图层的位置
558
+ this.historyPolylineLayer.polyline.positions = this.historyTrailPositions;
559
+ }
560
+
561
+ // 同步显示状态
562
+ if (this.polylineLayer && this.historyPolylineLayer) {
563
+ this.historyPolylineLayer.polyline.show = this.polylineLayer.polyline.show;
564
+ }
492
565
  }
493
566
  }
494
567
 
495
568
  /**
496
- * 获取当前状态信息
569
+ * 标记已经移动到历史的路径段
497
570
  */
498
571
  }, {
499
- key: "getStatus",
500
- value: function getStatus() {
501
- var _this$currentSegment;
502
- var currentProgress = this.currentSegment ? Math.round(this.currentPointIndex / this.currentSegment.interpolatedPoints.length * 100) : 0;
503
- return {
504
- status: this.status,
505
- receivedPositionsCount: this.receivedPositions.length,
506
- completedSegmentsCount: this.completedSegments.length,
507
- currentSegmentIndex: ((_this$currentSegment = this.currentSegment) === null || _this$currentSegment === void 0 ? void 0 : _this$currentSegment.segmentIndex) || null,
508
- currentSegmentProgress: "".concat(currentProgress, "%"),
509
- futureSegmentsCount: this.futureSegments.length,
510
- currentPointIndex: this.currentPointIndex,
511
- totalTrailPoints: this.getTrailLinePositions().length,
512
- isWaitingForData: !this.currentSegment && this.futureSegments.length === 0
513
- };
572
+ key: "markCompletedSegmentsAsMovedToHistory",
573
+ value: function markCompletedSegmentsAsMovedToHistory() {
574
+ if (!Array.isArray(this.completedSegments) || this.completedSegments.length === 0) {
575
+ return;
576
+ }
577
+
578
+ // 标记除了最后一个路径段之外的所有已完成路径段
579
+ var segmentsToMark = this.completedSegments.length - 2;
580
+ for (var i = 0; i < segmentsToMark; i++) {
581
+ var segment = this.completedSegments[i];
582
+ if (segment.isCompleted && !segment.isMovedToHistory) {
583
+ segment.isMovedToHistory = true;
584
+ }
585
+ }
514
586
  }
515
587
 
516
588
  /**
517
- * 获取详细的飞行信息
589
+ * 更新轨迹线 - 现在由CallbackProperty自动更新
518
590
  */
519
591
  }, {
520
- key: "getFlightDetails",
521
- value: function getFlightDetails() {
522
- var _this4 = this;
523
- return {
524
- // 当前位置信息
525
- currentPosition: this.currentSegment && this.currentPointIndex < this.currentSegment.interpolatedPoints.length ? function () {
526
- var pos = _this4.currentSegment.interpolatedPoints[_this4.currentPointIndex];
527
- var cartographic = Cesium.Cartographic.fromCartesian(pos);
528
- return {
529
- longitude: Cesium.Math.toDegrees(cartographic.longitude),
530
- latitude: Cesium.Math.toDegrees(cartographic.latitude),
531
- height: cartographic.height
532
- };
533
- }() : null,
534
- // 当前路径段信息
535
- currentSegment: this.currentSegment ? {
536
- index: this.currentSegment.segmentIndex,
537
- startPos: this.currentSegment.startPos,
538
- endPos: this.currentSegment.endPos,
539
- totalPoints: this.currentSegment.interpolatedPoints.length,
540
- currentPoint: this.currentPointIndex,
541
- progress: Math.round(this.currentPointIndex / this.currentSegment.interpolatedPoints.length * 100)
542
- } : null,
543
- // 队列信息
544
- queue: {
545
- completed: Array.isArray(this.completedSegments) ? this.completedSegments.map(function (seg) {
546
- return {
547
- index: seg.segmentIndex,
548
- from: "(".concat(seg.startPos.lng, ", ").concat(seg.startPos.lat, ")"),
549
- to: "(".concat(seg.endPos.lng, ", ").concat(seg.endPos.lat, ")")
550
- };
551
- }) : [],
552
- future: Array.isArray(this.futureSegments) ? this.futureSegments.map(function (seg) {
553
- return {
554
- index: seg.segmentIndex,
555
- from: "(".concat(seg.startPos.lng, ", ").concat(seg.startPos.lat, ")"),
556
- to: "(".concat(seg.endPos.lng, ", ").concat(seg.endPos.lat, ")"),
557
- points: seg.interpolatedPoints.length
558
- };
559
- }) : []
560
- },
561
- // 整体统计
562
- statistics: {
563
- totalDataReceived: this.receivedPositions.length,
564
- totalSegmentsCreated: this.segmentCounter,
565
- totalTrailPoints: this.getTrailLinePositions().length,
566
- memoryStatus: "\u5DF2\u5B8C\u6210\u6BB5\u6570: ".concat(this.completedSegments.length, ", \u7B49\u5F85\u6BB5\u6570: ").concat(this.futureSegments.length)
567
- }
568
- };
592
+ key: "updateTrailLine",
593
+ value: function updateTrailLine() {
594
+ // 由于使用了CallbackProperty和getTrailLinePositions方法
595
+ // 轨迹线会自动更新显示:所有原始位置点 + 当前段已飞行的插值点
596
+ if (!this.polylineLayer && this.receivedPositions.length >= 2) {
597
+ this.initTrailLine();
598
+ }
599
+
600
+ // 强制更新轨迹数据,确保即使轨迹隐藏时数据也能正确更新
601
+ if (this.polylineLayer && !this.trailDataUpdated) {
602
+ // 手动触发一次数据更新
603
+ this.getTrailLinePositions();
604
+ this.trailDataUpdated = true;
605
+ }
569
606
  }
570
607
 
571
608
  /**
@@ -662,7 +699,20 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
662
699
  }, {
663
700
  key: "updateThirdPersonView",
664
701
  value: function updateThirdPersonView(position) {
665
- this._map.camera.lookAt(position, new Cesium.HeadingPitchRange(this.hpRoll.heading, Cesium.Math.toRadians(this.thirdPersonSettings.pitch), this.thirdPersonSettings.distance));
702
+ // 计算相机位置(在模型后方一定距离)
703
+ var transform = Cesium.Transforms.headingPitchRollToFixedFrame(position, this.hpRoll, Cesium.Ellipsoid.WGS84, Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west'));
704
+ var offset = new Cesium.Cartesian3(-this.thirdPersonSettings.distance, 0, 500);
705
+ var cameraPosition = Cesium.Matrix4.multiplyByPoint(transform, offset, new Cesium.Cartesian3());
706
+
707
+ // 设置相机位置和朝向
708
+ this._map.camera.setView({
709
+ destination: cameraPosition,
710
+ orientation: {
711
+ heading: this.hpRoll.heading,
712
+ pitch: Cesium.Math.toRadians(this.thirdPersonSettings.pitch),
713
+ roll: 0.0
714
+ }
715
+ });
666
716
  }
667
717
 
668
718
  /**
@@ -678,7 +728,7 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
678
728
  }
679
729
 
680
730
  /**
681
- * 设置第一人称视角
731
+ * 设置第三人称视角
682
732
  */
683
733
  }, {
684
734
  key: "setFollowThird",
@@ -710,6 +760,44 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
710
760
  this._map.camera.flyToBoundingSphere(boundingSphere);
711
761
  }
712
762
 
763
+ /**
764
+ * 显示隐藏飞行轨迹
765
+ * */
766
+ }, {
767
+ key: "showPolylineLayer",
768
+ value: function showPolylineLayer(isShow) {
769
+ this.trailShowState = isShow;
770
+ if (this.polylineLayer) {
771
+ this.polylineLayer.polyline.show = isShow;
772
+ }
773
+ if (this.historyPolylineLayer) {
774
+ this.historyPolylineLayer.polyline.show = isShow;
775
+ }
776
+
777
+ // 如果显示轨迹,强制更新一次数据以确保轨迹连续性
778
+ if (isShow && this.polylineLayer) {
779
+ this.trailDataUpdated = false;
780
+ // 手动触发一次数据更新
781
+ this.getTrailLinePositions();
782
+ this.trailDataUpdated = true;
783
+ }
784
+ }
785
+
786
+ /**
787
+ * 强制更新轨迹数据
788
+ * 用于确保轨迹数据的连续性
789
+ */
790
+ }, {
791
+ key: "forceUpdateTrailData",
792
+ value: function forceUpdateTrailData() {
793
+ if (this.polylineLayer) {
794
+ this.trailDataUpdated = false;
795
+ // 手动触发一次数据更新
796
+ this.getTrailLinePositions();
797
+ this.trailDataUpdated = true;
798
+ }
799
+ }
800
+
713
801
  /**
714
802
  * 监听
715
803
  */
@@ -737,12 +825,19 @@ var ModelRoamRealTime = /*#__PURE__*/function () {
737
825
  this._map.entities.remove(this.polylineLayer);
738
826
  this.polylineLayer = null;
739
827
  }
828
+ if (this.historyPolylineLayer) {
829
+ this._map.entities.remove(this.historyPolylineLayer);
830
+ this.historyPolylineLayer = null;
831
+ }
740
832
  this.receivedPositions = [];
741
833
  this.completedSegments = [];
742
834
  this.currentSegment = null;
743
835
  this.futureSegments = [];
744
836
  this.currentPointIndex = 0;
745
837
  this.segmentCounter = 0;
838
+ this.historyTrailPositions = [];
839
+ this.trailDataUpdated = false;
840
+ this.trailShowState = true;
746
841
  }
747
842
  }]);
748
843
  return ModelRoamRealTime;
@@ -353,10 +353,11 @@ export var DEFAULT_POLYLINE_TRAIL_LINK_MATERIAL_STYLE = function DEFAULT_POLYLIN
353
353
  mixRatio: 0.5,
354
354
  duration: 2,
355
355
  count: 3,
356
+ repeat: [1, 1],
357
+ repeatPixel: 1000,
356
358
  image: utils.getDeepTwinsFile('Image/line.png')
357
359
  };
358
360
  };
359
-
360
361
  // 动态墙材质默认的配置
361
362
  export var DEFAULT_DYNAMIC_WALL_MATERIAL_STYLE = function DEFAULT_DYNAMIC_WALL_MATERIAL_STYLE() {
362
363
  return {