import * as mars3d from "mars3d" export let map // mars3d.Map三维地图对象 export let graphicLayer // 矢量图层对象 let allCount let lastSelectWX // 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并) export const mapOptions = { scene: { center: { lat: 29.646563, lng: 96.25028, alt: 150004581, heading: 352, pitch: -90 }, cameraController: { zoomFactor: 3.0, minimumZoomDistance: 1, maximumZoomDistance: 500000000, constrainedAxis: false // 解除在南北极区域鼠标操作限制 }, clock: { multiplier: 2 // 速度 } }, control: { clockAnimate: true, // 时钟动画控制(左下角) timeline: true, // 是否显示时间线控件 compass: { top: "10px", left: "5px" } }, terrain: false } export const eventTarget = new mars3d.BaseClass() // 事件对象,用于抛出事件到面板中 /** * 初始化地图业务,生命周期钩子函数(必须) * 框架在地图初始化完成后自动调用该函数 * @param {mars3d.Map} mapInstance 地图对象 * @returns {void} 无 */ export function onMounted(mapInstance) { map = mapInstance // 记录map map.toolbar.style.bottom = "55px" // 修改toolbar控件的样式 // 修改天空盒 map.scene.skyBox = new Cesium.SkyBox({ sources: { negativeX: "img/skybox/5/tycho2t3_80_mx.jpg", negativeY: "img/skybox/5/tycho2t3_80_my.jpg", negativeZ: "img/skybox/5/tycho2t3_80_mz.jpg", positiveX: "img/skybox/5/tycho2t3_80_px.jpg", positiveY: "img/skybox/5/tycho2t3_80_py.jpg", positiveZ: "img/skybox/5/tycho2t3_80_pz.jpg" } }) // 访问后端接口,取数据 mars3d.Util.fetchJson({ url: "//data.mars3d.cn/file/apidemo/tle.json" }) .then(function (arr) { initData(arr.list) }) .catch(function () { globalMsg("获取空间目标轨道数据异常!") }) // 单击地图空白处 map.on(mars3d.EventType.clickMap, function (event) { if (lastSelectWX) { // 重置上次选中的轨道样式 lastSelectWX.remove() lastSelectWX = null } eventTarget.fire("clickMap") }) } /** * 释放当前地图业务的生命周期函数 * @returns {void} 无 */ export function onUnmounted() { map = null } function initData(arr) { allCount = arr.length globalMsg("当前外太空物数量: " + allCount) // 创建Graphic图层 graphicLayer = new mars3d.layer.GraphicLayer() map.addLayer(graphicLayer) for (let i = 0; i < arr.length; i++) { const item = arr[i] const style = { pixelSize: 5, color: "rgba(0,255,0,0.6)", outlineWidth: 1, outlineColor: "#000000", scaleByDistance: new Cesium.NearFarScalar(20000000, 1.0, 150000000, 0.4) } // 转为属性,方便使用 if (item.info) { item.type = item.info[0] // 对象类型 item.status = item.info[1] // 操作状态代码 item.country = item.info[2] // 所有权(国家) item.launchDate = item.info[3] && new Date(item.info[3]) // 发射日期 item.launchSite = item.info[4] // 发射地点 item.decayDate = item.info[5] // 衰减日期 item.period = item.info[6] // 轨道周期[分钟] item.inclination = item.info[7] // 倾角[度] item.apogee = item.info[8] // 远地点高度[公里] item.perigee = item.info[9] // 近地点高度[公里] item.rcs = item.info[10] // 雷达截面 // item.dataStatus = item.info[11]; // 数据状态码 item.orbitCenter = item.info[12] // 轨道中心 item.orbitType = item.info[13] // 轨道类型 delete item.info } const primitive = new mars3d.graphic.PointPrimitive({ id: item.id, style: style, attr: item }) graphicLayer.addGraphic(primitive) } graphicLayer.on(mars3d.EventType.click, function (event) { console.log("单击了卫星", event) const satelliteObj = event.graphic if (lastSelectWX) { // 重置上次选中的轨道样式 lastSelectWX.remove() lastSelectWX = null } if (satelliteObj) { const item = satelliteObj.attr if (!item.name) { return } let launchDate, status, country, launchSite if (item.launchDate) { launchDate = mars3d.Util.formatDate(item.launchDate, "yyyy-MM-dd") } if (item.status) { status = getStatusName(item.status) } else { status = "" } if (item.country) { country = getCountryName(item.country) } if (item.launchSite) { launchSite = getLaunchSiteName(item.launchSite) } const period = mars3d.Util.formatNum(item.period, 2) + " 分钟" const inclination = item.inclination + "°" const apogee = mars3d.Util.formatNum(item.apogee, 0) + " km" const perigee = mars3d.Util.formatNum(item.perigee, 0) + " km" const inhtml = `N2YO...` const weixinList = [ item.name, item.id, item.cospar, item.type, status, country, launchDate, launchSite, period, inclination, apogee, perigee, item.rcs || "未知", item.orbitCenter, item.orbitType, inhtml ] eventTarget.fire("clickWeixin", { weixinList }) weixingStyle(item) } }) initWorker(arr) } // 采用多线程来计算卫星位置 let worker function initWorker(arr) { worker = new Worker(window.currentPath + "tleWorker.js") // currentPath为当前目录,内置在示例框架中 worker.onmessage = function (event) { const time = event.data.time const positionObj = event.data.positionObj for (const id in positionObj) { const item = positionObj[id] if (!item) { continue } const graphic = graphicLayer.getGraphicById(id) if (graphic) { graphic.position = new Cesium.Cartesian3(item.x, item.y, item.z) } } // 循环继续发送请求消息 postWorkerMessage(arr) } // 主线程调用worker.postMessage()方法,向 Worker 发消息。 postWorkerMessage(arr) } function postWorkerMessage(arr) { // 取数据的时间范围,开始时间 const date = Cesium.JulianDate.toDate(map.clock.currentTime) // 主线程调用worker.postMessage()方法,向 Worker 发消息。 worker.postMessage({ time: date, list: arr }) } function weixingStyle(item) { // 高亮选中的轨道样式 const weixin = new mars3d.graphic.Satellite({ tle1: item.tle1, tle2: item.tle2, model: { url: "//data.mars3d.cn/gltf/mars/weixin.gltf", scale: 1, autoHeading: true, minimumPixelSize: 50, show: !!item.name }, label: { color: "#ffffff", opacity: 1, font_family: "楷体", font_size: 30, outline: true, outlineColor: "#000000", outlineWidth: 3, background: true, backgroundColor: "#000000", backgroundOpacity: 0.5, font_weight: "normal", font_style: "normal", pixelOffsetX: 0, pixelOffsetY: -20, scaleByDistance: true, scaleByDistance_far: 10000000, scaleByDistance_farValue: 0.4, scaleByDistance_near: 100000, scaleByDistance_nearValue: 1, show: true }, path: { show: true, color: "#e2e2e2", opacity: 0.8, width: 1 } }) map.graphicLayer.addGraphic(weixin) lastSelectWX = weixin } // Orbital altitude definitions. // 重置 export function resetGraphic() { // 循环所有卫星 if (!graphicLayer) { globalMsg("当前数据正在加载") return } graphicLayer.eachGraphic(function (graphic) { if (graphic.selected) { graphic.setStyle({ color: "rgba(0,255,0,0.6)", outlineColor: "#000000" }) graphic.selected = false } }) } // Well known satellite constellations. const GPS = [ 20959, 22877, 23953, 24876, 25933, 26360, 26407, 26605, 26690, 27663, 27704, 28129, 28190, 28361, 28474, 28874, 29486, 29601, 32260, 32384, 32711, 35752, 36585, 37753, 38833, 39166, 39533, 39741, 40105, 40294, 40534 ] const GLONASS = [ 28915, 29672, 29670, 29671, 32276, 32275, 32393, 32395, 36111, 36112, 36113, 36400, 36402, 36401, 37139, 37138, 37137, 37829, 37869, 37867, 37868, 39155, 39620, 40001 ] const INMARSAT = [20918, 21149, 21814, 21940, 23839, 24307, 24674, 24819, 25153, 28628, 28899, 33278, 40384, 39476] const LANDSAT = [25682, 39084] const DIGITALGLOBE = [25919, 32060, 33331, 35946, 40115] // 判断卫星数据 export function selectSatellites(data) { if (!graphicLayer) { return } const name = data.name const xilie = data.selXiLie // 系列卫星 const country = data.selCountry // 所属国家 const type = data.selType // 对象类型 const val1 = data.sliLaunchdate const min1 = 1950 const max1 = 2022 const val2 = data.sliPeriod const min2 = 0 const max2 = 60000 const val3 = data.sliInclination const min3 = 0 const max3 = 150 const val4 = data.sliApogee const min4 = 0 const max4 = 600000 const val5 = data.sliPerigee const min5 = 0 const max5 = 500000 const val6 = data.sliRcs const min6 = 0 const max6 = 1000 let selCount = 0 // 循环所有卫星 graphicLayer.eachGraphic(function (graphic) { // 先将所有样式还原 if (graphic.selected) { graphic.setStyle({ color: "rgba(0,255,0,0.6)", outlineColor: "#000000" }) graphic.selected = false } const attr = graphic.attr // 卫星的属性 // 名称 if (name) { if ((attr.name && attr.name.indexOf(name) !== -1) || (attr.id && attr.id === name) || (attr.cospar && attr.cospar.indexOf(name) !== -1)) { // } else { return } } // 系列卫星时 if (xilie) { let selected switch (xilie) { case "gps": selected = GPS.indexOf(attr.id) !== -1 break case "bd": selected = attr.name.indexOf("BD") !== -1 || attr.name.indexOf("BEIDOU") !== -1 break case "glonass": selected = GLONASS.indexOf(attr.id) !== -1 break case "inmarsat": selected = INMARSAT.indexOf(attr.id) !== -1 break case "landsat": selected = LANDSAT.indexOf(attr.id) !== -1 break case "digitalglobe": selected = DIGITALGLOBE.indexOf(attr.id) !== -1 break } if (!selected) { return } } // 国家 if (country && country !== attr.country) { return } // 类型的判断 if (type) { const name = attr.name if (type === "junk" && name.indexOf(" DEB") === -1 && name.indexOf(" R/B") === -1) { return } if (type === "satellite" && (name.indexOf(" DEB") !== -1 || name.indexOf(" R/B") !== -1)) { return } } // 滑动轨的判断 // Launch date if (val1[0] !== min1 || val1[1] !== max1) { if (!attr.launchDate) { return } const y = attr.launchDate.getFullYear() if (y <= val1[0] || y >= val1[1]) { return } } // Orbital period if (val2[0] !== min2 || val2[1] !== max2) { if (!attr.period) { return } if (attr.period < val2[0] || attr.period > val2[1]) { return } } // Inclination if (val3[0] !== min3 || val3[1] !== max3) { if (!attr.inclination) { return } if (attr.inclination < val3[0] || attr.inclination > val3[1]) { return } } // Apogee if (val4[0] !== min4 || val4[1] !== max4) { if (!attr.apogee) { return } if (attr.apogee < val4[0] || attr.apogee > val4[1]) { return } } // Perigee if (val5[0] !== min5 || val5[1] !== max5) { if (!attr.perigee) { return } if (attr.perigee < val5[0] || attr.perigee > val5[1]) { return } } // 尺寸的判断 if (val6[0] !== min6 || val6[1] !== max6) { if (!attr.rcs) { return } if (attr.rcs <= val6[0] || attr.rcs >= val6[1]) { return } } // 将筛选到的数据修改为红色 if (!graphic.selected) { graphic.selected = true graphic.setStyle({ color: "rgba(255,0,0,1.0)", outlineColor: "#FFFFFF" }) } selCount++ }) globalMsg(`${allCount}个对象中,有 ${selCount} 个符合条件`) } function getStatusName(code) { switch (code) { case "+": return "运作的" case "-": return "非运转的" case "P": return "部分运转,部分完成主要任务或次要任务" case "B": return "备份/备用,先前运行的卫星进入储备状态" case "S": return "备用,新卫星等待完全激活" case "X": return "扩展的任务" case "D": return "衰退的" case "?": return "未知的" } return code } function getLaunchSiteName(code) { switch (code) { case "AFETR": return "美国佛罗里达州空军东部试验场" case "AFWTR": return "美国加州空军西部试验场" case "CAS": return "Canaries Airspace" case "DLS": return "俄罗斯Dombarovskiy发射场" case "ERAS": return "东部领空范围" case "FRGUI": return "法属圭亚那库鲁的欧洲太空港" case "HGSTR": return "阿尔及利亚的Hammaguira空间轨道靶场" case "JSC": return "中国酒泉航天中心" case "KODAK": return "美国阿拉斯加科迪亚克发射中心" case "KSCUT": return "日本内浦航天中心" case "KWAJ": return "美国陆军夸贾林环礁" case "KYMSC": return "俄罗斯Kapustin Yar导弹和太空综合体" case "NSC": return "韩国罗老宇航中心" case "PLMSC": return "俄罗斯普列谢茨克导弹和太空综合体" case "RLLB": return "火箭实验室发射基地" case "SEAL": return "海上发射平台(流动)" case "SEMLS": return "伊朗塞姆南卫星发射场" case "SMTS": return "伊朗沙赫鲁德导弹试验场" case "SNMLP": return "印度洋(肯尼亚)圣马可发射平台" case "SRILR": return "印度萨迪什·达万航天中心" case "SUBL": return "潜艇发射平台(移动式)" case "SVOBO": return "俄罗斯Svobodnyy发射中心" case "TAISC": return "中国太原航天中心" case "TANSC": return "日本种子岛宇宙中心" case "TYMSC": return "哈萨克斯坦秋拉坦导弹和航天中心" case "VOSTO": return "俄罗斯东方港航天器发射场" case "WLPIS": return "美国弗吉尼亚州瓦勒普斯岛" case "WOMRA": return "澳大利亚Woomera" case "WRAS": return "西方领空范围" case "WSC": return "中国文昌卫星发射场" case "XICLF": return "中国西昌发射场" case "YAVNE": return "以色列Yavne发射设施" case "YUN": return "朝鲜云松发射场" case "UNK": return "未知的" } return code } function getCountryName(code) { switch (code) { case "AB": return "阿拉伯卫星通信组织" case "ABS": return "亚洲广播卫星" case "AC": return "亚洲卫星电讯公司" case "ALG": return "阿尔及利亚" case "ANG": return "安哥拉" case "ARGN": return "阿根廷" case "ASRA": return "奥地利" case "AUS": return "澳大利亚" case "AZER": return "阿塞拜疆" case "BEL": return "比利时" case "BELA": return "白俄罗斯" case "BERM": return "百慕大" case "BGD": return "孟加拉国" case "BHUT": return "不丹王国" case "BOL": return "玻利维亚" case "BRAZ": return "巴西" case "BUL": return "保加利亚" case "CA": return "加拿大" case "CHBZ": return "中国/巴西" case "CHLE": return "智利" case "CIS": return "前苏联" case "COL": return "哥伦比亚" case "CRI": return "哥斯达黎加共和国" case "CZCH": return "捷克" case "DEN": return "丹麦" case "ECU": return "厄瓜多尔" case "EGYP": return "埃及" case "ESA": return "欧洲太空总署" case "ESRO": return "欧洲空间研究组织" case "EST": return "爱沙尼亚" case "EUME": return "欧洲气象卫星开发组织" case "EUTE": return "欧洲电信卫星组织" case "FGER": return "法国/德国" case "FIN": return "芬兰" case "FR": return "法国" case "FRIT": return "法国/意大利" case "GER": return "德国" case "GHA": return "加纳共和国" case "GLOB": return "全球星" case "GREC": return "希腊" case "GRSA": return "希腊/沙特阿拉伯" case "GUAT": return "危地马拉" case "HUN": return "匈牙利" case "IM": return "国际移动卫星组织(INMARSAT)" case "IND": return "印度" case "INDO": return "印尼" case "IRAN": return "伊朗" case "IRAQ": return "伊拉克" case "IRID": return "IRID" case "ISRA": return "以色列" case "ISRO": return "印度空间研究组织" case "ISS": return "国际空间站" case "IT": return "意大利" case "ITSO": return "国际电信卫星组织" case "JPN": return "日本" case "KAZ": return "哈萨克斯坦" case "KEN": return "肯尼亚" case "LAOS": return "老挝" case "LKA": return "斯里兰卡" case "LTU": return "立陶宛" case "LUXE": return "卢森堡" case "MA": return "摩洛哥" case "MALA": return "马来西亚" case "MEX": return "墨西哥" case "MMR": return "缅甸" case "MNG": return "蒙古" case "MUS": return "毛里求斯" case "NATO": return "北大西洋公约组织" case "NETH": return "荷兰" case "NICO": return "新图标" case "NIG": return "尼日利亚" case "NKOR": return "朝鲜" case "NOR": return "挪威" case "NPL": return "尼泊尔" case "NZ": return "新西兰" case "O3B": return "O3b Networks公司" case "ORB": return "ORBCOMM卫星公司" case "PAKI": return "巴基斯坦" case "PERU": return "秘鲁" case "POL": return "波兰" case "POR": return "葡萄牙" case "PRC": return "中国" case "PRY": return "巴拉圭" case "PRES": return "中国/欧洲航天局" case "QAT": return "卡塔尔的状态" case "RASC": return "非洲区域卫星通信组织" case "ROC": return "台湾" case "ROM": return "罗马尼亚" case "RP": return "菲律宾" case "RWA": return "卢旺达" case "SAFR": return "南非" case "SAUD": return "沙特阿拉伯" case "SDN": return "苏丹" case "SEAL": return "Sea Launch公司" case "SES": return "SES电信公司" case "SGJP": return "新加坡/日本" case "SING": return "新加坡" case "SKOR": return "韩国" case "SPN": return "西班牙" case "STCT": return "新加坡/台湾" case "SVN": return "斯洛文尼亚" case "SWED": return "瑞典" case "SWTZ": return "瑞士" case "TBD": return "待定" case "THAI": return "泰国" case "TMMC": return "土库曼斯坦/摩纳哥" case "TUN": return "突尼斯共和国" case "TURK": return "土耳其" case "UAE": return "阿拉伯联合酋长国" case "UK": return "英国" case "UKR": return "乌克兰" case "URY": return "乌拉圭" case "US": return "美国" case "USBZ": return "美国/巴西" case "VENZ": return "委内瑞拉" case "VTNM": return "越南" case "UNK": return "未知" } return code } // 清除卫星的点击事件,隐藏卫星的面板 export function highlightSatellite() { lastSelectWX.remove() lastSelectWX = null }