From 60868e72390e2bf8cb0f2724c5c2ca4b7eb761bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20R=C3=A4is=C3=A4nen?= Date: Sun, 15 Sep 2024 21:23:24 +0300 Subject: [PATCH] Added visualization of target names in a list --- GUI/Controls.js | 2 + GUI/ListDialog.js | 2 + GUI/OrbitControls.js | 15 +++--- app.css | 36 +++++++++++---- app.js | 99 ++++++++++++++++++++++++++++++++++++++-- computation/MathUtils.js | 5 ++ index.html | 1 + 7 files changed, 140 insertions(+), 20 deletions(-) diff --git a/GUI/Controls.js b/GUI/Controls.js index 909af05..b4c77ae 100644 --- a/GUI/Controls.js +++ b/GUI/Controls.js @@ -50,6 +50,7 @@ function createControls() this.deltaMins = 0; this.deltaSecs = 0; this.showTargetName = true; + this.showListNames = false; this.showLocal = false; this.showUtc = true; this.showJulian = false; @@ -255,6 +256,7 @@ function createControls() displayControls.enableOrbit = displayFolder.add(guiControls, 'enableOrbit').name('Orbit Lines'); displayControls.enableSun = displayFolder.add(guiControls, 'enableSun').name('Sun Orbit'); displayControls.enableList = displayFolder.add(guiControls, 'enableList').name('Show List'); + displayControls.enableListNames = displayFolder.add(guiControls, 'showListNames').name('Show Names'); //displayFolder.add(guiControls, 'enableMoon').name('Show Moon'); const lonControl = displayFolder.add(guiControls, 'gridLonResolution', 1, 180, 1) .name('Grid Lon. Resolution') diff --git a/GUI/ListDialog.js b/GUI/ListDialog.js index a181305..c7aa8bd 100644 --- a/GUI/ListDialog.js +++ b/GUI/ListDialog.js @@ -15,6 +15,7 @@ ListEnter.onclick = function() satellites = []; satelliteNames = []; satNameToIndex = []; + satIndexToName = []; let innerHTML = ""; autoCompleteTargetList.length = 0; @@ -41,6 +42,7 @@ ListEnter.onclick = function() satelliteNames.push(title); autoCompleteTargetList.push(title); satNameToIndex[title] = indElem; + satIndexToName.push(title) } satelliteNames.sort(); diff --git a/GUI/OrbitControls.js b/GUI/OrbitControls.js index f1c7ce1..9b3125f 100644 --- a/GUI/OrbitControls.js +++ b/GUI/OrbitControls.js @@ -10,14 +10,15 @@ var drawing = false; // Get A WebGL context var canvas = document.querySelector("#canvas"); +var canvasJs = document.querySelector("#canvasJs"); -canvas.addEventListener("mousedown", function(e) { +canvasJs.addEventListener("mousedown", function(e) { xStart = e.clientX; yStart = e.clientY; dragXStart = -MathUtils.rad2Deg(rotZ); dragYStart = -MathUtils.rad2Deg(rotX) - 90; - canvas.onmousemove = function(m) { + canvasJs.onmousemove = function(m) { //console.log(m); dragX = dragXStart - (m.clientX - xStart) / 10.0; dragY = dragYStart - (m.clientY - yStart) / 10.0; @@ -35,15 +36,15 @@ canvas.addEventListener("mousedown", function(e) { } }); -canvas.addEventListener("mouseup", function(e) { - canvas.onmousemove = null; +canvasJs.addEventListener("mouseup", function(e) { + canvasJs.onmousemove = null; }); -canvas.addEventListener("mouseleave", function(e) { - canvas.onmousemove = null; +canvasJs.addEventListener("mouseleave", function(e) { + canvasJs.onmousemove = null; }); -canvas.addEventListener("wheel", function(e) { +canvasJs.addEventListener("wheel", function(e) { distance *= (e.deltaY * 0.0001 + 1); cameraControls.distance.setValue(distance); }); diff --git a/app.css b/app.css index 707f3b3..5742dd3 100644 --- a/app.css +++ b/app.css @@ -4,16 +4,6 @@ body { padding: 0; } -#canvas { - position: absolute !important; - left: 0; - right: 0; - margin: 0; - width: 100%; - height: 100%; - border: none; - outline: none; -} #dateText { @@ -208,3 +198,29 @@ body { font-size: 15px; font-family : monospace; } + +#canvasJs { + position: absolute !important; + left: 0; + right: 0; + width: 100%; + height: 100%; + border: none; + outline: none; + background-color: transparent; +} + +#canvas { + position: absolute !important; + left: 0; + right: 0; + margin: 0; + width: 100%; + height: 100%; + border: none; + outline: none; +} + +#gui_css { + z-index : 3; +} \ No newline at end of file diff --git a/app.js b/app.js index f17f98f..ee4cb9f 100644 --- a/app.js +++ b/app.js @@ -39,6 +39,9 @@ var rotX = MathUtils.deg2Rad(-90); var rotY = MathUtils.deg2Rad(0); var rotZ = MathUtils.deg2Rad(0); +// JS canvas +var canvasJs = document.querySelector("#canvasJs"); +var contextJs = canvasJs.getContext("2d"); gl = canvas.getContext("webgl2"); if (!gl) @@ -57,6 +60,7 @@ pointShaders.init(); var satellites = []; var satLines = []; var satNameToIndex = []; +var satIndexToName = []; requestAnimationFrame(drawScene); @@ -290,9 +294,11 @@ function drawScene(time) // Clear the canvas gl.clearColor(0, 0, 0, 255); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + contextJs.clearRect(0, 0, canvasJs.width, canvasJs.height); // Handle screen size updates. resizeCanvasToDisplaySize(gl.canvas); + resizeCanvasToDisplaySize(canvasJs); gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); gl.enable(gl.DEPTH_TEST); gl.enable(gl.CULL_FACE); @@ -304,11 +310,12 @@ function drawScene(time) drawOrbit(today, matrix, kepler_updated, nutPar); } + let rotMatrixTeme; if (enableList) { // Performance : It is significantly faster to perform the J2000->ECEF coordinate // transformation in the vertex shader: - const rotMatrixTeme = createRotMatrix(today, JD, JT, nutPar); + rotMatrixTeme = createRotMatrix(today, JD, JT, nutPar); if (guiControls.frame === 'J2000') { @@ -325,6 +332,33 @@ function drawScene(time) drawSun(lonlat, JT, JD, rASun, declSun, matrix, nutPar); } + if (enableList && guiControls.showListNames) + { + // Semi-major axis: + const a = 6378137; + const cameraPos = [ + 1000 * guiControls.distance * MathUtils.cosd(guiControls.lat)*MathUtils.cosd(guiControls.lon), + 1000 * guiControls.distance * MathUtils.cosd(guiControls.lat)*MathUtils.sind(guiControls.lon), + 1000 * guiControls.distance * MathUtils.sind(guiControls.lat) + ]; + + for (let indSat = 0; indSat < osvSatListTeme.length; indSat++) + { + const osvTeme = {r : osvSatListTeme[indSat].r, v : [0, 0, 0], JT : JT, JD : JD, ts : today}; + if (guiControls.frame === 'J2000') + { + if (!checkIntersection(cameraPos, osvTeme.r, 6371000)) + drawCaption(MathUtils.vecsub(osvTeme.r, cameraPos), satIndexToName[indSat], matrix); + } else { + let targetEcef = sgp4.coordTemePef(osvTeme).r; + + if (!checkIntersection(cameraPos, targetEcef, 6371000)) + drawCaption(MathUtils.vecsub(targetEcef, cameraPos), satIndexToName[indSat], matrix); + } + } + pointShaders.setGeometry(pointsOut); + } + // Call drawScene again next frame requestAnimationFrame(drawScene); @@ -516,7 +550,7 @@ function createViewMatrix() cameraControls.lon.setValue(ISS.lon); } - else if (canvas.onmousemove == null) + else if (canvasJs.onmousemove == null) { rotZ = MathUtils.deg2Rad(-90 - guiControls.lon); } @@ -528,7 +562,7 @@ function createViewMatrix() rotX = MathUtils.deg2Rad(-90 + ISS.lat); cameraControls.lat.setValue(ISS.lat); } - else if (canvas.onmousemove == null) + else if (canvasJs.onmousemove == null) { rotX = MathUtils.deg2Rad(-90 + guiControls.lat); } @@ -761,4 +795,63 @@ function drawSun(lonlat, JT, JD, rASun, declSun, matrix, nutPar) lineShaders.setGeometry(pSun); lineShaders.draw(matrix); +} + +/** + * Draw caption. + * + * @param {*} rTarget + * Relative position of the target. + * @param {*} caption + * Caption. + * @param {*} matrix + * View Matrix. + */ +function drawCaption(rTarget, caption, matrix) +{ + contextJs.fillStyle = "rgba(" + + guiControls.colorSatellite[0] + "," + + guiControls.colorSatellite[1] + "," + + guiControls.colorSatellite[2] + ")"; + + contextJs.textAlign = "center"; + contextJs.textBaseline = "bottom"; + contextJs.textAlign = "right"; + contextJs.strokeStyle = contextJs.fillStyle; + + const clipSpace = m4.transformVector(matrix, [rTarget[0], rTarget[1], rTarget[2], 1]); + clipSpace[0] /= clipSpace[3]; + clipSpace[1] /= clipSpace[3]; + const pixelX = (clipSpace[0] * 0.5 + 0.5) * gl.canvas.width; + const pixelY = (clipSpace[1] * -0.5 + 0.5) * gl.canvas.height; + contextJs.fillText(caption + " ", pixelX, pixelY); +} + +/** + * Check whether there is an Earth intersection in front of the satellite + * to be drawn. + * + * @param {*} source + * Camera position. + * @param {*} target + * Satellite position. + * @param {*} radius + * Radius of the sphere. + * @returns {*} Whether there is an intersection. + */ +function checkIntersection(source, target, radius) +{ + const c = [0, 0, 0]; + const direction = MathUtils.vecsub(target, source); + const distance = MathUtils.norm(direction); + const u = MathUtils.vecmul(direction, 1/MathUtils.norm(direction)); + const lambda = (MathUtils.dot(u, source) ** 2) + - (MathUtils.norm(source) ** 2 - radius * radius); + + if (lambda >= 0) + { + const d = - MathUtils.dot(u, source) + Math.sqrt(lambda); + return (d < distance); + } + return false; } \ No newline at end of file diff --git a/computation/MathUtils.js b/computation/MathUtils.js index dc28d8b..1162584 100644 --- a/computation/MathUtils.js +++ b/computation/MathUtils.js @@ -10,6 +10,11 @@ MathUtils.cross = function(u, v) u[0]*v[1] - u[1]*v[0]]; } +MathUtils.dot = function(u, v) +{ + return u[0]*v[0] + u[1]*v[1] + u[2]*v[2]; +} + MathUtils.norm = function(u) { return Math.sqrt(u[0]*u[0] + u[1]*u[1] + u[2]*u[2]); diff --git a/index.html b/index.html index 124a10c..4dae6e0 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,7 @@

LOADING

LOADING

+