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

59 lines
2.6 KiB
Go

package geojson
import (
"fmt"
"time"
"b612.me/astro/basic"
)
func marshalPlanetTransitPartial(input planetTransitInput, options PlanetTransitOptions, scale basic.TimeScale, withBase func(map[string]interface{}) map[string]interface{}, module *Generator) ([]byte, error) {
result := planetTransitResultOf(input)
label := func(value time.Time) string { return formatTime(basic.LabelIn(scale, value.UTC())) }
features := make([]feature, 0, 4)
if !skippedLunarRole(options.SkipRoles, "transit-partial") {
columns := basic.PlanetTransitVisibilityColumnsWithInstance(result, module.inst)
longitudes := make([]float64, len(columns))
intervals := make([][]lunarLatitudeInterval, len(columns))
for index, column := range columns {
longitudes[index] = column.Longitude
for _, interval := range column.Intervals {
intervals[index] = append(intervals[index], lunarLatitudeInterval{low: interval[0], high: interval[1]})
}
}
value, err := planetTransitRegionGeometry(longitudes, intervals)
if err != nil {
return nil, fmt.Errorf("geojson: partial transit: %w", err)
}
features = append(features, newFeature(planetTransitEvent, "transit-partial", value,
withBase(map[string]interface{}{"longitude_step_degrees": 2, "latitude_sample_degrees": 1})))
}
if options.IsochroneStep > 0 {
lines, err := planetTransitIsochroneFeatures(input, options.IsochroneStep, scale, options.SkipRoles, withBase, module)
if err != nil {
return nil, err
}
features = append(features, lines...)
}
point := solarSubsolarPoint(input.greatest, module)
var err error
features, err = appendPointFeature(features, planetTransitEvent, "greatest",
pathSample{Time: basic.LabelIn(scale, input.greatest.UTC()), Longitude: point.Longitude, Latitude: point.Latitude},
withBase(map[string]interface{}{"greatest": label(input.greatest), "window_start": label(input.windowStart), "window_end": label(input.windowEnd),
"minimum_separation_arcsec": input.separation, "sun_semidiameter_arcsec": input.sunRadius, "planet_semidiameter_arcsec": input.planetRad}))
if err != nil {
return nil, err
}
if options.TimeMarkers != nil {
markers, markerErr := planetTransitTimeMarkerSamples(input.windowStart, input.windowEnd, scale, *options.TimeMarkers, module)
if markerErr != nil {
return nil, markerErr
}
features, err = appendTimeMarkerPointFeatures(features, planetTransitEvent, "subsolar-track", markers, options.TimeMarkers.Location)
if err != nil {
return nil, err
}
}
return marshalFeatureCollectionWithTimeScale(dropFeaturesByRole(features, options.SkipRoles), scale)
}