Files
astro/basic/star_catalog_data.go
T

132 lines
4.3 KiB
Go
Raw Normal View History

2026-05-01 22:38:44 +08:00
package basic
import (
"bytes"
"compress/gzip"
_ "embed"
"encoding/binary"
"fmt"
"io"
)
// star_catalog.dat gzip 解压后的布局 / star_catalog.dat layout after gzip decompression:
// magic[8] | version[1] | rawDataLen[4] | rawData | stringCount[2](字符串计数) |
// repeated(stringLen[uvarint] + stringBytes)(字符串表) |
// maxHR[2] | repeated(maxHR * 6 * stringIndex[2]) | repeated(maxHR * hip[4])(星表记录)。
2026-05-01 22:38:44 +08:00
const starCatalogMagic = "STRCAT01"
//go:embed star_catalog.dat
var starCatalogCompressed []byte
// supplementalStarDetails 保存嵌入载荷没有对应命名条目的星表元数据 / supplementalStarDetails contains catalog metadata that is maintained in
// 源码形式 / source form when the embedded payload has no corresponding named entry.
// 六个字段按编码顺序排列:中文名、别名、拜耳命名、通用名、中文星座和 IAU 星座 / The six fields follow the encoded detail order: Chinese name, alias, Bayer
// 命名、通用名、中文星座和 IAU 星座 / designation, common name, Chinese constellation, and IAU constellation.
var supplementalStarDetails = map[uint16][]string{
4799: {"进贤增九", "", "室女座25", "", "室女座", "Virgo"},
}
2026-05-01 22:38:44 +08:00
func initStarCatalogData() []byte {
reader, err := gzip.NewReader(bytes.NewReader(starCatalogCompressed))
if err != nil {
panic(err)
}
defer reader.Close()
payload, err := io.ReadAll(reader)
if err != nil {
panic(err)
}
data, detail, hip, err := decodeStarCatalogPayload(payload)
if err != nil {
panic(err)
}
for hr, record := range supplementalStarDetails {
detail[hr] = record
}
2026-05-01 22:38:44 +08:00
hr2detail = detail
hr2hip = hip
return data
}
func decodeStarCatalogPayload(payload []byte) ([]byte, map[uint16][]string, map[uint16]uint32, error) {
reader := bytes.NewReader(payload)
var magic [len(starCatalogMagic)]byte
if _, err := io.ReadFull(reader, magic[:]); err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog magic: %w", err)
}
if string(magic[:]) != starCatalogMagic {
return nil, nil, nil, fmt.Errorf("invalid star catalog magic %q", string(magic[:]))
}
version, err := reader.ReadByte()
if err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog version: %w", err)
}
if version != 1 {
return nil, nil, nil, fmt.Errorf("unsupported star catalog version %d", version)
}
var rawLen uint32
if err := binary.Read(reader, binary.LittleEndian, &rawLen); err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog data length: %w", err)
}
data := make([]byte, rawLen)
if _, err := io.ReadFull(reader, data); err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog data: %w", err)
}
var stringCount uint16
if err := binary.Read(reader, binary.LittleEndian, &stringCount); err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog string count: %w", err)
}
stringsTable := make([]string, int(stringCount)+1)
for i := 1; i < len(stringsTable); i++ {
length, err := binary.ReadUvarint(reader)
if err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog string length: %w", err)
}
value := make([]byte, length)
if _, err := io.ReadFull(reader, value); err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog string: %w", err)
}
stringsTable[i] = string(value)
}
var maxHR uint16
if err := binary.Read(reader, binary.LittleEndian, &maxHR); err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog max HR: %w", err)
}
detail := make(map[uint16][]string)
for hr := uint16(1); hr <= maxHR; hr++ {
record := make([]string, 6)
hasValue := false
for i := range record {
var index uint16
if err := binary.Read(reader, binary.LittleEndian, &index); err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog detail index: %w", err)
}
if int(index) >= len(stringsTable) {
return nil, nil, nil, fmt.Errorf("detail string index out of range: hr=%d index=%d", hr, index)
}
record[i] = stringsTable[index]
hasValue = hasValue || index != 0
}
if hasValue {
detail[hr] = record
}
}
hip := make(map[uint16]uint32)
for hr := uint16(1); hr <= maxHR; hr++ {
var value uint32
if err := binary.Read(reader, binary.LittleEndian, &value); err != nil {
return nil, nil, nil, fmt.Errorf("read star catalog HIP: %w", err)
}
if value != 0 {
hip[hr] = value
}
}
return data, detail, hip, nil
}