layerManagement.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. import { actions, storeDate } from '../store/store.js' //局部状态管理
  2. // 添加s3m
  3. function addS3mLayers(scps, callback) {
  4. let promiseArray = [];
  5. try {
  6. if (scps) {
  7. scps.forEach(scp => {
  8. promiseArray.push(
  9. viewer.scene.addS3MTilesLayerByScp(scp.url, scp.options)
  10. );
  11. });
  12. }
  13. promiseWhen(promiseArray, callback, 'S3M')
  14. } catch (e) {
  15. let widget = viewer.cesiumWidget;
  16. if (widget._showRenderLoopErrors) {
  17. let title = "渲染时发生错误,已停止渲染。";
  18. widget.showErrorPanel(title, undefined, e);
  19. }
  20. }
  21. };
  22. // 添加场景
  23. function addScene(url, options, callback) {
  24. if (options && options.SceneToken) {
  25. Cesium.Credential.CREDENTIAL = new Cesium.Credential(options.SceneToken);
  26. }
  27. let flag = true;
  28. if (options && options.autoSetView !== undefined) {
  29. flag = options.autoSetView
  30. }
  31. if (checkURL(url)) {
  32. try {
  33. let s = [viewer.scene.open(url, undefined, { 'autoSetView': flag })];
  34. promiseWhen(s, callback, 'SCENE');
  35. } catch (e) {
  36. let widget = viewer.cesiumWidget;
  37. if (widget._showRenderLoopErrors) {
  38. let title = "渲染时发生错误,已停止渲染。";
  39. widget.showErrorPanel(title, undefined, e);
  40. }
  41. }
  42. }
  43. };
  44. // 添加地形
  45. function addTerrainLayer(LayerURL, isSct) {
  46. try {
  47. const terrainProvider = new Cesium.CesiumTerrainProvider({
  48. url: LayerURL,
  49. isSct: isSct,
  50. });
  51. viewer.terrainProvider = terrainProvider;
  52. return terrainProvider;
  53. } catch (e) {
  54. let widget = viewer.cesiumWidget;
  55. if (widget._showRenderLoopErrors) {
  56. let title = "渲染时发生错误,已停止渲染。";
  57. widget.showErrorPanel(title, undefined, e);
  58. }
  59. return null;
  60. }
  61. };
  62. // ======================= ✅ 已修复:万能自动坐标系转换 =======================
  63. function addImageLayer(LayerURL, layerName) {
  64. try {
  65. let url = LayerURL;
  66. let mapName = '';
  67. // 清理URL参数,不手动解析投影
  68. if (LayerURL.includes('prjCoordSys')) {
  69. try {
  70. const urlObj = new URL(LayerURL);
  71. url = urlObj.origin + urlObj.pathname;
  72. } catch (e) {
  73. console.warn('解析URL失败:', e);
  74. }
  75. }
  76. // 提取地图名称
  77. if (url.includes('/maps/')) {
  78. const mapsIndex = url.lastIndexOf('/maps/');
  79. mapName = url.substring(mapsIndex + 6);
  80. }
  81. let options = {
  82. url: url,
  83. };
  84. if (mapName) {
  85. options.name = mapName;
  86. }
  87. // ✅ 核心:自动将任意坐标系 → 输出 WGS84
  88. options.outputPrjCoordSys = {
  89. epsgCode: 4326,
  90. name: "WGS 84",
  91. type: "EPSG",
  92. coordinateSystemType: "GEODETIC"
  93. };
  94. // ✅ 不手动指定原投影,不硬编码范围,交给超图自动处理
  95. let layer = viewer.imageryLayers.addImageryProvider(
  96. new Cesium.SuperMapImageryProvider(options)
  97. );
  98. viewer.imageryLayers.raiseToTop(layer);
  99. layer.show = true;
  100. layer._loadedUrl = LayerURL;
  101. layer._loadedLayerName = layerName || '';
  102. // 自动定位到图层范围
  103. checkLayerExtentAndAdjust(layer);
  104. return layer;
  105. } catch (e) {
  106. console.error('加载影像图层失败:', e);
  107. let widget = viewer.cesiumWidget;
  108. if (widget._showRenderLoopErrors) {
  109. let title = "渲染时发生错误,已停止渲染。";
  110. widget.showErrorPanel(title, undefined, e);
  111. }
  112. }
  113. };
  114. // 检查图层范围并自动定位
  115. function checkLayerExtentAndAdjust(layer) {
  116. try {
  117. const provider = layer.imageryProvider;
  118. Cesium.when(provider.readyPromise, function () {
  119. const rectangle = provider.rectangle;
  120. if (rectangle) {
  121. const west = Cesium.Math.toDegrees(rectangle.west);
  122. const south = Cesium.Math.toDegrees(rectangle.south);
  123. const east = Cesium.Math.toDegrees(rectangle.east);
  124. const north = Cesium.Math.toDegrees(rectangle.north);
  125. console.log('图层真实范围:', { west, south, east, north });
  126. // 范围无效时飞到中国区域
  127. const isInvalidExtent = (south < -90 || north > 90) ||
  128. (south > north) || (west > east);
  129. if (isInvalidExtent) {
  130. console.warn('范围无效,自动定位到中国区域');
  131. flyToChinaRegion();
  132. } else {
  133. // 有效范围 → 自动定位到图层
  134. viewer.flyTo(layer, { duration: 1.5 });
  135. }
  136. }
  137. });
  138. } catch (e) {
  139. console.error('检查图层范围失败:', e);
  140. }
  141. }
  142. // 定位到中国
  143. function flyToChinaRegion() {
  144. viewer.scene.camera.flyTo({
  145. destination: Cesium.Cartesian3.fromDegrees(104.0, 35.0, 4000000),
  146. duration: 2,
  147. orientation: { heading: 0, pitch: -60, roll: 0 }
  148. });
  149. }
  150. // 添加mvt
  151. function addMvtLayer(LayerURL, name, callback) {
  152. try {
  153. let mvtMap = viewer.scene.addVectorTilesMap({
  154. url: LayerURL,
  155. canvasWidth: 512,
  156. name: name || 'mvt',
  157. viewer: viewer
  158. });
  159. Cesium.when(mvtMap.readyPromise, function (data) {
  160. var bounds = mvtMap.rectangle;
  161. viewer.scene.camera.flyTo({
  162. destination: new Cesium.Cartesian3.fromRadians(
  163. (bounds.east + bounds.west) * 0.5,
  164. (bounds.north + bounds.south) * 0.5,
  165. 10000
  166. ),
  167. duration: 0,
  168. orientation: { heading: 0, roll: 0 }
  169. });
  170. actions.setChangeLayers();
  171. callback(mvtMap)
  172. });
  173. return mvtMap
  174. } catch (e) {
  175. let widget = viewer.cesiumWidget;
  176. if (widget._showRenderLoopErrors) {
  177. let title = "渲染时发生错误,已停止渲染。";
  178. widget.showErrorPanel(title, undefined, e);
  179. }
  180. }
  181. };
  182. // 加载GeoJson图层
  183. function addGeoJsonLayer(url, name, callback) {
  184. try {
  185. // 判断是否为超图REST数据服务
  186. if (url.includes('/iserver/services/') && url.includes('/rest/data/datasources')) {
  187. loadSuperMapRestDataService(url, name, callback);
  188. return;
  189. }
  190. const loadPromise = Cesium.GeoJsonDataSource.load(url, {
  191. stroke: Cesium.Color.fromCssColorString('#0055FF').withAlpha(1),
  192. fill: Cesium.Color.fromCssColorString('#00FF00').withAlpha(0.4),
  193. strokeWidth: 3,
  194. clampToGround: true
  195. });
  196. Cesium.when(loadPromise, function (dataSource) {
  197. viewer.dataSources.add(dataSource);
  198. processGeoJsonEntities(dataSource, name);
  199. viewer.flyTo(dataSource, { duration: 2 });
  200. actions.setChangeLayers();
  201. if (callback) callback(dataSource);
  202. }, function (error) {
  203. console.error("加载GeoJSON失败:", error);
  204. });
  205. } catch (e) {
  206. console.error("加载GeoJSON异常:", e);
  207. }
  208. };
  209. // 从超图REST服务获取要素并转换为标准GeoJSON
  210. function fetchFeaturesFromSuperMap(url, timeout) {
  211. const timeoutPromise = new Promise((_, reject) => {
  212. setTimeout(() => reject(new Error('请求超时')), timeout);
  213. });
  214. return Promise.race([
  215. fetch(url, { timeout: timeout }),
  216. timeoutPromise
  217. ])
  218. .then(response => {
  219. if (!response.ok) {
  220. throw new Error(`HTTP错误: ${response.status}`);
  221. }
  222. return response.text();
  223. })
  224. .then(text => {
  225. try {
  226. return JSON.parse(text);
  227. } catch (e) {
  228. console.error('JSON解析失败:', text.substring(0, 200));
  229. throw new Error('服务返回的不是有效的JSON数据');
  230. }
  231. })
  232. .then(superMapData => {
  233. // 超图返回的格式是: { features: [...], totalCount: N, ... }
  234. // 需要转换为标准GeoJSON格式: { type: 'FeatureCollection', features: [...] }
  235. // 调试:查看完整返回数据结构
  236. console.log('超图服务返回的数据:', JSON.stringify(superMapData, null, 2).substring(0, 2000));
  237. console.log('数据类型:', typeof superMapData);
  238. console.log('数据键:', Object.keys(superMapData || {}));
  239. let features = [];
  240. // 尝试多种可能的数据结构
  241. if (superMapData.features && Array.isArray(superMapData.features)) {
  242. features = superMapData.features;
  243. console.log('从 features 属性获取要素');
  244. } else if (superMapData.recordset && Array.isArray(superMapData.recordset)) {
  245. features = superMapData.recordset;
  246. console.log('从 recordset 属性获取要素');
  247. } else if (superMapData.result && superMapData.result.features && Array.isArray(superMapData.result.features)) {
  248. features = superMapData.result.features;
  249. console.log('从 result.features 属性获取要素');
  250. } else if (Array.isArray(superMapData)) {
  251. features = superMapData;
  252. console.log('数据本身是数组');
  253. } else {
  254. console.warn('未找到要素数据,尝试查找其他属性');
  255. // 遍历所有属性查找数组
  256. for (const key of Object.keys(superMapData || {})) {
  257. if (Array.isArray(superMapData[key])) {
  258. console.log(`发现数组属性 ${key},长度:`, superMapData[key].length);
  259. if (superMapData[key].length > 0 && superMapData[key][0].geometry) {
  260. features = superMapData[key];
  261. console.log(`使用 ${key} 作为要素数组`);
  262. break;
  263. }
  264. }
  265. }
  266. }
  267. // 转换每个要素的坐标格式(超图可能返回平面坐标,需要转换为经纬度)
  268. console.log('原始要素数量:', features.length);
  269. if (features.length > 0) {
  270. console.log('第一个要素示例:', JSON.stringify(features[0], null, 2).substring(0, 1000));
  271. }
  272. features = features.map((feature, index) => {
  273. if (!feature) {
  274. console.warn(`要素 ${index} 为空`);
  275. return null;
  276. }
  277. if (!feature.geometry) {
  278. console.warn(`要素 ${index} 没有geometry`);
  279. return null;
  280. }
  281. if (!feature.geometry.coordinates) {
  282. console.warn(`要素 ${index} 没有coordinates`);
  283. return null;
  284. }
  285. // 尝试转换坐标
  286. try {
  287. feature.geometry.coordinates = convertCoordinates(feature.geometry.coordinates);
  288. return feature;
  289. } catch (e) {
  290. console.error(`要素 ${index} 坐标转换失败:`, e);
  291. return null;
  292. }
  293. }).filter(Boolean);
  294. console.log('转换后的要素数量:', features.length);
  295. // 返回标准GeoJSON FeatureCollection
  296. return {
  297. type: 'FeatureCollection',
  298. features: features
  299. };
  300. });
  301. }
  302. // 坐标转换:尝试将平面坐标转换为经纬度
  303. function convertCoordinates(coordinates) {
  304. if (!Array.isArray(coordinates)) {
  305. return coordinates;
  306. }
  307. // 检查是否是经纬度范围(-180到180,-90到90)
  308. const isLatLng = (coord) => {
  309. return Math.abs(coord[0]) <= 180 && Math.abs(coord[1]) <= 90;
  310. };
  311. // 检查是否是Web Mercator或其他大坐标值
  312. const isLargeCoord = (coord) => {
  313. return Math.abs(coord[0]) > 10000 || Math.abs(coord[1]) > 10000;
  314. };
  315. // 处理点坐标
  316. if (coordinates.length >= 2 && typeof coordinates[0] === 'number') {
  317. if (isLargeCoord(coordinates)) {
  318. console.log('检测到大坐标值,尝试Web Mercator转WGS84:', coordinates);
  319. try {
  320. const cartesian3 = Cesium.Cartesian3.fromArray(coordinates);
  321. const cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
  322. return [
  323. Cesium.Math.toDegrees(cartographic.longitude),
  324. Cesium.Math.toDegrees(cartographic.latitude),
  325. cartographic.height || 0
  326. ];
  327. } catch (e) {
  328. console.warn('坐标转换失败:', e);
  329. return coordinates;
  330. }
  331. }
  332. return coordinates;
  333. }
  334. // 处理线坐标(二维数组)
  335. if (coordinates.length > 0 && Array.isArray(coordinates[0])) {
  336. return coordinates.map(coord => convertCoordinates(coord));
  337. }
  338. // 处理多边形坐标(三维数组)
  339. if (coordinates.length > 0 && Array.isArray(coordinates[0][0])) {
  340. return coordinates.map(ring => ring.map(coord => convertCoordinates(coord)));
  341. }
  342. return coordinates;
  343. }
  344. // 加载超图REST数据服务
  345. function loadSuperMapRestDataService(baseUrl, name, callback) {
  346. console.log('开始加载超图REST数据服务:', baseUrl);
  347. // 设置超时时间
  348. const timeout = 30000; // 30秒
  349. // 创建超时Promise
  350. const timeoutPromise = new Promise((_, reject) => {
  351. setTimeout(() => reject(new Error('请求超时')), timeout);
  352. });
  353. // 修正URL:添加.json后缀(如果缺少的话)
  354. let datasourcesUrl = baseUrl;
  355. if (!datasourcesUrl.endsWith('.json')) {
  356. datasourcesUrl = `${baseUrl}.json`;
  357. }
  358. console.log('修正后的数据源URL:', datasourcesUrl);
  359. // 获取数据源列表
  360. Promise.race([
  361. fetch(datasourcesUrl, { timeout: timeout }),
  362. timeoutPromise
  363. ])
  364. .then(response => {
  365. if (!response.ok) {
  366. // 如果.json后缀失败,尝试不加后缀
  367. if (datasourcesUrl !== baseUrl) {
  368. console.log(`HTTP错误: ${response.status},尝试不加.json后缀`);
  369. return fetch(baseUrl, { timeout: timeout });
  370. }
  371. throw new Error(`HTTP错误: ${response.status}`);
  372. }
  373. return response;
  374. })
  375. .then(response => {
  376. if (!response.ok) {
  377. throw new Error(`HTTP错误: ${response.status}`);
  378. }
  379. return response.text();
  380. })
  381. .then(text => {
  382. // 尝试解析JSON
  383. try {
  384. return JSON.parse(text);
  385. } catch (e) {
  386. // 如果JSON解析失败,检查是否是HTML错误页面
  387. console.error('JSON解析失败,响应内容:', text.substring(0, 200));
  388. throw new Error('服务返回的不是有效的JSON数据');
  389. }
  390. })
  391. .then(dataSources => {
  392. console.log('获取到数据源列表:', dataSources);
  393. // 处理超图REST数据服务返回的格式
  394. // 超图返回的格式是: { datasourceNames: [...], childUriList: [...], datasourceCount: N }
  395. let dataSourceNames = [];
  396. if (Array.isArray(dataSources)) {
  397. // 如果返回的是数组,直接使用
  398. dataSourceNames = dataSources.map(ds => ds.name || ds);
  399. } else if (dataSources && dataSources.datasourceNames && Array.isArray(dataSources.datasourceNames)) {
  400. // 超图REST数据服务格式
  401. dataSourceNames = dataSources.datasourceNames;
  402. }
  403. if (!dataSourceNames || dataSourceNames.length === 0) {
  404. console.warn('未找到数据源');
  405. if (callback) callback(null);
  406. return;
  407. }
  408. // 遍历所有数据源
  409. const loadPromises = [];
  410. dataSourceNames.forEach(dataSourceName => {
  411. // 确保数据源名称是字符串
  412. const name = typeof dataSourceName === 'object' ? (dataSourceName.name || dataSourceName) : dataSourceName;
  413. let datasetsUrl = `${baseUrl}/${encodeURIComponent(name)}/datasets`;
  414. if (!datasetsUrl.endsWith('.json')) {
  415. datasetsUrl += '.json';
  416. }
  417. // 获取数据集列表
  418. const datasetPromise = Promise.race([
  419. fetch(datasetsUrl, { timeout: timeout }),
  420. timeoutPromise
  421. ])
  422. .then(response => {
  423. if (!response.ok) {
  424. if (datasetsUrl !== `${baseUrl}/${encodeURIComponent(name)}/datasets`) {
  425. return fetch(`${baseUrl}/${encodeURIComponent(name)}/datasets`, { timeout: timeout });
  426. }
  427. throw new Error(`HTTP错误: ${response.status}`);
  428. }
  429. return response;
  430. })
  431. .then(response => {
  432. if (!response.ok) {
  433. throw new Error(`HTTP错误: ${response.status}`);
  434. }
  435. return response.text();
  436. })
  437. .then(text => {
  438. try {
  439. return JSON.parse(text);
  440. } catch (e) {
  441. console.error(`数据集列表JSON解析失败 (${name}):`, text.substring(0, 200));
  442. throw new Error('数据集列表不是有效的JSON');
  443. }
  444. })
  445. .then(datasets => {
  446. console.log(`数据源 ${name} 的数据集列表:`, datasets);
  447. // 处理数据集格式
  448. let datasetNames = [];
  449. if (Array.isArray(datasets)) {
  450. datasetNames = datasets.map(ds => ds.name || ds);
  451. } else if (datasets && datasets.datasetNames && Array.isArray(datasets.datasetNames)) {
  452. datasetNames = datasets.datasetNames;
  453. }
  454. if (!datasetNames || datasetNames.length === 0) {
  455. return Promise.resolve([]);
  456. }
  457. // 加载每个数据集的要素(限制同时加载的数量)
  458. const featurePromises = [];
  459. const maxConcurrent = 3; // 最大并发数
  460. for (let i = 0; i < datasetNames.length; i += maxConcurrent) {
  461. const batch = datasetNames.slice(i, i + maxConcurrent);
  462. const batchPromises = batch.map(dsName => {
  463. // 确保数据集名称是字符串
  464. const datasetName = typeof dsName === 'object' ? (dsName.name || dsName) : dsName;
  465. let featuresUrl = `${baseUrl}/${encodeURIComponent(name)}/datasets/${encodeURIComponent(datasetName)}/features.json?returnContent=true`;
  466. console.log('加载要素URL:', featuresUrl);
  467. // 先获取超图格式的要素数据,转换为标准GeoJSON后再加载
  468. return fetchFeaturesFromSuperMap(featuresUrl, timeout)
  469. .then(geoJsonData => {
  470. if (!geoJsonData) {
  471. throw new Error('未获取到有效要素数据');
  472. }
  473. // 使用Cesium加载GeoJSON
  474. return Cesium.GeoJsonDataSource.load(geoJsonData, {
  475. stroke: Cesium.Color.fromCssColorString('#0055FF').withAlpha(1),
  476. fill: Cesium.Color.fromCssColorString('#00FF00').withAlpha(0.4),
  477. strokeWidth: 3,
  478. clampToGround: true
  479. });
  480. })
  481. .then(geoJsonDataSource => {
  482. viewer.dataSources.add(geoJsonDataSource);
  483. processGeoJsonEntities(geoJsonDataSource, `${name}-${datasetName}`);
  484. return geoJsonDataSource;
  485. })
  486. .catch(error => {
  487. console.error(`加载数据集 ${datasetName} 失败:`, error);
  488. return null;
  489. });
  490. });
  491. featurePromises.push(Promise.all(batchPromises));
  492. }
  493. return Promise.all(featurePromises).then(results => results.flat());
  494. })
  495. .catch(error => {
  496. console.error(`获取数据集列表失败 (${name}):`, error);
  497. return [];
  498. });
  499. loadPromises.push(datasetPromise);
  500. });
  501. Promise.all(loadPromises)
  502. .then(results => {
  503. const allDataSources = results.flat().filter(Boolean);
  504. console.log('所有加载的GeoJSON数据源:', allDataSources);
  505. if (allDataSources.length > 0) {
  506. viewer.flyTo(allDataSources[0], { duration: 2 });
  507. }
  508. actions.setChangeLayers();
  509. if (callback) callback(allDataSources.length > 0 ? allDataSources : null);
  510. })
  511. .catch(error => {
  512. console.error('加载超图REST数据服务失败:', error);
  513. if (callback) callback(null);
  514. });
  515. })
  516. .catch(error => {
  517. console.error('获取数据源列表失败:', error);
  518. if (callback) callback(null);
  519. });
  520. }
  521. // 处理GeoJSON实体(异步方式,避免阻塞主线程)
  522. function processGeoJsonEntities(dataSource, name) {
  523. try {
  524. let entities = dataSource.entities.values;
  525. let entitiesLength = entities.length;
  526. // 限制处理的实体数量,防止大量数据导致卡死
  527. const maxEntities = 5000;
  528. if (entitiesLength > maxEntities) {
  529. console.warn(`实体数量过多(${entitiesLength}),仅处理前${maxEntities}个`);
  530. entitiesLength = maxEntities;
  531. }
  532. // 使用异步批量处理
  533. const batchSize = 50; // 每批处理50个实体
  534. let currentIndex = 0;
  535. const processBatch = () => {
  536. if (currentIndex >= entitiesLength) {
  537. return; // 处理完成
  538. }
  539. const endIndex = Math.min(currentIndex + batchSize, entitiesLength);
  540. for (let i = currentIndex; i < endIndex; i++) {
  541. let entity = entities[i];
  542. if (!entity) continue;
  543. entity.name = name || 'GeoJSON';
  544. if (entity.polygon) {
  545. entity.polygon.fill = true;
  546. entity.polygon.outline = true;
  547. entity.polygon.clampToGround = true;
  548. entity.polygon.arcType = Cesium.ArcType.GEODESIC;
  549. entity.polygon.perPositionHeight = false;
  550. entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
  551. entity.polygon.disableDepthTestDistance = Number.POSITIVE_INFINITY;
  552. entity.polygon.material = Cesium.Color.fromCssColorString('#00FF00').withAlpha(0.4);
  553. entity.polygon.outlineColor = Cesium.Color.fromCssColorString('#0055FF');
  554. entity.polygon.outlineWidth = 4;
  555. }
  556. if (entity.polyline) {
  557. entity.polyline.clampToGround = true;
  558. entity.polyline.classificationType = Cesium.ClassificationType.TERRAIN;
  559. entity.polyline.material = Cesium.Color.fromCssColorString('#0055FF');
  560. entity.polyline.width = 4;
  561. }
  562. if (entity.point) {
  563. entity.point.clampToGround = true;
  564. entity.point.color = Cesium.Color.fromCssColorString('#FF0000');
  565. entity.point.pixelSize = 10;
  566. entity.point.outlineColor = Cesium.Color.fromCssColorString('#FFFFFF');
  567. entity.point.outlineWidth = 2;
  568. entity.point.disableDepthTestDistance = Number.POSITIVE_INFINITY;
  569. entity.isGeoJsonPoint = true;
  570. }
  571. if (entity.billboard) {
  572. entity.billboard.show = false;
  573. entity.point = {
  574. color: Cesium.Color.fromCssColorString('#FF0000'),
  575. pixelSize: 10,
  576. outlineColor: Cesium.Color.fromCssColorString('#FFFFFF'),
  577. outlineWidth: 2,
  578. clampToGround: true,
  579. disableDepthTestDistance: Number.POSITIVE_INFINITY
  580. };
  581. entity.isGeoJsonPoint = true;
  582. }
  583. }
  584. currentIndex = endIndex;
  585. // 使用 requestAnimationFrame 让出主线程给渲染
  586. requestAnimationFrame(processBatch);
  587. };
  588. // 开始处理
  589. processBatch();
  590. } catch (error) {
  591. console.error('处理GeoJSON实体失败:', error);
  592. }
  593. }
  594. // 加载s3m和场景
  595. function promiseWhen(promiseArray, callback, type) {
  596. Cesium.when.all(
  597. promiseArray,
  598. function (layers) {
  599. storeDate.layers = viewer.scene.layers.layerQueue;
  600. actions.setChangeLayers();
  601. callback(layers, type);
  602. storeDate.layers.forEach((s3mlayer) => {
  603. if (!s3mlayer.visibleDistanceMax || s3mlayer.visibleDistanceMax > 12000) {
  604. s3mlayer.visibleDistanceMax = 12000
  605. }
  606. })
  607. },
  608. function (e) {
  609. let widget = viewer.cesiumWidget;
  610. if (widget._showRenderLoopErrors) {
  611. let title = '请检查url地址是否正确?';
  612. widget.showErrorPanel(title, undefined, e);
  613. }
  614. }
  615. );
  616. };
  617. // 检验url
  618. function checkURL(url) {
  619. if (url === null || url === "") {
  620. return false;
  621. }
  622. if (url.charAt(0) == '"' || url.charAt(0) == "'") {
  623. let reg = /^['|"](.*)['|"]$/;
  624. url = url.replace(reg, "$1");
  625. }
  626. return true
  627. };
  628. // 删除图层
  629. function layersDelete(type, id_name, callback) {
  630. switch (type) {
  631. case "SCENE":
  632. if (viewer.scene.layers && viewer.scene.layers.layerQueue) {
  633. const layers = viewer.scene.layers.layerQueue;
  634. for (let i = layers.length - 1; i >= 0; i--) {
  635. viewer.scene.layers.remove(layers[i]);
  636. }
  637. }
  638. actions.setChangeLayers();
  639. if (callback) callback();
  640. break;
  641. case "S3M":
  642. viewer.scene.layers.remove(id_name);
  643. actions.setChangeLayers();
  644. if (callback) callback();
  645. break;
  646. case "IMG":
  647. case "IMAGE":
  648. let img_layer;
  649. if (typeof (id_name) === 'number') {
  650. img_layer = viewer.imageryLayers.get(id_name);
  651. } else {
  652. let img_layers = viewer.imageryLayers._layers;
  653. for (let i = 0; i < img_layers.length; i++) {
  654. const layer = img_layers[i];
  655. const provider = layer.imageryProvider;
  656. let matched = false;
  657. if (provider.tablename && provider.tablename === id_name) matched = true;
  658. if (!matched && layer._loadedLayerName && (layer._loadedLayerName === id_name || layer._loadedLayerName.includes(id_name) || id_name.includes(layer._loadedLayerName))) matched = true;
  659. if (!matched && layer._loadedUrl && (layer._loadedUrl === id_name || layer._loadedUrl.includes(id_name) || id_name.includes(layer._loadedUrl))) matched = true;
  660. if (!matched && provider.url) {
  661. const urlStr = typeof provider.url === 'string' ? provider.url : JSON.stringify(provider.url);
  662. if (urlStr.includes(id_name) || id_name.includes(urlStr)) matched = true;
  663. }
  664. if (!matched && provider.name && (provider.name === id_name || provider.name.includes(id_name))) matched = true;
  665. if (matched) {
  666. img_layer = layer;
  667. break;
  668. }
  669. }
  670. }
  671. if (img_layer) {
  672. viewer.imageryLayers.remove(img_layer);
  673. actions.setChangeLayers();
  674. if (callback) callback();
  675. }
  676. break;
  677. case "TERRAIN":
  678. viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();
  679. actions.setChangeLayers();
  680. if (callback) callback();
  681. break;
  682. case "MVT":
  683. viewer.scene.removeVectorTilesMap(id_name);
  684. actions.setChangeLayers();
  685. if (callback) callback();
  686. break;
  687. case "GEOJSON":
  688. case "SHP":
  689. if (viewer.dataSources) {
  690. const dataSources = viewer.dataSources._dataSources;
  691. let removed = false;
  692. for (let i = dataSources.length - 1; i >= 0; i--) {
  693. const ds = dataSources[i];
  694. if (ds.name === id_name || ds._name === id_name ||
  695. (ds.name && ds.name.includes(id_name)) ||
  696. (ds._name && ds._name.includes(id_name))) {
  697. viewer.dataSources.remove(ds);
  698. removed = true;
  699. break;
  700. }
  701. const entities = ds.entities ? ds.entities.values : [];
  702. for (let j = 0; j < entities.length; j++) {
  703. const entity = entities[j];
  704. if (entity.name === id_name || (entity.name && entity.name.includes(id_name))) {
  705. viewer.dataSources.remove(ds);
  706. removed = true;
  707. break;
  708. }
  709. }
  710. if (removed) break;
  711. }
  712. }
  713. actions.setChangeLayers();
  714. if (callback) callback();
  715. break;
  716. default:
  717. if (callback) callback();
  718. }
  719. }
  720. export default {
  721. addS3mLayers,
  722. addScene,
  723. addTerrainLayer,
  724. addImageLayer,
  725. layersDelete,
  726. addMvtLayer,
  727. addGeoJsonLayer
  728. };
  729. export {
  730. addS3mLayers,
  731. addScene,
  732. addTerrainLayer,
  733. addImageLayer,
  734. layersDelete,
  735. addMvtLayer,
  736. addGeoJsonLayer
  737. };