feat: 完善日月食与月掩几何链路并扩展历法接口
- 新增日月食中心带、偏食带、阴影足迹、等时线、食分线及升落边界计算,支持极区与混合食拓扑 - 新增日食单时刻阴影求解器、站心状态查询、批量采样和 ΔT 覆盖接口 - 重构恒星与行星月掩路径,补充有限盘面接触、站心修正、掩带宽度、极区投影及升落边界 - 扩展 SVG 与 GeoJSON 输出,支持详细面板、全球/极区/地球投影、边界闭合、时间标记和拓扑签名 - 扩展日月食候选搜索、局地搜索、沙罗序列预计算与范围外推,补充系列锚点和成员一致性校验 - 补齐古历纪年、儒略历独有闰日、多公历候选、历法改革跨日及精确日期运算接口 - 优化 ΔT、章动、恒星时、月球地平线、事件根搜索和本地星历缓存,降低重复计算开销并提升边界稳定
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package svg
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
|
||||
"b612.me/astro/internal/geodata"
|
||||
"b612.me/astro/moon"
|
||||
)
|
||||
|
||||
// occultationBandPolygons 是一次紧凑掩带合并的只读结果。
|
||||
type occultationBandPolygons struct {
|
||||
polygons [][]geodata.GeoPoint
|
||||
authoritative bool
|
||||
}
|
||||
|
||||
type occultationBandCacheKey struct {
|
||||
kind occultationFootprintSweepKind
|
||||
digest [2]uint64
|
||||
}
|
||||
|
||||
// occultationBandCacheCapacity 限制常驻的合并结果数量;掩带多边形可能上万点。
|
||||
const occultationBandCacheCapacity = 6
|
||||
|
||||
var occultationBandCache = struct {
|
||||
sync.RWMutex
|
||||
entries map[occultationBandCacheKey]occultationBandPolygons
|
||||
order []occultationBandCacheKey
|
||||
}{entries: make(map[occultationBandCacheKey]occultationBandPolygons, occultationBandCacheCapacity)}
|
||||
|
||||
func lookupOccultationBandPolygons(key occultationBandCacheKey) (occultationBandPolygons, bool) {
|
||||
occultationBandCache.RLock()
|
||||
value, ok := occultationBandCache.entries[key]
|
||||
occultationBandCache.RUnlock()
|
||||
return value, ok
|
||||
}
|
||||
|
||||
func storeOccultationBandPolygons(key occultationBandCacheKey, value occultationBandPolygons) {
|
||||
occultationBandCache.Lock()
|
||||
defer occultationBandCache.Unlock()
|
||||
if _, exists := occultationBandCache.entries[key]; exists {
|
||||
return
|
||||
}
|
||||
if len(occultationBandCache.order) >= occultationBandCacheCapacity {
|
||||
delete(occultationBandCache.entries, occultationBandCache.order[0])
|
||||
occultationBandCache.order = occultationBandCache.order[1:]
|
||||
}
|
||||
occultationBandCache.entries[key] = value
|
||||
occultationBandCache.order = append(occultationBandCache.order, key)
|
||||
}
|
||||
|
||||
// occultationBandDigest 汇总合并的全部输入;按 64 位字混合而不是逐字节,摘要成本必须远低于合并本身。
|
||||
func occultationBandDigest(s occultationFootprintSweep) [2]uint64 {
|
||||
const (
|
||||
seed1 = 0x9e3779b97f4a7c15
|
||||
seed2 = 0xc2b2ae3d27d4eb4f
|
||||
prime = 0x100000001b3
|
||||
)
|
||||
first, second := uint64(seed1), uint64(seed2)
|
||||
write := func(value uint64) {
|
||||
first = (first ^ value) * prime
|
||||
first ^= first >> 31
|
||||
second = (second + value) * prime
|
||||
second ^= second >> 33
|
||||
}
|
||||
writeFloat := func(value float64) { write(math.Float64bits(value)) }
|
||||
writeTime := func(value int64) { write(uint64(value)) }
|
||||
writePoint := func(point moon.OccultationPathPoint) {
|
||||
writeTime(point.Time.UnixNano())
|
||||
writeFloat(point.Longitude)
|
||||
writeFloat(point.Latitude)
|
||||
writeFloat(point.MoonAltitude)
|
||||
writeFloat(point.WidthKM)
|
||||
writeFloat(point.LimitSeparationKM)
|
||||
}
|
||||
writePolygons := func(polygons [][]moon.OccultationPathPoint) {
|
||||
write(uint64(len(polygons)))
|
||||
for _, polygon := range polygons {
|
||||
write(uint64(len(polygon)))
|
||||
for _, point := range polygon {
|
||||
writePoint(point)
|
||||
}
|
||||
}
|
||||
}
|
||||
writeString := func(value string) {
|
||||
write(uint64(len(value)))
|
||||
for index := 0; index < len(value); index++ {
|
||||
write(uint64(value[index]))
|
||||
}
|
||||
}
|
||||
writeFootprints := func(footprints []moon.PlanetOccultationFootprint) {
|
||||
write(uint64(len(footprints)))
|
||||
for _, footprint := range footprints {
|
||||
writeTime(footprint.Time.UnixNano())
|
||||
writePolygons(footprint.Polygons)
|
||||
writePolygons(footprint.InteriorPolygons)
|
||||
writePolygons(footprint.Boundaries)
|
||||
if footprint.Closed {
|
||||
write(1)
|
||||
} else {
|
||||
write(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
writeCurves := func(curves []moon.OccultationRiseSetCurve) {
|
||||
write(uint64(len(curves)))
|
||||
for _, curve := range curves {
|
||||
writeString(string(curve.Phase))
|
||||
writeString(string(curve.Direction))
|
||||
writePolygons(curve.Segments)
|
||||
}
|
||||
}
|
||||
write(uint64(s.kind))
|
||||
writeFootprints(s.footprints)
|
||||
writePolygons(s.contours)
|
||||
writePolygons(s.visibilityContours)
|
||||
writePolygons([][]moon.OccultationPathPoint{s.northern, s.southern})
|
||||
writeCurves(s.curves)
|
||||
return [2]uint64{first, second}
|
||||
}
|
||||
Reference in New Issue
Block a user