roaming.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /* 漫游类 */
  2. class Roaming {
  3. /**
  4. * Creates an instance of Roaming.
  5. * @param {*} viewer 需要传入
  6. * @param {*} options.model 模型的相关配置 需要传入
  7. * @param {*} options.data 点集合 需要传入
  8. * @param {*} options.isPathShow 路径是否显示 默认显示
  9. * @memberof Roaming
  10. * @example
  11. * const options = {
  12. data: '', // 直接点数据(经纬度或笛卡尔)
  13. model: {
  14. url: ''// 和SuperMap3D中model的配置一致
  15. },
  16. speed: '', // 移动速度默认10m/s,默认可不传
  17. isPathShow: true, // 漫游路径是否显示, 默认可不传
  18. offset: new SuperMap3D.Cartesian3(-25, 0, 10), // 相机视角偏移,默认可不传
  19. perspectiveMode: 'NO', //视角类型 默认无,NO TRACK FIRST GOD ,默认可不传
  20. isInterpolation: false , //是否插值 ,用于飞行路线平滑曲线 ,默认可不传
  21. };
  22. */
  23. constructor(viewer, options) {
  24. this.viewer = viewer;
  25. this.updateOptionsParams(options);
  26. this.isPathShow = true;
  27. this.isInterpolation = false;
  28. this.perspectiveMode = 'NO';
  29. this.offset = new SuperMap3D.Cartesian3(-25, 0, 5);
  30. this.multiplier = options.multiplier || 10;
  31. this.speed = options.speed || 10;
  32. this.entity = undefined;
  33. this.start = undefined;
  34. this.stop = undefined;
  35. this.matrix3Scratch = new SuperMap3D.Matrix3();
  36. this.scratch = new SuperMap3D.Matrix4();
  37. }
  38. /**
  39. * 更新漫游可配置的内部参数
  40. * @param {object} options 漫游的配置项
  41. */
  42. updateOptionsParams(options) {
  43. if (SuperMap3D.defined(options.data)) this.data = options.data;
  44. if (SuperMap3D.defined(options.model)) this.model = options.model || {};
  45. if (SuperMap3D.defined(options.speed)) this.speed = options.speed;
  46. if (SuperMap3D.defined(options.isPathShow)) this.isPathShow = options.isPathShow;
  47. if (SuperMap3D.defined(options.isInterpolation)) this.isInterpolation = options.isInterpolation;
  48. if (SuperMap3D.defined(options.offset)) this.offset = options.offset;
  49. if (SuperMap3D.defined(options.perspectiveMode)) this.perspectiveMode = options.perspectiveMode;
  50. if (SuperMap3D.defined(options.multiplier)) this.multiplier = options.multiplier;
  51. }
  52. /**
  53. * 处理读取到的数据
  54. * @param {array} data
  55. */
  56. processData(data) {
  57. if (SuperMap3D.defined(data[0].x)) return data;
  58. const positions = [];
  59. data.forEach((position) => {
  60. const car3Position = SuperMap3D.Cartesian3.fromDegrees(position[0], position[1], position[2]); // 给定默认值
  61. positions.push(car3Position);
  62. });
  63. return positions;
  64. }
  65. /**
  66. * 创建漫游
  67. * @param {array} data
  68. * @memberof Roaming
  69. */
  70. createRoaming() {
  71. if (this.data && Array.isArray(this.data)) {
  72. // 加载路径数据
  73. const positions = this.processData(this.data);
  74. // 根据基础路径生成漫游路线
  75. this.property = this.computeRoamingLineProperty(positions);
  76. this.createEntity(this.property, this.start, this.stop, this.isPathShow);
  77. }
  78. }
  79. /**
  80. * 创建位置集合
  81. * @param {cartesian3} coordinates 点集合
  82. * @returns
  83. */
  84. computeRoamingLineProperty(coordinates) {
  85. const property = new SuperMap3D.SampledPositionProperty();
  86. const coordinatesLength = coordinates.length;
  87. const start = SuperMap3D.JulianDate.now();
  88. this.start = start;
  89. let stopTime = 0;
  90. property.addSample(start, coordinates[0]);
  91. for (let i = 1; i < coordinatesLength; i += 1) {
  92. let d = SuperMap3D.Cartesian3.distance(coordinates[i], coordinates[i - 1]);
  93. stopTime += d / this.speed;
  94. const time1 = SuperMap3D.JulianDate.addSeconds(start, stopTime, new SuperMap3D.JulianDate());
  95. const position = coordinates[i];
  96. property.addSample(time1, position);
  97. }
  98. const stop = SuperMap3D.JulianDate.addSeconds(start, stopTime, new SuperMap3D.JulianDate());
  99. this.stop = stop;
  100. this.setClockTime(start, stop, this.multiplier);
  101. if (this.isInterpolation) {
  102. property.setInterpolationOptions({ // 点插值
  103. interpolationDegree: 5,
  104. interpolationAlgorithm: SuperMap3D.LagrangePolynomialApproximation, //LagrangePolynomialApproximation LinearApproximation HermitePolynomialApproximation
  105. });
  106. }
  107. return property;
  108. }
  109. /**
  110. * 设置漫游时间系统
  111. * @param {*} start
  112. * @param {*} stop
  113. * @param {*} multiplier
  114. * @memberof Roaming
  115. */
  116. setClockTime(start, stop, multiplier) {
  117. // 将当前日期转为JulianDate
  118. this.viewer.clock.startTime = start.clone();
  119. this.viewer.clock.stopTime = stop.clone();
  120. this.viewer.clock.currentTime = start.clone();
  121. this.viewer.clock.multiplier = multiplier;
  122. // 默认循环漫游
  123. this.viewer.clock.clockRange = SuperMap3D.ClockRange.LOOP_STOP;
  124. // 时钟在此模式下前进的间隔当前间隔乘以某个系数
  125. this.viewer.clock.clockStep = SuperMap3D.ClockStep.SYSTEM_CLOCK_MULTIPLIER;
  126. }
  127. /**
  128. * 创建entity
  129. * @param {*} position computeRoamingLineProperty计算的属性
  130. * @param {*} start 开始时间节点
  131. * @param {*} stop 结束时间节点
  132. * @param {*} isPathShow path路径是否显示
  133. * @memberof Roaming
  134. */
  135. createEntity(position, start, stop, isPathShow) {
  136. this.entity = this.viewer.entities.add({
  137. availability: new SuperMap3D.TimeIntervalCollection([new SuperMap3D.TimeInterval({
  138. start,
  139. stop,
  140. })]),
  141. // 位置
  142. position,
  143. // 计算朝向
  144. orientation: new SuperMap3D.VelocityOrientationProperty(position),
  145. // 加载模型
  146. model: { // 模型路径
  147. uri: this.model.url,
  148. // 模型最小刻度
  149. minimumPixelSize: 64,
  150. maximumSize: 128,
  151. // 设置模型最大放大大小
  152. maximumScale: 200,
  153. // 模型是否可见
  154. show: true,
  155. // 模型轮廓颜色
  156. silhouetteColor: SuperMap3D.Color.WHITE,
  157. // 模型颜色 ,这里可以设置颜色的变化
  158. // color: color,
  159. // 仅用于调试,显示模型绘制时的线框
  160. debugWireframe: false,
  161. // 仅用于调试。显示模型绘制时的边界球。
  162. debugShowBoundingVolume: false,
  163. scale: 1,
  164. runAnimations: true, // 是否运行模型中的动画效果
  165. ...this.model,
  166. },
  167. path: {
  168. resolution: 0.1,
  169. material: new SuperMap3D.PolylineGlowMaterialProperty({
  170. glowPower: 0.1,
  171. color: SuperMap3D.Color.YELLOW,
  172. }),
  173. width: 10,
  174. show: isPathShow,
  175. },
  176. });
  177. this.setPerspective(this.perspectiveMode);
  178. }
  179. /**
  180. * 设置漫游路径是否可见
  181. * @param {boolean} visible
  182. * @memberof Roaming
  183. */
  184. setRoamingPathVisibility(visible) {
  185. if (this.entity) {
  186. this.entity.path.show = visible;
  187. }
  188. // 更新全局漫游路径是否可见参数
  189. this.isPathShow = visible;
  190. }
  191. /**
  192. * 设置漫游模型是否可见
  193. * @param {boolean} visible
  194. * @memberof Roaming
  195. */
  196. setRoamingModelVisibility(visible) {
  197. if (this.entity) {
  198. this.entity.model.show = visible;
  199. }
  200. }
  201. /**
  202. * 设置相机位置
  203. * @param {cartesian3} position
  204. * @param {cartesian4} orientation
  205. * @memberof Roaming
  206. */
  207. setCameraPosition(position, orientation) {
  208. if (!SuperMap3D.defined(position)) {
  209. return undefined;
  210. }
  211. if (!SuperMap3D.defined(orientation)) {
  212. this.scratch = SuperMap3D.Transforms.eastNorthUpToFixedFrame(position, undefined, this.scratch);
  213. } else {
  214. this.scratch = SuperMap3D.Matrix4.fromRotationTranslation(SuperMap3D.Matrix3.fromQuaternion(orientation, this.matrix3Scratch), position, this.scratch);
  215. }
  216. this.viewer.scene.camera.lookAtTransform(this.scratch, this.offset); // 修改相机
  217. }
  218. /**
  219. * 监听场景渲染事件
  220. * @param callback
  221. */
  222. addSceneEvent(callback) {
  223. // addEventListener() → Event.RemoveCallback
  224. // 监听之前先销毁
  225. if (this.handler instanceof Function) {
  226. this.handler();
  227. this.handler = null;
  228. }
  229. this.handler = this.viewer.scene.preRender.addEventListener((scene, time) => {
  230. callback(time);
  231. });
  232. }
  233. /**
  234. * 根据时刻获取漫游位置
  235. * @param {object} time
  236. * @memberof Roaming
  237. */
  238. getRoamingPosition(time) {
  239. if (this.entity) {
  240. const position = this.entity.position.getValue(time);
  241. const orientation = this.entity.orientation.getValue(time);
  242. this.setCameraPosition(position, orientation);
  243. }
  244. }
  245. /**
  246. * 漫游的暂停和继续
  247. * @param {boolean} state false为暂停,ture为继续
  248. */
  249. pauseOrContinue(state) {
  250. if (state) {
  251. // 继续播放
  252. if (!this.handler && this.entity) {
  253. this.setPerspective(this.perspectiveMode)
  254. }
  255. } else if (this.handler) {
  256. // 停止监听屏幕绘制事件(停止相机变化)
  257. this.handler();
  258. this.handler = null;
  259. // 解锁相机视角
  260. this.viewer.camera.lookAtTransform(SuperMap3D.Matrix4.IDENTITY);
  261. }
  262. this.viewer.clock.shouldAnimate = state;
  263. }
  264. /**
  265. * 改变飞行的速度
  266. * @param {*} value 整数类型
  267. */
  268. changeRoamingSpeed(value) {
  269. this.multiplier = value;
  270. this.viewer.clock.multiplier = value;
  271. }
  272. /**
  273. * 设置视角
  274. * @param {*} value 字符串类型 NO TRACK FIRST GOD
  275. */
  276. setPerspective(value) {
  277. this.perspectiveMode = value;
  278. this.removePerspective();
  279. switch (value) {
  280. case "NO":
  281. break;
  282. case "TRACK":
  283. this.viewer.trackedEntity = this.entity;
  284. break;
  285. case "FIRST":
  286. this.offset = new SuperMap3D.Cartesian3(-25, 0, 5);
  287. this.addSceneEvent((time) => {
  288. this.getRoamingPosition(time);
  289. });
  290. break;
  291. case "GOD":
  292. this.offset = new SuperMap3D.Cartesian3(-25, 0, 50);
  293. this.addSceneEvent((time) => {
  294. this.getRoamingPosition(time);
  295. });
  296. break;
  297. default:
  298. break;
  299. }
  300. }
  301. /**
  302. * 清除视角
  303. */
  304. removePerspective() {
  305. this.viewer.trackedEntity = undefined;
  306. if (this.handler) {
  307. this.handler();
  308. this.handler = null;
  309. }
  310. this.viewer.camera.lookAtTransform(SuperMap3D.Matrix4.IDENTITY);
  311. }
  312. /**
  313. * 移除漫游
  314. */
  315. removeRoaming() {
  316. if (this.entity !== undefined) {
  317. if (this.handler instanceof Function) {
  318. this.handler();
  319. this.handler = null;
  320. }
  321. // 清空实体
  322. this.viewer.entities.remove(this.entity);
  323. // 清空内部数据
  324. this.data = null;
  325. // 解锁相机视角
  326. this.viewer.camera.lookAtTransform(SuperMap3D.Matrix4.IDENTITY);
  327. this.entity = null;
  328. }
  329. }
  330. }
  331. window.Roaming = Roaming