feat: 引入可切换星历模型并扩展天象观测链路
- 新增半解析、旧模型、自定义与多源堆叠星历实例,提供 Context、Instance、SPK 读取及状态与视位置计算 - 统一太阳、月球和行星实例接口,扩展黄经穿越、留、相位、最近角距、偕日可见、任意高度升落、轨道节点及凌日等天象查询 - 完善日月食、月掩与凌日的月缘剖面、有限盘面接触、站心修正、局地可见性、全球路径和地图输出 - 新增 SVG、GeoJSON、KML 天象输出及凌日、月掩和月缘地形相关缓存与几何求解 - 新增恒星星表导入与查询,支持 CSV、Hipparcos、BSC5、Stellarium 等格式及名称、交叉标识、锥面检索和星等过滤 - 补充 IAU 2006、地球定向、折射消光、大气观测、轨道传播及半解析行星/月球数据支持 - 将默认未来民用时标切换为 TimeScaleLeapHour,更新 2027–2400 农历速查表、中文日期解析和时区边界处理 - 增加事件基线、跨模型回归、几何边界、月缘地形和输出契约测试,完善中英文手册、示例资源、NOTICE 与忽略规则
This commit is contained in:
@@ -103,7 +103,7 @@ func newVisibleLineworkArcIndex(lines [][]GeoPoint) visibleLineworkArcIndex {
|
||||
|
||||
func (index visibleLineworkArcIndex) pointDistanceKM(point GeoPoint) float64 {
|
||||
if source, ok := index.vertices[visibleLineworkIndexPointKey(point)]; ok {
|
||||
return geoPointDistanceKM(point, source)
|
||||
return EquatorialDistanceKM(point, source)
|
||||
}
|
||||
pointVector := geoPointVector(point)
|
||||
minimum := math.Inf(1)
|
||||
@@ -130,10 +130,10 @@ func (index visibleLineworkArcIndex) edgePointDistanceKM(
|
||||
matched := false
|
||||
for _, arcIndex := range arcIndices {
|
||||
arc := index.arcs[arcIndex]
|
||||
direct := geoPointDistanceKM(first, arc.start) <= 0.001 &&
|
||||
geoPointDistanceKM(second, arc.end) <= 0.001
|
||||
reverse := geoPointDistanceKM(first, arc.end) <= 0.001 &&
|
||||
geoPointDistanceKM(second, arc.start) <= 0.001
|
||||
direct := EquatorialDistanceKM(first, arc.start) <= 0.001 &&
|
||||
EquatorialDistanceKM(second, arc.end) <= 0.001
|
||||
reverse := EquatorialDistanceKM(first, arc.end) <= 0.001 &&
|
||||
EquatorialDistanceKM(second, arc.start) <= 0.001
|
||||
if !direct && !reverse {
|
||||
continue
|
||||
}
|
||||
@@ -151,12 +151,12 @@ func (arc visibleLineworkArc) pointDistanceKM(point GeoPoint, pointVector geoVec
|
||||
for _, candidate := range []geoVector3{projected, geoVectorScale(projected, -1)} {
|
||||
if sphericalPointOnArcVectors(candidate, arc.startVector, arc.endVector, arc.arcRadians) {
|
||||
angle := math.Acos(math.Max(-1, math.Min(1, geoVectorDot(pointVector, candidate))))
|
||||
return angle * 6378.1366
|
||||
return angle * EarthEquatorialRadiusKM
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return math.Min(geoPointDistanceKM(point, arc.start), geoPointDistanceKM(point, arc.end))
|
||||
return math.Min(EquatorialDistanceKM(point, arc.start), EquatorialDistanceKM(point, arc.end))
|
||||
}
|
||||
|
||||
func visibleLineworkIndexPointKey(point GeoPoint) visibleLineworkPointKey {
|
||||
@@ -278,7 +278,7 @@ func visibleLineworkPolygons(
|
||||
// curves, but using that same radius for point-in-face tests makes adjacent
|
||||
// polar faces overlap and selects the wrong side of a narrow band.
|
||||
faceToleranceKM := math.Min(5, math.Max(0.5, snapDistanceKM/10))
|
||||
projectedTolerance := faceToleranceKM / 111.195
|
||||
projectedTolerance := faceToleranceKM / EarthKMPerDegree
|
||||
cycleProbes := visibleLineworkFilledCycleProbes(cycles, projectedFill, projectedTolerance)
|
||||
if len(cycleProbes) > 0 {
|
||||
for _, probe := range cycleProbes {
|
||||
@@ -403,7 +403,7 @@ func visibleLineworkProjectedEdgeDistanceKM(first, second GeoPoint) float64 {
|
||||
latitude := (first.Latitude + second.Latitude) * math.Pi / 360
|
||||
deltaLongitude := math.Remainder(second.Longitude-first.Longitude, 360) * math.Cos(latitude)
|
||||
deltaLatitude := second.Latitude - first.Latitude
|
||||
return math.Hypot(deltaLongitude, deltaLatitude) * 111.195
|
||||
return math.Hypot(deltaLongitude, deltaLatitude) * EarthKMPerDegree
|
||||
}
|
||||
|
||||
func visibleLineworkBoundarySourceMissDistanceKM(
|
||||
@@ -516,7 +516,7 @@ func visibleLineworkBoundaryBridge(
|
||||
if !visibleLineworkBridgeIsSimple(bridge, toleranceKM) {
|
||||
continue
|
||||
}
|
||||
if geoPointDistanceKM(originalStart, bridge[0]) > geoPointDistanceKM(originalStart, bridge[len(bridge)-1]) {
|
||||
if EquatorialDistanceKM(originalStart, bridge[0]) > EquatorialDistanceKM(originalStart, bridge[len(bridge)-1]) {
|
||||
reverseGeoPoints(bridge)
|
||||
}
|
||||
length := visibleLineworkBridgeLength(bridge)
|
||||
@@ -554,10 +554,10 @@ func visibleLineworkCrossLineBoundaryBridge(
|
||||
continue
|
||||
}
|
||||
for pointIndex, point := range line {
|
||||
if distance := geoPointDistanceKM(start, point); distance <= toleranceKM {
|
||||
if distance := EquatorialDistanceKM(start, point); distance <= toleranceKM {
|
||||
startLocations = append(startLocations, location{lineIndex, pointIndex, distance})
|
||||
}
|
||||
if distance := geoPointDistanceKM(end, point); distance <= toleranceKM {
|
||||
if distance := EquatorialDistanceKM(end, point); distance <= toleranceKM {
|
||||
endLocations = append(endLocations, location{lineIndex, pointIndex, distance})
|
||||
}
|
||||
}
|
||||
@@ -574,7 +574,7 @@ func visibleLineworkCrossLineBoundaryBridge(
|
||||
secondIndices := []int{0, len(secondLine) - 1}
|
||||
for _, firstIndex := range firstIndices {
|
||||
for _, secondIndex := range secondIndices {
|
||||
if geoPointDistanceKM(firstLine[firstIndex], secondLine[secondIndex]) > toleranceKM {
|
||||
if EquatorialDistanceKM(firstLine[firstIndex], secondLine[secondIndex]) > toleranceKM {
|
||||
continue
|
||||
}
|
||||
firstPath := visibleLineworkLinePath(firstLine, first.pointIndex, firstIndex, start, firstLine[firstIndex])
|
||||
@@ -609,8 +609,8 @@ func visibleLineworkBridgeIsSimple(points []GeoPoint, toleranceKM float64) bool
|
||||
}
|
||||
endpointRepeatTolerance := math.Min(1, toleranceKM/10)
|
||||
for index := 1; index+1 < len(points); index++ {
|
||||
if geoPointDistanceKM(points[index], points[0]) <= endpointRepeatTolerance ||
|
||||
geoPointDistanceKM(points[index], points[len(points)-1]) <= endpointRepeatTolerance {
|
||||
if EquatorialDistanceKM(points[index], points[0]) <= endpointRepeatTolerance ||
|
||||
EquatorialDistanceKM(points[index], points[len(points)-1]) <= endpointRepeatTolerance {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -633,7 +633,7 @@ func visibleLineworkLinePath(
|
||||
path = append(path, line[index])
|
||||
}
|
||||
}
|
||||
if len(path) == 0 || geoPointDistanceKM(path[len(path)-1], end) > 1e-9 {
|
||||
if len(path) == 0 || EquatorialDistanceKM(path[len(path)-1], end) > 1e-9 {
|
||||
path = append(path, end)
|
||||
}
|
||||
return path
|
||||
@@ -642,7 +642,7 @@ func visibleLineworkLinePath(
|
||||
func visibleLineworkBridgeLength(points []GeoPoint) float64 {
|
||||
length := 0.0
|
||||
for index := 1; index < len(points); index++ {
|
||||
length += geoPointDistanceKM(points[index-1], points[index])
|
||||
length += EquatorialDistanceKM(points[index-1], points[index])
|
||||
}
|
||||
return length
|
||||
}
|
||||
@@ -654,7 +654,7 @@ func visibleLineworkNearestVertex(
|
||||
bestIndex := -1
|
||||
bestDistance := math.Inf(1)
|
||||
for index, candidate := range line {
|
||||
distance := geoPointDistanceKM(point, candidate)
|
||||
distance := EquatorialDistanceKM(point, candidate)
|
||||
if distance < bestDistance {
|
||||
bestIndex = index
|
||||
bestDistance = distance
|
||||
@@ -1805,7 +1805,7 @@ func buildVisibleLineworkGraph(
|
||||
if index == otherIndex || len(other.outgoing) == 0 {
|
||||
continue
|
||||
}
|
||||
if distance := geoPointDistanceKM(point, chart.unproject(other.point)); distance < minimum {
|
||||
if distance := EquatorialDistanceKM(point, chart.unproject(other.point)); distance < minimum {
|
||||
first, second, minimum = index, otherIndex, distance
|
||||
}
|
||||
}
|
||||
@@ -1923,7 +1923,7 @@ func visibleLineworkNodeIndex(
|
||||
bestIndex := -1
|
||||
bestDistance := math.Inf(1)
|
||||
for index, node := range nodes {
|
||||
distance := geoPointDistanceKM(chart.unproject(node.point), target)
|
||||
distance := EquatorialDistanceKM(chart.unproject(node.point), target)
|
||||
if distance <= snapDistanceKM && distance < bestDistance {
|
||||
bestIndex, bestDistance = index, distance
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user