add all the stars, better visibility
This commit is contained in:
parent
bf1b43cf4c
commit
f0928994a5
9 changed files with 3810 additions and 25 deletions
11
input.example.csv
Normal file
11
input.example.csv
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
1 ;* 61 Cyg B;Er*;082.3171310715589 -05.8262372280102;K7V ;3.4964
|
||||||
|
2 ;* 61 Cyg A;BY*;082.3197403091576 -05.8181041502094;K5V ;3.4965
|
||||||
|
3 ;GAT 1383 ;PM*;085.6450087237446 -07.3769487234860;M5.5V ;14.5094
|
||||||
|
4 ;BD+40 4631;PM*;089.4905214280362 -08.8259946066449;K8V ;19.837
|
||||||
|
5 ;V* EV Lac ;Er*;100.6067176270883 -13.0693645782006;M4.0Ve;5.0515
|
||||||
|
6 ;G 216-43 ;PM*;107.6831520259098 -14.9929080409418;M4.5 ;35.6304
|
||||||
|
7 ;BD+45 4378;SB*;113.6133003656408 -15.1866691700906;K7V ;17.1213
|
||||||
|
8 ;LP 149-14 ;PM*;114.0239531748840 -14.2146886796646;M5.0V ;19.189
|
||||||
|
9 ;HD 38B ;PM*;114.6501340218375 -16.3243260935338;M0.5V ;11.518
|
||||||
|
10;HD 38A ;SB*;114.6505214717521 -16.3226459980874;K6V ;11.5207
|
||||||
|
11;BD+44 4548;PM*;114.5559641502924 -16.3315501979801;M2Ve ;11.5035
|
|
|
@ -15,6 +15,7 @@
|
||||||
"@types/three": "^0.148.0",
|
"@types/three": "^0.148.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
||||||
"@typescript-eslint/parser": "^5.48.2",
|
"@typescript-eslint/parser": "^5.48.2",
|
||||||
|
"csv-parse": "^5.3.3",
|
||||||
"eslint": "^8.32.0",
|
"eslint": "^8.32.0",
|
||||||
"eslint-config-prettier": "^8.6.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
|
|
38
simbad4csv2json.js
Normal file
38
simbad4csv2json.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { parse } from 'csv-parse'
|
||||||
|
import { readFile, writeFile } from 'fs/promises'
|
||||||
|
;(async () => {
|
||||||
|
const content = await readFile('input.csv')
|
||||||
|
const records = []
|
||||||
|
const columns = ['id', 'name', 'type', 'coords', 'spectral', 'distance']
|
||||||
|
const parser = parse(content, {
|
||||||
|
bom: true,
|
||||||
|
delimiter: ';',
|
||||||
|
trim: true,
|
||||||
|
columns,
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('readable', () => {
|
||||||
|
let record
|
||||||
|
while ((record = parser.read()) !== null) {
|
||||||
|
// objects without spectral class are probably not stars
|
||||||
|
if (record.spectral === '~') continue
|
||||||
|
|
||||||
|
const [phi, theta] = record.coords.split(' ').map((n) => parseFloat(n))
|
||||||
|
|
||||||
|
records.push({
|
||||||
|
id: parseInt(record.id),
|
||||||
|
name: record.name,
|
||||||
|
type: record.type,
|
||||||
|
spectral: record.spectral,
|
||||||
|
radius: parseFloat(record.distance),
|
||||||
|
phi,
|
||||||
|
theta,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('end', async () => {
|
||||||
|
await writeFile('output.json', JSON.stringify(records))
|
||||||
|
console.log('wrote', records.length, 'records to output.json')
|
||||||
|
})
|
||||||
|
})()
|
25
src/main.ts
25
src/main.ts
|
@ -11,10 +11,10 @@ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
|
||||||
import { planeGeometry } from './plane'
|
import { planeGeometry } from './plane'
|
||||||
import { renderStars, Star } from './stars'
|
import { renderStars, Star } from './stars'
|
||||||
|
|
||||||
function init() {
|
async function init() {
|
||||||
const w = window.innerWidth
|
const w = window.innerWidth
|
||||||
const h = window.innerHeight
|
const h = window.innerHeight
|
||||||
const radius = 50
|
const radius = 5
|
||||||
const infoEl = document.getElementById('info')!
|
const infoEl = document.getElementById('info')!
|
||||||
|
|
||||||
const renderer = new WebGLRenderer({ antialias: true })
|
const renderer = new WebGLRenderer({ antialias: true })
|
||||||
|
@ -24,18 +24,19 @@ function init() {
|
||||||
const camera = new PerspectiveCamera(30, w / h, 0.01, 1001)
|
const camera = new PerspectiveCamera(30, w / h, 0.01, 1001)
|
||||||
camera.position.x = 0
|
camera.position.x = 0
|
||||||
camera.position.y = radius
|
camera.position.y = radius
|
||||||
camera.position.z = radius * 2
|
camera.position.z = radius * 5
|
||||||
|
|
||||||
const controls = new OrbitControls(camera, renderer.domElement)
|
const controls = new OrbitControls(camera, renderer.domElement)
|
||||||
controls.enableZoom = true
|
controls.enableZoom = true
|
||||||
controls.enableRotate = true
|
controls.enableRotate = true
|
||||||
controls.enablePan = true
|
controls.enablePan = true
|
||||||
controls.maxDistance = radius * 2.5
|
controls.maxDistance = radius * 5
|
||||||
controls.minDistance = 0.1
|
controls.minDistance = 0.1
|
||||||
controls.listenToKeyEvents(window)
|
controls.listenToKeyEvents(window)
|
||||||
|
|
||||||
const plane = planeGeometry(radius)
|
const plane = planeGeometry(radius)
|
||||||
const stars = renderStars(radius)
|
const stars = await renderStars(radius)
|
||||||
|
infoEl.innerText = `Currently diplaying ${stars.children.length} stars.`
|
||||||
|
|
||||||
scene.add(stars)
|
scene.add(stars)
|
||||||
scene.add(plane)
|
scene.add(plane)
|
||||||
|
@ -55,7 +56,7 @@ function init() {
|
||||||
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1
|
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1
|
||||||
})
|
})
|
||||||
document.addEventListener('click', () => {
|
document.addEventListener('click', () => {
|
||||||
infoEl.innerText = 'Click a star to get options.'
|
infoEl.innerText = `Currently diplaying ${stars.children.length} stars.`
|
||||||
for (let star of stars.children) {
|
for (let star of stars.children) {
|
||||||
;(star as Star).highlighted = false
|
;(star as Star).highlighted = false
|
||||||
}
|
}
|
||||||
|
@ -100,11 +101,17 @@ function init() {
|
||||||
|
|
||||||
renderer.render(scene, camera)
|
renderer.render(scene, camera)
|
||||||
|
|
||||||
|
const distanceToPlane = camera.position.distanceTo(plane.children[0].position)
|
||||||
|
|
||||||
// update label positions in HTML space
|
// update label positions in HTML space
|
||||||
// Attention: This has to happen after the render call, to avoid flickering
|
// Attention: This has to happen after the render call, to avoid flickering
|
||||||
for (let star of stars.children) {
|
for (let star of stars.children as Star[]) {
|
||||||
;(star as Star).setLabelPos(camera, w, h)
|
star.setLabelPos(camera, w, h)
|
||||||
// set label z-index to distance to make them overlap intuitively
|
if (camera.position.distanceTo(star.coords) > distanceToPlane) {
|
||||||
|
star.dimLabel()
|
||||||
|
} else {
|
||||||
|
star.undimLabel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
35
src/plane.ts
35
src/plane.ts
|
@ -1,9 +1,32 @@
|
||||||
import { BufferGeometry, Group, Line, LineBasicMaterial, Shape, Vector3 } from 'three'
|
import {
|
||||||
|
BufferGeometry,
|
||||||
|
Group,
|
||||||
|
Line,
|
||||||
|
LineBasicMaterial,
|
||||||
|
MeshBasicMaterial,
|
||||||
|
Shape,
|
||||||
|
ShapeGeometry,
|
||||||
|
Mesh,
|
||||||
|
Vector3,
|
||||||
|
DoubleSide,
|
||||||
|
} from 'three'
|
||||||
|
|
||||||
export function planeGeometry(radius: number, n = 5) {
|
export function planeGeometry(radius: number, n = 5) {
|
||||||
const material = new LineBasicMaterial({ color: 0x205020 })
|
const lineMaterial = new LineBasicMaterial({ color: 0x205020 })
|
||||||
|
const shapeMaterial = new MeshBasicMaterial({
|
||||||
|
color: 0x0,
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.8,
|
||||||
|
side: DoubleSide,
|
||||||
|
})
|
||||||
const plane = new Group()
|
const plane = new Group()
|
||||||
|
|
||||||
|
const shape = new Shape()
|
||||||
|
shape.moveTo(0, 0).absarc(0, 0, radius, 0, Math.PI * 2, false)
|
||||||
|
const shapeGeometry = new ShapeGeometry(shape)
|
||||||
|
shapeGeometry.rotateX(Math.PI / 2)
|
||||||
|
plane.add(new Mesh(shapeGeometry, shapeMaterial))
|
||||||
|
|
||||||
const xLine = new BufferGeometry().setFromPoints([
|
const xLine = new BufferGeometry().setFromPoints([
|
||||||
new Vector3(-radius, 0, 0),
|
new Vector3(-radius, 0, 0),
|
||||||
new Vector3(radius, 0, 0),
|
new Vector3(radius, 0, 0),
|
||||||
|
@ -19,9 +42,9 @@ export function planeGeometry(radius: number, n = 5) {
|
||||||
new Vector3(0, 0, radius),
|
new Vector3(0, 0, radius),
|
||||||
])
|
])
|
||||||
|
|
||||||
plane.add(new Line(xLine, material))
|
plane.add(new Line(xLine, lineMaterial))
|
||||||
plane.add(new Line(yLine, material))
|
plane.add(new Line(yLine, lineMaterial))
|
||||||
plane.add(new Line(zLine, material))
|
plane.add(new Line(zLine, lineMaterial))
|
||||||
|
|
||||||
const step = Math.round(radius / n)
|
const step = Math.round(radius / n)
|
||||||
|
|
||||||
|
@ -29,7 +52,7 @@ export function planeGeometry(radius: number, n = 5) {
|
||||||
const shape = new Shape().moveTo(0, r).absarc(0, 0, r, 0, Math.PI * 2, false)
|
const shape = new Shape().moveTo(0, r).absarc(0, 0, r, 0, Math.PI * 2, false)
|
||||||
shape.autoClose = true
|
shape.autoClose = true
|
||||||
const geometry = new BufferGeometry().setFromPoints(shape.getPoints())
|
const geometry = new BufferGeometry().setFromPoints(shape.getPoints())
|
||||||
const line = new Line(geometry, material)
|
const line = new Line(geometry, lineMaterial)
|
||||||
line.rotateX(Math.PI / 2)
|
line.rotateX(Math.PI / 2)
|
||||||
plane.add(line)
|
plane.add(line)
|
||||||
}
|
}
|
||||||
|
|
1
src/stars.json
Normal file
1
src/stars.json
Normal file
File diff suppressed because one or more lines are too long
39
src/stars.ts
39
src/stars.ts
|
@ -27,14 +27,16 @@ export class Star extends Group {
|
||||||
public starData: StarData
|
public starData: StarData
|
||||||
public labelEl = document.createElement('label')
|
public labelEl = document.createElement('label')
|
||||||
|
|
||||||
private coords = new Vector3()
|
private labelDimmed = false
|
||||||
|
|
||||||
|
public coords = new Vector3()
|
||||||
|
|
||||||
private isHighlighted = false
|
private isHighlighted = false
|
||||||
private normalPointSize = 2
|
private normalPointSize: number
|
||||||
private highlightedPointSize = 3
|
private highlightedPointSize: number
|
||||||
|
|
||||||
private lineMaterial = new LineBasicMaterial({ color: 0xffffff })
|
private lineMaterial = new LineBasicMaterial({ color: 0xffffff })
|
||||||
private pointMaterial = new PointsMaterial({ size: this.normalPointSize, vertexColors: true })
|
private pointMaterial = new PointsMaterial({ size: 1, vertexColors: true })
|
||||||
private pointGeometry = new BufferGeometry()
|
private pointGeometry = new BufferGeometry()
|
||||||
|
|
||||||
private whiteColor = new Float32BufferAttribute([255, 255, 255], 3)
|
private whiteColor = new Float32BufferAttribute([255, 255, 255], 3)
|
||||||
|
@ -42,10 +44,13 @@ export class Star extends Group {
|
||||||
|
|
||||||
private point: Points<BufferGeometry, PointsMaterial>
|
private point: Points<BufferGeometry, PointsMaterial>
|
||||||
|
|
||||||
constructor(starData: StarData) {
|
constructor(starData: StarData, maxRadius: number) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
this.starData = starData
|
this.starData = starData
|
||||||
|
this.normalPointSize = maxRadius / 25
|
||||||
|
this.highlightedPointSize = this.normalPointSize * 1.5
|
||||||
|
this.pointMaterial.setValues({ size: this.normalPointSize })
|
||||||
|
|
||||||
const { radius, phi, theta } = starData
|
const { radius, phi, theta } = starData
|
||||||
const sphericalCoords = new Spherical(radius, phi, theta)
|
const sphericalCoords = new Spherical(radius, phi, theta)
|
||||||
|
@ -70,7 +75,8 @@ export class Star extends Group {
|
||||||
|
|
||||||
// label
|
// label
|
||||||
const container = document.getElementById('labels')!
|
const container = document.getElementById('labels')!
|
||||||
this.labelEl.innerText = starData.name
|
// stars with a proper name start with NAME, so lets strip that away
|
||||||
|
this.labelEl.innerText = starData.name.replace(/^NAME /, '')
|
||||||
container.appendChild(this.labelEl)
|
container.appendChild(this.labelEl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,17 +112,34 @@ export class Star extends Group {
|
||||||
pos.y = Math.round((0.5 - pos.y / 2) * (height / dpr))
|
pos.y = Math.round((0.5 - pos.y / 2) * (height / dpr))
|
||||||
|
|
||||||
this.labelEl.style.transform = `translate(${pos.x}px, ${pos.y}px)`
|
this.labelEl.style.transform = `translate(${pos.x}px, ${pos.y}px)`
|
||||||
|
|
||||||
|
if (this.labelDimmed) {
|
||||||
|
this.labelEl.style.zIndex = '0'
|
||||||
|
} else {
|
||||||
const zIndex = `${10000000 - Math.round(pos.z * 10000000)}` // ridiculous
|
const zIndex = `${10000000 - Math.round(pos.z * 10000000)}` // ridiculous
|
||||||
this.labelEl.style.zIndex = zIndex
|
this.labelEl.style.zIndex = zIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderStars(maxRadius: number) {
|
public dimLabel() {
|
||||||
|
this.labelDimmed = true
|
||||||
|
this.labelEl.style.opacity = '0.3'
|
||||||
|
this.labelEl.style.zIndex = '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
public undimLabel() {
|
||||||
|
this.labelEl.style.opacity = '1'
|
||||||
|
this.labelDimmed = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function renderStars(maxRadius: number) {
|
||||||
const group = new Group()
|
const group = new Group()
|
||||||
|
const data: StarData[] = (await import('./stars.json')).default
|
||||||
|
|
||||||
data.forEach((starData) => {
|
data.forEach((starData) => {
|
||||||
if (starData.radius > maxRadius) return
|
if (starData.radius > maxRadius) return
|
||||||
const star = new Star(starData)
|
const star = new Star(starData, maxRadius)
|
||||||
group.add(star)
|
group.add(star)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -383,6 +383,11 @@ cross-spawn@^7.0.2:
|
||||||
shebang-command "^2.0.0"
|
shebang-command "^2.0.0"
|
||||||
which "^2.0.1"
|
which "^2.0.1"
|
||||||
|
|
||||||
|
csv-parse@^5.3.3:
|
||||||
|
version "5.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-5.3.3.tgz#3b75d2279e2edb550cbc54c65b25cbbf3d0033ad"
|
||||||
|
integrity sha512-kEWkAPleNEdhFNkHQpFHu9RYPogsFj3dx6bCxL847fsiLgidzWg0z/O0B1kVWMJUc5ky64zGp18LX2T3DQrOfw==
|
||||||
|
|
||||||
debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
|
debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
|
||||||
version "4.3.4"
|
version "4.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||||
|
|
Loading…
Add table
Reference in a new issue