feat: 完善水星与金星全球凌日搜索及制图导出
- 基于平均下合周期与节点相位预筛候选,减少无效星历计算;跳过无法求解的单个会合周期,避免有限覆盖星历导致搜索提前终止 - 引入影轴 γ、半影半径及地球尺度几何判定,结合站心可见性识别地心无接触、仅部分地区可见的掠凌 - 添加金星 243 年、水星 46 年周期族编号,并明确编号适用范围及未分配时的零值语义 - 为 SVG、GeoJSON 和 KML 增加站心部分凌日可见区,适配接触等时线、几何元数据、图层样式及取景;为地心无接触凌日事件增加正射图,按可见区球面面积加权居中
This commit is contained in:
41 files changed
+1554
-307
No files matched your search
@@ -0,0 +1,79 @@
|
||||
package basic
|
||||
|
||||
import "math"
|
||||
|
||||
// PlanetTransitVisibilityColumn 子午线上的可见纬度区间,端点单位为度 / visible latitude intervals on a meridian, in degrees.
|
||||
type PlanetTransitVisibilityColumn struct {
|
||||
Longitude float64
|
||||
Intervals [][2]float64
|
||||
}
|
||||
|
||||
// PlanetTransitVisibilityColumnsWithInstance 按 2° 经度、1° 纬度探测站心可见区并细化边界 / sample topocentric visibility at 2-degree longitude and 1-degree latitude spacing and refine boundaries.
|
||||
func PlanetTransitVisibilityColumnsWithInstance(transit PlanetTransitResult, inst *Instance) []PlanetTransitVisibilityColumn {
|
||||
snapshot, ok := newPlanetTransitSnapshot(transit, inst)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
snapshot.visibilityOnce.Do(func() {
|
||||
for column := 0; column <= 180; column++ {
|
||||
longitude := -180 + float64(column)*2
|
||||
visible := func(latitude float64) bool {
|
||||
local := snapshot.local(transit, Observer{Longitude: longitude, Latitude: latitude})
|
||||
return local.Valid && local.Visible
|
||||
}
|
||||
value := PlanetTransitVisibilityColumn{Longitude: longitude}
|
||||
previous, start := visible(-90), -90.0
|
||||
for latitude := -89.0; latitude <= 90; latitude++ {
|
||||
current := visible(latitude)
|
||||
if current != previous {
|
||||
left, right := latitude-1, latitude
|
||||
for right-left > 0.0001 {
|
||||
middle := (left + right) / 2
|
||||
if visible(middle) == previous {
|
||||
left = middle
|
||||
} else {
|
||||
right = middle
|
||||
}
|
||||
}
|
||||
boundary := (left + right) / 2
|
||||
if current {
|
||||
start = boundary
|
||||
} else {
|
||||
value.Intervals = append(value.Intervals, [2]float64{start, boundary})
|
||||
}
|
||||
}
|
||||
previous = current
|
||||
}
|
||||
if previous {
|
||||
value.Intervals = append(value.Intervals, [2]float64{start, 90})
|
||||
}
|
||||
snapshot.visibility = append(snapshot.visibility, value)
|
||||
}
|
||||
})
|
||||
result := make([]PlanetTransitVisibilityColumn, len(snapshot.visibility))
|
||||
for index, column := range snapshot.visibility {
|
||||
result[index] = PlanetTransitVisibilityColumn{Longitude: column.Longitude, Intervals: append([][2]float64(nil), column.Intervals...)}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// PlanetTransitVisibilityPolygonsWithInstance 可见区的经度条带多边形 / longitude-strip polygons of the visible region.
|
||||
func PlanetTransitVisibilityPolygonsWithInstance(transit PlanetTransitResult, inst *Instance) [][]PlanetTransitIsochronePoint {
|
||||
columns := PlanetTransitVisibilityColumnsWithInstance(transit, inst)
|
||||
var result [][]PlanetTransitIsochronePoint
|
||||
for index := 1; index < len(columns); index++ {
|
||||
left, right := columns[index-1], columns[index]
|
||||
for _, interval := range left.Intervals {
|
||||
for _, other := range right.Intervals {
|
||||
if math.Min(interval[1], other[1]) <= math.Max(interval[0], other[0]) {
|
||||
continue
|
||||
}
|
||||
result = append(result, []PlanetTransitIsochronePoint{
|
||||
{Longitude: left.Longitude, Latitude: interval[0]}, {Longitude: right.Longitude, Latitude: other[0]},
|
||||
{Longitude: right.Longitude, Latitude: other[1]}, {Longitude: left.Longitude, Latitude: interval[1]},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in new issue
Block a user