<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel='stylesheet' />
<script src='http://ua.bigemap.com:30081/bmsdk/bigemap-gl.js/v1.1.0/bigemap-gl.js'></script>
<script src="/offline_data/satellite.min.js"></script>
<title>衛星軌跡</title>
</head>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
html,
body,
#map {
width: 100%;
height: 100%;
}
#result {
width: 150px;
height: 120px;
border-radius: 5px;
background: rgba(255, 255, 255, 0.6);
font-size: 12px;
user-select: none; /*禁止選中*/
pointer-events: none; /*鼠標穿透*/
line-height: 20px;
}
#result div {
margin-left: 10px;
}
</style>
<body>
<div id="map"></div>
<div id="result">
<div class="name">0</div>
<div class="mylat">0</div>
<div class="mylng">0</div>
<div class="myheight">0</div>
<div class="Per-second">0</div>
<div class="Omni-hora">0</div>
</div>
</body>
</html>
<script src="/offline_data/3d_div.min.js"></script>
<script type="text/javascript">
window.onload = function () {
getTLE()
}
bmgl.Config.HTTP_URL = 'http://ua.bigemap.com:30081/bmsdk/';
var viewer = new bmgl.Viewer('map', { mapId: 'bigemap.dc-tian-w-satellite' });
var dom = document.getElementById('result')
var val = {
viewer: viewer,
position: [104, 30],
height: 0,
offset: [0, -130],
dom
}
var layer = new divLabel(val)
layer.toggleShow(false)
var data = [
{
name: 'THOR ABLE R/B',
tleLine1: '1 00037U 60005 D 61074.65882873 .00039007 +00000-0 +00000-0 0 9995',
tleLine2: '2 00037 064.8899 343.2411 0198403 333.4201 027.0840 15.49800338046906'
},
{
name: 'SL-3 R/B',
tleLine1: '1 00035U 60005 B 60198.16679572 .03271057 +00000-0 +00000-0 0 9991',
tleLine2: '2 00035 064.8899 044.6976 0000000 036.3819 323.6180 16.27523673009903'
},
{
name: 'MIDAS 2 DEB',
tleLine1: '1 00044U 60006 B 60339.48320007 .05617416 +00000-0 +00000-0 0 9995',
tleLine2: '2 00044 033.0000 103.1687 0000000 237.9085 122.0914 16.16822545029905'
},
{
name: 'SPUTNIK 4 DEB',
tleLine1: '1 00041U 60005 H 60213.55741600 .00877296 +00000-0 +00000-0 0 9995',
tleLine2: '2 00041 064.8899 009.0399 0041880 060.9395 299.2735 15.87027825012009'
},
{
name: 'DELTA 1 R/B',
tleLine1: '1 00050U 60009B 24142.92633053 -.00000094 00000-0 -94502-4 0 9993',
tleLine2: '2 00050 47.2345 349.0820 0113206 280.9957 77.8117 12.20140331845365'
},
]
function getTLE () {
viewer.clock.shouldAnimate = true
// satlliteTest(data)
data.forEach(item => {
satlliteTest(item.tleLine1, item.tleLine2, item.name)
})
}
// 計算速度
function calculateSpeed(velocityObject) {
// 假設velocityObject是一個包含{vx: ..., vy: ..., vz: ...}的對象
const vx = velocityObject.x;
const vy = velocityObject.y;
const vz = velocityObject.z;
// 計算速度模(大小)
const speed = Math.sqrt(vx * vx + vy * vy + vz * vz);
return speed;
}
var handler = new bmgl.ScreenSpaceEventHandler(viewer.scene.canvas);
var state = false
var mysatellite = null
handler.setInputAction(function(e) {
var entity = viewer.scene.pick(e.endPosition);
if (bmgl.defined(entity)) {
mysatellite = entity.id
state = true
entity.id.label.show = false
dom.querySelector('.name').innerText = entity.id.label.text.getValue()
layer.toggleShow(true);
} else {
state = false
if(mysatellite) {
mysatellite.label.show = true
mysatellite = null
}
layer.toggleShow(false);
}
}, bmgl.ScreenSpaceEventType.MOUSE_MOVE)
viewer.clock.onTick.addEventListener((clock) => {
if(mysatellite) {
let satrec = mysatellite.satrec
var positionAndVelocity = satellite.propagate(satrec, new Date());
let positionEci = positionAndVelocity.position
var cartesian3 = new bmgl.Cartesian3(positionEci.x * 1000, positionEci.y * 1000, positionEci.z * 1000)
layer.changePosition(cartesian3)
let latlngs = transform(cartesian3)
dom.querySelector('.mylat').innerText = '緯度:' + latlngs[1].toFixed(2) + '°'
dom.querySelector('.mylng').innerText = '經度:' + latlngs[0].toFixed(2) + '°'
dom.querySelector('.myheight').innerText = '高度:' + (latlngs[2] / 1000).toFixed(2) + ' km'
let speed = calculateSpeed(positionAndVelocity.velocity)
dom.querySelector('.Per-second').innerText = '速度:' + speed.toFixed(2) + ' km/s'
dom.querySelector('.Omni-hora').innerText = "速度:" + (speed * 60 * 60).toFixed(2) + ' km/h'
}
});
function transform (position) {
let cartographic = bmgl.Cartographic.fromCartesian(position)
if (cartographic.height < 0) cartographic.height = 0
let lon = bmgl.Math.toDegrees(cartographic.longitude),
lat = bmgl.Math.toDegrees(cartographic.latitude),
height = cartographic.height
return [lon, lat, height]
}
function satlliteTest(tleLine1, tleLine2, name) {
var satrec = satellite.twoline2satrec(tleLine1, tleLine2)
var positionAndVelocity = satellite.propagate(satrec, new Date());
let totalIntervalsInDay = satrec.no * 1440 * 0.159155 //1440 = min && 0.159155 = 1turn
let minsPerInterval = 1440 / totalIntervalsInDay // mins for 1 revolution around earth
const { startTime, endTime } = getStratEndTime(minsPerInterval)
viewer.clock.startTime = startTime.clone()
viewer.clock.endTime = endTime.clone()
viewer.clock.currentTime = startTime.clone()
const positionProperty = getPositionSample(satrec, minsPerInterval)
let str = `${Math.floor(255 * Math.random(0, 1))}, ${Math.floor(255 * Math.random(0, 1))}, ${Math.floor(255 * Math.random(0, 1))}`
const entity = viewer.entities.add({
name: '衛星',
availability: new bmgl.TimeIntervalCollection([
new bmgl.TimeInterval({
start: startTime,
stop: endTime
})
]),
position: positionProperty,
orientation: new bmgl.VelocityOrientationProperty(positionProperty),
// 衛星模型
model: {
uri: '/offline_data/weixing.glb',
minimumPixelSize: 128
},
label: {
scale:1,
fillColor: new bmgl.Color.fromCssColorString(`rgba(${str}, 1)`),
text: name,
font: '20px',
showBackground:false,
backgroundColor: bmgl.Color.AQUA,
pixelOffset: new bmgl.Cartesian2(0, -20)
},
path: {
resolution: 1,
material: new bmgl.PolylineGlowMaterialProperty({
color: new bmgl.Color.fromCssColorString(`rgba(${str}, 1)`),
}),
width: 10
// leadTime: 720,
// trailTime: 720
}
})
// 插值
entity.position.setInterpolationOptions({
interpolationDegree: 5,
interpolationAlgorithm: bmgl.LagrangePolynomialApproximation
})
entity.satrec = satrec
}
function getStratEndTime(minsPerInterval) {
const startTimeStamp = Date.now()
// 結束時間為一圈后的時間
const endTimeStamp = startTimeStamp + minsPerInterval * 60 * 1000
let startTime = new bmgl.JulianDate.fromDate(new Date(startTimeStamp))
startTime = bmgl.JulianDate.addHours(startTime, 8, new bmgl.JulianDate())
let endTime = new bmgl.JulianDate.fromDate(new Date(endTimeStamp))
endTime = bmgl.JulianDate.addHours(endTime, 8, new bmgl.JulianDate())
return {
startTime,
endTime
}
}
function getPositionSample(satrec, minsPerInterval) {
const positionProperty = new bmgl.SampledPositionProperty()
const now = Date.now()
for (let i = 0; i <= Math.ceil(minsPerInterval); i++) {
const curTimeDate = new Date(now + i * 60 * 1000)
var positionAndVelocity = satellite.propagate(satrec, curTimeDate) // 此方法拿到的是慣性系坐標
var gmst = satellite.gstime(new Date(curTimeDate))
const positionEci = positionAndVelocity.position
const positionEcf = satellite.eciToEcf(positionEci, gmst)
const curJulianDate = new bmgl.JulianDate.fromDate(curTimeDate)
const d = new bmgl.JulianDate.addHours(curJulianDate, 8, new bmgl.JulianDate())
positionProperty.addSample(
d,
new bmgl.Cartesian3(positionEci.x * 1000, positionEci.y * 1000, positionEci.z * 1000)
)
}
return positionProperty
}
</script>