9ee2163cc7
- 新增月掩恒星和行星:支持搜索、掩甚点、全球掩带及固定地点轨迹计算 - 支持恒星星表坐标转换、有限盘面行星接触事件和月掩 SVG 输出 - 新增日月食及月掩全球投影图、时间标记和 GeoJSON 地理数据接口 - 扩展日食中心线、南北界及偏食足迹采样,支持极区投影 - 修正站心时角、月出月落、月球视半径、折射和恒星自行计算 - 优化内外行星事件搜索、边界选择、极端输入处理和计算稳定性
132 lines
4.3 KiB
Go
132 lines
4.3 KiB
Go
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])(星表记录)。
|
|
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"},
|
|
}
|
|
|
|
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
|
|
}
|
|
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
|
|
}
|