tower / files / tools / bright-stars.mjs
bright-stars.mjs
e331ec2a 2026-09-28 Pavel Safronov | 1 | /** |
| 2 | * Builds src/data/bright-stars.json from the Yale Bright Star Catalogue, 5th revised | |
| 3 | * edition (Hoffleit & Warren 1991, CDS catalogue V/50): every star to about magnitude | |
| 4 | * 6.5, which is every star the naked eye can see from Earth's darkest sites. | |
| 5 | * | |
| 6 | * node tools/bright-stars.mjs | |
| 7 | * | |
| 8 | * Kept is what the sky shader needs and nothing more: J2000 position, V magnitude and | |
| 9 | * B−V colour. The fourteen entries with no position (novae and non-stellar objects the | |
| 10 | * catalogue retired) are dropped; a missing B−V is written as 0.6, a sun-like white. | |
| 11 | */ | |
| 12 | import { writeFileSync } from 'node:fs' | |
| 13 | import { gunzipSync } from 'node:zlib' | |
| 14 | ||
| 15 | const URL_BSC5 = 'https://cdsarc.cds.unistra.fr/ftp/V/50/catalog.gz' | |
| 16 | const OUT = new URL('../src/data/bright-stars.json', import.meta.url) | |
| 17 | ||
| 18 | const res = await fetch(URL_BSC5) | |
| 19 | if (!res.ok) throw new Error(`${URL_BSC5}: ${res.status}`) | |
| 20 | const text = gunzipSync(Buffer.from(await res.arrayBuffer())).toString('latin1') | |
| 21 | ||
| 22 | // Byte ranges from the catalogue's ReadMe, 1-based and inclusive. | |
| 23 | const col = (line, from, to) => line.slice(from - 1, to).trim() | |
| 24 | const stars = [] | |
| 25 | for (const line of text.split('\n')) { | |
| 26 | const rah = col(line, 76, 77) | |
| 27 | if (!rah) continue | |
| 28 | const ra = 15 * (Number(rah) + Number(col(line, 78, 79)) / 60 + Number(col(line, 80, 83)) / 3600) | |
| 29 | const sign = col(line, 84, 84) === '-' ? -1 : 1 | |
| 30 | const dec = sign * (Number(col(line, 85, 86)) + Number(col(line, 87, 88)) / 60 + Number(col(line, 89, 90)) / 3600) | |
| 31 | const vmag = Number(col(line, 103, 107)) | |
| 32 | const bvText = col(line, 110, 114) | |
| 33 | const bv = bvText ? Number(bvText) : 0.6 | |
| 34 | if (![ra, dec, vmag, bv].every(Number.isFinite)) continue | |
| 35 | stars.push(+ra.toFixed(4), +dec.toFixed(4), +vmag.toFixed(2), +bv.toFixed(2)) | |
| 36 | } | |
| 37 | ||
| 38 | writeFileSync(OUT, JSON.stringify({ | |
| 39 | source: 'Yale Bright Star Catalogue, 5th revised ed. (Hoffleit & Warren 1991), CDS V/50', | |
| 40 | fields: ['raDeg', 'decDeg', 'vmag', 'bv'], | |
| 41 | equinox: 'J2000', | |
| 42 | stars, | |
| 43 | }) + '\n') | |
| 44 | console.log(`${stars.length / 4} stars → ${OUT.pathname}`) |