feat: 完善日月食与月掩几何链路并扩展历法接口
- 新增日月食中心带、偏食带、阴影足迹、等时线、食分线及升落边界计算,支持极区与混合食拓扑 - 新增日食单时刻阴影求解器、站心状态查询、批量采样和 ΔT 覆盖接口 - 重构恒星与行星月掩路径,补充有限盘面接触、站心修正、掩带宽度、极区投影及升落边界 - 扩展 SVG 与 GeoJSON 输出,支持详细面板、全球/极区/地球投影、边界闭合、时间标记和拓扑签名 - 扩展日月食候选搜索、局地搜索、沙罗序列预计算与范围外推,补充系列锚点和成员一致性校验 - 补齐古历纪年、儒略历独有闰日、多公历候选、历法改革跨日及精确日期运算接口 - 优化 ΔT、章动、恒星时、月球地平线、事件根搜索和本地星历缓存,降低重复计算开销并提升边界稳定
This commit is contained in:
+16
-58
@@ -240,40 +240,12 @@ func starOccultationLatitudeEnvelopePass(startTT, endTT float64, star StarCoordi
|
||||
return minimumLatitude <= limit && maximumLatitude >= -limit
|
||||
}
|
||||
|
||||
func starOccultationGeocentricLongitudeCandidate(startTT, endTT, step float64, star StarCoordinate) float64 {
|
||||
bestTT := math.NaN()
|
||||
bestDelta := math.Inf(1)
|
||||
for tt := startTT; tt <= endTT; tt += step {
|
||||
delta := math.Abs(signedAngleDifference(HMoonTrueLoN(tt, 8), starOccultationGeocentricStarLongitude(tt, star)))
|
||||
if delta < bestDelta {
|
||||
bestDelta = delta
|
||||
bestTT = tt
|
||||
}
|
||||
}
|
||||
if endTT > startTT {
|
||||
delta := math.Abs(signedAngleDifference(HMoonTrueLoN(endTT, 8), starOccultationGeocentricStarLongitude(endTT, star)))
|
||||
if delta < bestDelta {
|
||||
bestTT = endTT
|
||||
}
|
||||
}
|
||||
return bestTT
|
||||
}
|
||||
|
||||
func starOccultationGeocentricStarLongitude(tt float64, star StarCoordinate) float64 {
|
||||
ra, dec := starApparentRaDecGeocentric(tt, star)
|
||||
longitude, _ := RaDecToLoBo(tt, ra, dec)
|
||||
return longitude
|
||||
}
|
||||
|
||||
func starOccultationMinimizeGeocentricSeparation(seed, startTT, endTT float64, star StarCoordinate) float64 {
|
||||
halfWindow := 0.75
|
||||
left := math.Max(startTT, seed-halfWindow)
|
||||
right := math.Min(endTT, seed+halfWindow)
|
||||
return starOccultationMinimizeValue(left, right, func(tt float64) float64 {
|
||||
return starOccultationGeocentricSeparationArcsec(tt, star)
|
||||
})
|
||||
}
|
||||
|
||||
func starOccultationMinimizeValue(left, right float64, value func(float64) float64) float64 {
|
||||
if right <= left {
|
||||
return left
|
||||
@@ -321,7 +293,15 @@ func starOccultationBestObserver(seedTT, startTT, endTT float64, star StarCoordi
|
||||
frameAt := func(tt float64) (occultationPathFrame, bool) {
|
||||
return starOccultationPathFrameAt(tt, star)
|
||||
}
|
||||
point, pointOK = occultationPathBoundaryPointForFrame(greatestTT, frameAt, time.UTC)
|
||||
// 同行星最佳事件搜索:非中心路径的最佳站心取离影轴最近的椭球点,
|
||||
// 外接触切点位于掩带边缘,只作最后回退。
|
||||
// Same as the planetary best-event search: for a non-central path the
|
||||
// best station is the ellipsoid point nearest to the shadow axis, while
|
||||
// the outer contact tangent on the band edge stays the last resort.
|
||||
point, pointOK = occultationPathTrackPointForFrame(greatestTT, frameAt, time.UTC)
|
||||
if !pointOK {
|
||||
point, pointOK = occultationPathBoundaryPointForFrame(greatestTT, frameAt, time.UTC)
|
||||
}
|
||||
}
|
||||
if !pointOK {
|
||||
return 0, Observer{}, 0, false
|
||||
@@ -531,25 +511,6 @@ func starAnnualParallaxEcliptic(tt, longitude, latitude, parallaxMas float64) (f
|
||||
return normalizeRA(longitude), latitude
|
||||
}
|
||||
|
||||
func starOccultationLongitudeCandidate(startTT, endTT, step float64, star StarCoordinate, observer Observer) float64 {
|
||||
bestTT := math.NaN()
|
||||
bestDelta := math.Inf(1)
|
||||
for tt := startTT; tt <= endTT; tt += step {
|
||||
delta := starOccultationLongitudeDistance(tt, star, observer)
|
||||
if delta < bestDelta {
|
||||
bestDelta = delta
|
||||
bestTT = tt
|
||||
}
|
||||
}
|
||||
if endTT > startTT {
|
||||
delta := starOccultationLongitudeDistance(endTT, star, observer)
|
||||
if delta < bestDelta {
|
||||
bestTT = endTT
|
||||
}
|
||||
}
|
||||
return bestTT
|
||||
}
|
||||
|
||||
func starOccultationLongitudeDistance(tt float64, star StarCoordinate, observer Observer) float64 {
|
||||
moonLongitude := HMoonTrueLoN(tt, 8)
|
||||
starRA, starDec := starApparentRaDec(tt, star, observer)
|
||||
@@ -557,15 +518,6 @@ func starOccultationLongitudeDistance(tt float64, star StarCoordinate, observer
|
||||
return math.Abs(signedAngleDifference(moonLongitude, starLongitude))
|
||||
}
|
||||
|
||||
func starOccultationMinimizeSeparation(seed, startTT, endTT float64, star StarCoordinate, observer Observer) float64 {
|
||||
halfWindow := 0.75
|
||||
left := math.Max(startTT, seed-halfWindow)
|
||||
right := math.Min(endTT, seed+halfWindow)
|
||||
return starOccultationMinimizeValue(left, right, func(tt float64) float64 {
|
||||
return starMoonSeparationArcsec(tt, star, observer)
|
||||
})
|
||||
}
|
||||
|
||||
func starMoonSeparationArcsec(tt float64, star StarCoordinate, observer Observer) float64 {
|
||||
position := starMoonPositionAt(tt, star, observer)
|
||||
if !position.valid {
|
||||
@@ -675,7 +627,13 @@ func occultationPositionAngle(moonRA, moonDec, starRA, starDec float64) float64
|
||||
}
|
||||
|
||||
func occultationAltitude(tt float64, observer Observer, ra, dec float64) float64 {
|
||||
hourAngle := signedAngleDifference(ApparentSiderealTime(TD2UT(tt, false))*15+observer.Longitude, ra) * math.Pi / 180
|
||||
return occultationAltitudeWithSidereal(
|
||||
ApparentSiderealTime(TD2UT(tt, false))*15, observer, ra, dec,
|
||||
)
|
||||
}
|
||||
|
||||
func occultationAltitudeWithSidereal(siderealDegrees float64, observer Observer, ra, dec float64) float64 {
|
||||
hourAngle := signedAngleDifference(siderealDegrees+observer.Longitude, ra) * math.Pi / 180
|
||||
lat := observer.Latitude * math.Pi / 180
|
||||
declination := dec * math.Pi / 180
|
||||
sinAltitude := math.Sin(lat)*math.Sin(declination) + math.Cos(lat)*math.Cos(declination)*math.Cos(hourAngle)
|
||||
|
||||
Reference in New Issue
Block a user