feat: 引入可切换星历模型并扩展天象观测链路
- 新增半解析、旧模型、自定义与多源堆叠星历实例,提供 Context、Instance、SPK 读取及状态与视位置计算 - 统一太阳、月球和行星实例接口,扩展黄经穿越、留、相位、最近角距、偕日可见、任意高度升落、轨道节点及凌日等天象查询 - 完善日月食、月掩与凌日的月缘剖面、有限盘面接触、站心修正、局地可见性、全球路径和地图输出 - 新增 SVG、GeoJSON、KML 天象输出及凌日、月掩和月缘地形相关缓存与几何求解 - 新增恒星星表导入与查询,支持 CSV、Hipparcos、BSC5、Stellarium 等格式及名称、交叉标识、锥面检索和星等过滤 - 补充 IAU 2006、地球定向、折射消光、大气观测、轨道传播及半解析行星/月球数据支持 - 将默认未来民用时标切换为 TimeScaleLeapHour,更新 2027–2400 农历速查表、中文日期解析和时区边界处理 - 增加事件基线、跨模型回归、几何边界、月缘地形和输出契约测试,完善中英文手册、示例资源、NOTICE 与忽略规则
This commit is contained in:
@@ -80,7 +80,7 @@ func prepareTopologyPoints(points []GeoPoint) ([]GeoPoint, bool) {
|
||||
normalized := make([]GeoPoint, len(points))
|
||||
copy(normalized, points)
|
||||
for index := range normalized {
|
||||
normalized[index].Longitude = normalizeLongitude(normalized[index].Longitude)
|
||||
normalized[index].Longitude = NormalizeLongitude(normalized[index].Longitude)
|
||||
}
|
||||
return normalized, true
|
||||
}
|
||||
@@ -382,17 +382,17 @@ func hemisphereIntersection(a, b GeoPoint) GeoPoint {
|
||||
firstSign := firstVector.z
|
||||
secondSign := secondVector.z
|
||||
if math.Abs(firstSign) <= 1e-15 {
|
||||
return GeoPoint{Longitude: normalizeLongitude(first.Longitude), Latitude: 0}
|
||||
return GeoPoint{Longitude: NormalizeLongitude(first.Longitude), Latitude: 0}
|
||||
}
|
||||
if math.Abs(secondSign) <= 1e-15 {
|
||||
return GeoPoint{Longitude: normalizeLongitude(second.Longitude), Latitude: 0}
|
||||
return GeoPoint{Longitude: NormalizeLongitude(second.Longitude), Latitude: 0}
|
||||
}
|
||||
left, right := 0.0, 1.0
|
||||
for iteration := 0; iteration < 64; iteration++ {
|
||||
middle := (left + right) / 2
|
||||
point := sphericalInterpolate(first, second, middle)
|
||||
if point.Latitude == 0 || right-left <= 1e-13 {
|
||||
return GeoPoint{Longitude: normalizeLongitude(point.Longitude), Latitude: 0}
|
||||
return GeoPoint{Longitude: NormalizeLongitude(point.Longitude), Latitude: 0}
|
||||
}
|
||||
if point.Latitude*first.Latitude > 0 {
|
||||
left = middle
|
||||
@@ -401,7 +401,7 @@ func hemisphereIntersection(a, b GeoPoint) GeoPoint {
|
||||
}
|
||||
}
|
||||
point := sphericalInterpolate(first, second, (left+right)/2)
|
||||
return GeoPoint{Longitude: normalizeLongitude(point.Longitude), Latitude: 0}
|
||||
return GeoPoint{Longitude: NormalizeLongitude(point.Longitude), Latitude: 0}
|
||||
}
|
||||
|
||||
func sphericalLongitudeIntersection(a, b GeoPoint, boundary, adjustedLongitude float64) GeoPoint {
|
||||
@@ -434,14 +434,6 @@ func sphericalLongitudeIntersection(a, b GeoPoint, boundary, adjustedLongitude f
|
||||
return GeoPoint{Longitude: boundary, Latitude: point.Latitude}
|
||||
}
|
||||
|
||||
func normalizeLongitude(value float64) float64 {
|
||||
value = math.Mod(value+180, 360)
|
||||
if value < 0 {
|
||||
value += 360
|
||||
}
|
||||
return value - 180
|
||||
}
|
||||
|
||||
// equirectangularSeamShift 返回把等经纬接缝从 ±180 搬到视图中心对面所需的经度旋转量。
|
||||
// 视图中心为 0 时返回 0,调用方即可沿用未旋转的原有路径,保证既有输出逐字节不变。
|
||||
func equirectangularSeamShift(view ClipView) float64 {
|
||||
@@ -473,7 +465,7 @@ func rotateLongitudes(points []GeoPoint, shift float64) []GeoPoint {
|
||||
rotated := make([]GeoPoint, len(points))
|
||||
copy(rotated, points)
|
||||
for index := range rotated {
|
||||
rotated[index].Longitude = normalizeLongitude180(rotated[index].Longitude + shift)
|
||||
rotated[index].Longitude = NormalizeLongitude(rotated[index].Longitude + shift)
|
||||
}
|
||||
return rotated
|
||||
}
|
||||
@@ -493,11 +485,3 @@ func unshiftLongitudesInPlace(points []GeoPoint, shift float64) {
|
||||
points[index].Longitude = value
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeLongitude180(longitude float64) float64 {
|
||||
value := math.Mod(longitude+180, 360)
|
||||
if value < 0 {
|
||||
value += 360
|
||||
}
|
||||
return value - 180
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user