feat: 新增月掩与日月食地理绘图并提升观测计算精度

- 新增月掩恒星和行星:支持搜索、掩甚点、全球掩带及固定地点轨迹计算
- 支持恒星星表坐标转换、有限盘面行星接触事件和月掩 SVG 输出
- 新增日月食及月掩全球投影图、时间标记和 GeoJSON 地理数据接口
- 扩展日食中心线、南北界及偏食足迹采样,支持极区投影
- 修正站心时角、月出月落、月球视半径、折射和恒星自行计算
- 优化内外行星事件搜索、边界选择、极端输入处理和计算稳定性
This commit is contained in:
2026-08-06 12:00:56 +08:00
parent 25dc7ac0bc
commit 9ee2163cc7
137 changed files with 21770 additions and 1746 deletions
+54 -13
View File
@@ -63,6 +63,9 @@ type SolarEclipsePartialFootprintOptions struct {
// BoundaryPoints 是每个瞬时半影边界的角向采样点数;<=0 时使用 180。
// BoundaryPoints is the angular sample count for each instantaneous penumbral boundary; values <= 0 use 180.
BoundaryPoints int
// CentralShadowStep 是本影/反本影瞬时足迹的采样步长;<=0 时不计算。
// CentralShadowStep is the umbral/antumbral footprint step; values <= 0 disable it.
CentralShadowStep time.Duration
}
// SolarEclipsePartialAreaOptions 是 SolarEclipsePartialFootprintOptions 的兼容别名。
@@ -89,11 +92,29 @@ type SolarEclipsePartialFootprintsInfo struct {
Eclipse SolarEclipseInfo
// Footprints 是按时间采样的瞬时半影足迹, sampled instantaneous penumbral footprints.
Footprints []SolarEclipsePartialFootprint
// CentralShadowFootprints 是按时间采样的本影/反本影足迹。
// CentralShadowFootprints are sampled umbral/antumbral footprints.
CentralShadowFootprints []SolarEclipsePartialFootprint
// P1-P4 是半影与地球的外切/内切接触点;不存在的内切点保持零值。
// P1-P4 are external/internal penumbral contacts; absent internal contacts remain zero.
P1 SolarEclipsePathPoint
P2 SolarEclipsePathPoint
P3 SolarEclipsePathPoint
P4 SolarEclipsePathPoint
// U1-U4 是本影/反本影与地球的外切/内切接触点;不存在时保持零值。
// U1-U4 are external/internal umbral/antumbral contacts; absent contacts remain zero.
U1 SolarEclipsePathPoint
U2 SolarEclipsePathPoint
U3 SolarEclipsePathPoint
U4 SolarEclipsePathPoint
// Step 是实际采用的基础时间采样步长, effective base time step.
Step time.Duration
// BoundaryPoints 是实际采用的边界角向采样点数。
// BoundaryPoints is the effective angular sample count for each boundary.
BoundaryPoints int
// CentralShadowStep 是本影/反本影足迹的实际采样步长;0 表示未计算。
// CentralShadowStep is the effective umbral/antumbral footprint step; zero means disabled.
CentralShadowStep time.Duration
}
// SolarEclipsePartialAreaInfo 是 SolarEclipsePartialFootprintsInfo 的兼容别名。
@@ -103,55 +124,55 @@ type SolarEclipsePartialAreaInfo = SolarEclipsePartialFootprintsInfo
type solarEclipsePathCalculator func(float64, basic.SolarEclipsePathOptions) basic.SolarEclipsePathResult
type solarEclipsePartialFootprintsCalculator func(float64, basic.SolarEclipsePartialFootprintOptions) basic.SolarEclipsePartialFootprintsResult
// SolarEclipseCentralPath 日食中心路径查询 / central solar eclipse path query.
// SolarEclipseCentralPath 计算指定日期附近的日食中心路径,默认使用 NASA bulletin Split-K 模型。
// SolarEclipseCentralPath computes the central path near the given date, using NASA bulletin Split-K by default.
func SolarEclipseCentralPath(date time.Time, options SolarEclipsePathOptions) (SolarEclipsePath, bool) {
return SolarEclipseCentralPathNASABulletinSplitK(date, options)
}
// SolarEclipseCentralPathNASABulletinSplitK 日食中心路径查询(NASA bulletin Split-K / central solar eclipse path query with NASA bulletin Split-K.
// SolarEclipseCentralPathNASABulletinSplitK 使用 NASA bulletin Split-K 模型计算日食中心路径。
// SolarEclipseCentralPathNASABulletinSplitK computes the central path with the NASA bulletin Split-K model.
func SolarEclipseCentralPathNASABulletinSplitK(date time.Time, options SolarEclipsePathOptions) (SolarEclipsePath, bool) {
return solarEclipseCentralPath(date, options, basic.SolarEclipseCentralPathNASABulletinSplitK)
}
// SolarEclipseCentralPathIAUSingleK 日食中心路径查询(IAU Single-K / central solar eclipse path query with IAU Single-K.
// SolarEclipseCentralPathIAUSingleK 使用 IAU Single-K 模型计算日食中心路径。
// SolarEclipseCentralPathIAUSingleK computes the central path with the IAU Single-K model.
func SolarEclipseCentralPathIAUSingleK(date time.Time, options SolarEclipsePathOptions) (SolarEclipsePath, bool) {
return solarEclipseCentralPath(date, options, basic.SolarEclipseCentralPathIAUSingleK)
}
// SolarEclipsePartialFootprints 日食偏食足迹查询 / solar eclipse penumbral footprints query.
// SolarEclipsePartialFootprints 计算指定日期附近的日食半影足迹,默认使用 NASA bulletin Split-K 模型。
// SolarEclipsePartialFootprints computes penumbral footprint samples near the given date, using NASA bulletin Split-K by default.
func SolarEclipsePartialFootprints(date time.Time, options SolarEclipsePartialFootprintOptions) (SolarEclipsePartialFootprintsInfo, bool) {
return SolarEclipsePartialFootprintsNASABulletinSplitK(date, options)
}
// SolarEclipsePartialFootprintsNASABulletinSplitK 日食偏食足迹查询(NASA bulletin Split-K / solar eclipse penumbral footprints query with NASA bulletin Split-K.
// SolarEclipsePartialFootprintsNASABulletinSplitK 使用 NASA bulletin Split-K 模型计算日食半影足迹。
// SolarEclipsePartialFootprintsNASABulletinSplitK computes penumbral footprint samples with the NASA bulletin Split-K model.
func SolarEclipsePartialFootprintsNASABulletinSplitK(date time.Time, options SolarEclipsePartialFootprintOptions) (SolarEclipsePartialFootprintsInfo, bool) {
return solarEclipsePartialFootprints(date, options, basic.SolarEclipsePartialFootprintsNASABulletinSplitK)
}
// SolarEclipsePartialFootprintsIAUSingleK 日食偏食足迹查询(IAU Single-K / solar eclipse penumbral footprints query with IAU Single-K.
// SolarEclipsePartialFootprintsIAUSingleK 使用 IAU Single-K 模型计算日食半影足迹。
// SolarEclipsePartialFootprintsIAUSingleK computes penumbral footprint samples with the IAU Single-K model.
func SolarEclipsePartialFootprintsIAUSingleK(date time.Time, options SolarEclipsePartialFootprintOptions) (SolarEclipsePartialFootprintsInfo, bool) {
return solarEclipsePartialFootprints(date, options, basic.SolarEclipsePartialFootprintsIAUSingleK)
}
// SolarEclipsePartialArea 偏食足迹兼容包装 / compatibility wrapper for penumbral footprints.
// SolarEclipsePartialArea 计算半影足迹,是 SolarEclipsePartialFootprints 的兼容包装。
// SolarEclipsePartialArea computes penumbral footprint samples and is a compatibility wrapper for SolarEclipsePartialFootprints.
func SolarEclipsePartialArea(date time.Time, options SolarEclipsePartialAreaOptions) (SolarEclipsePartialAreaInfo, bool) {
return SolarEclipsePartialFootprints(date, options)
}
// SolarEclipsePartialAreaNASABulletinSplitK 偏食足迹兼容包装(NASA bulletin Split-K / compatibility wrapper for penumbral footprints with NASA bulletin Split-K.
// SolarEclipsePartialAreaNASABulletinSplitK 是 SolarEclipsePartialFootprintsNASABulletinSplitK 的兼容包装。
// SolarEclipsePartialAreaNASABulletinSplitK is a compatibility wrapper for SolarEclipsePartialFootprintsNASABulletinSplitK.
func SolarEclipsePartialAreaNASABulletinSplitK(date time.Time, options SolarEclipsePartialAreaOptions) (SolarEclipsePartialAreaInfo, bool) {
return SolarEclipsePartialFootprintsNASABulletinSplitK(date, options)
}
// SolarEclipsePartialAreaIAUSingleK 偏食足迹兼容包装(IAU Single-K / compatibility wrapper for penumbral footprints with IAU Single-K.
// SolarEclipsePartialAreaIAUSingleK 是 SolarEclipsePartialFootprintsIAUSingleK 的兼容包装。
// SolarEclipsePartialAreaIAUSingleK is a compatibility wrapper for SolarEclipsePartialFootprintsIAUSingleK.
func SolarEclipsePartialAreaIAUSingleK(date time.Time, options SolarEclipsePartialAreaOptions) (SolarEclipsePartialAreaInfo, bool) {
return SolarEclipsePartialFootprintsIAUSingleK(date, options)
@@ -192,10 +213,20 @@ func solarEclipsePartialFootprints(
}
footprints := SolarEclipsePartialFootprintsInfo{
Eclipse: solarEclipseInfoFromBasic(result.Eclipse, location),
Footprints: solarEclipsePartialFootprintsFromBasic(result.Footprints, location),
Step: solarEclipsePathStepDuration(result.StepDays),
BoundaryPoints: result.BoundaryPoints,
Eclipse: solarEclipseInfoFromBasic(result.Eclipse, location),
Footprints: solarEclipsePartialFootprintsFromBasic(result.Footprints, location),
CentralShadowFootprints: solarEclipsePartialFootprintsFromBasic(result.CentralShadowFootprints, location),
P1: solarEclipseOptionalPathPointFromBasic(result.P1, location),
P2: solarEclipseOptionalPathPointFromBasic(result.P2, location),
P3: solarEclipseOptionalPathPointFromBasic(result.P3, location),
P4: solarEclipseOptionalPathPointFromBasic(result.P4, location),
U1: solarEclipseOptionalPathPointFromBasic(result.U1, location),
U2: solarEclipseOptionalPathPointFromBasic(result.U2, location),
U3: solarEclipseOptionalPathPointFromBasic(result.U3, location),
U4: solarEclipseOptionalPathPointFromBasic(result.U4, location),
Step: solarEclipsePathStepDuration(result.StepDays),
BoundaryPoints: result.BoundaryPoints,
CentralShadowStep: solarEclipsePathStepDuration(result.CentralShadowStepDays),
}
return footprints, true
}
@@ -217,6 +248,9 @@ func basicSolarEclipsePartialFootprintOptions(options SolarEclipsePartialFootpri
if options.Step > 0 {
basicOptions.StepDays = options.Step.Hours() / 24
}
if options.CentralShadowStep > 0 {
basicOptions.CentralShadowStepDays = options.CentralShadowStep.Hours() / 24
}
return basicOptions
}
@@ -245,6 +279,13 @@ func solarEclipsePathPointFromBasic(point basic.SolarEclipsePathPoint, location
}
}
func solarEclipseOptionalPathPointFromBasic(point basic.SolarEclipsePathPoint, location *time.Location) SolarEclipsePathPoint {
if point.JDE == 0 {
return SolarEclipsePathPoint{}
}
return solarEclipsePathPointFromBasic(point, location)
}
func solarEclipsePartialFootprintsFromBasic(
footprints []basic.SolarEclipsePartialFootprint,
location *time.Location,