Files
astro/basic/planet_transit_prediction.go
T
b612 ccf5880269 feat: 完善水星与金星全球凌日搜索及制图导出
- 基于平均下合周期与节点相位预筛候选,减少无效星历计算;跳过无法求解的单个会合周期,避免有限覆盖星历导致搜索提前终止
- 引入影轴 γ、半影半径及地球尺度几何判定,结合站心可见性识别地心无接触、仅部分地区可见的掠凌
- 添加金星 243 年、水星 46 年周期族编号,并明确编号适用范围及未分配时的零值语义
- 为 SVG、GeoJSON 和 KML 增加站心部分凌日可见区,适配接触等时线、几何元数据、图层样式及取景;为地心无接触凌日事件增加正射图,按可见区球面面积加权居中
2026-10-20 22:35:39 +08:00

70 lines
2.6 KiB
Go

package basic
import (
"math"
"b612.me/astro/internal/ephem"
)
func planetTransitPredictedSeason(seedTT float64, cfg planetTransitConfig, inst *Instance) bool {
centuries := (seedTT - 2451545) / 36525
if inst != nil && inst.Model() == ephem.Custom || centuries < -40 || centuries > 20 {
return true
}
node := 76.679920 + centuries*(0.9011206+centuries*(0.00040618-0.000000093*centuries))
if cfg.planetIndex == 1 {
node = 48.330893 + centuries*(1.1861883+centuries*(0.00017542+0.000000215*centuries))
}
solar := 280.46646 + centuries*(36000.76983+0.0003032*centuries)
phase := math.Abs(math.Remainder(solar-node, 180))
return phase <= 24
}
func planetTransitCoarseConjunction(seedTT float64, cfg planetTransitConfig, inst *Instance) float64 {
current := seedTT
for iteration := 0; iteration < 5; iteration++ {
value := planetTransitLongitudeDeltaN(current, cfg, planetTransitCoarseN, inst)
slope := (planetTransitLongitudeDeltaN(current+0.02, cfg, planetTransitCoarseN, inst) -
planetTransitLongitudeDeltaN(current-0.02, cfg, planetTransitCoarseN, inst)) / 0.04
if !isFiniteFloat(slope) || slope == 0 {
return math.NaN()
}
step := value / slope
current -= step
if math.Abs(step) < 0.0001 {
break
}
}
return current
}
// PlanetTransitSeries 凌日周期族,Number 为零表示超出编号适用范围 / transit family; a zero Number means unassigned.
type PlanetTransitSeries struct {
Number int
PeriodYears int
}
func planetTransitSeriesAt(greatestTT float64, cfg planetTransitConfig) PlanetTransitSeries {
period, synodicCycles := 243, 152
firstYear, lastYear := -2000, 4000
anchors := [][4]int{{-1892, 5, 21, 1}, {-1998, 11, 18, 2}, {-1884, 5, 19, 3}, {-1763, 11, 20, 4}, {554, 5, 22, 5}, {1631, 12, 7, 6}}
if cfg.planetIndex == 1 {
period, synodicCycles = 46, 145
firstYear, lastYear = 1601, 2300
anchors = [][4]int{{1644, 11, 9, 1}, {1631, 11, 7, 2}, {1628, 5, 5, 3}, {1618, 11, 4, 4}, {1615, 5, 3, 5}, {1605, 11, 1, 6}, {1740, 5, 2, 7}, {1776, 11, 2, 8}, {1957, 5, 6, 9}, {1993, 11, 6, 10}, {2174, 5, 8, 11}, {2210, 11, 9, 12}}
}
result := PlanetTransitSeries{PeriodYears: period}
if greatestTT < JDCalc(firstYear, 1, 1) || greatestTT >= JDCalc(lastYear+1, 1, 1) {
return result
}
cycle := int(math.Round((greatestTT - cfg.anchorInferiorTT) / cfg.synodicPeriodDays))
for _, anchor := range anchors {
anchorCycle := int(math.Round((JDCalc(anchor[0], anchor[1], float64(anchor[2])) - cfg.anchorInferiorTT) / cfg.synodicPeriodDays))
if (cycle-anchorCycle)%synodicCycles == 0 {
result.Number = anchor[3]
return result
}
}
return result
}