feat: 完善水星与金星全球凌日搜索及制图导出
- 基于平均下合周期与节点相位预筛候选,减少无效星历计算;跳过无法求解的单个会合周期,避免有限覆盖星历导致搜索提前终止 - 引入影轴 γ、半影半径及地球尺度几何判定,结合站心可见性识别地心无接触、仅部分地区可见的掠凌 - 添加金星 243 年、水星 46 年周期族编号,并明确编号适用范围及未分配时的零值语义 - 为 SVG、GeoJSON 和 KML 增加站心部分凌日可见区,适配接触等时线、几何元数据、图层样式及取景;为地心无接触凌日事件增加正射图,按可见区球面面积加权居中
This commit is contained in:
41 files changed
+1554
-307
No files matched your search
@@ -0,0 +1,106 @@
|
||||
package svg
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTransitSVGGlobalPartial(tester *testing.T) {
|
||||
date := time.Date(2854, 12, 14, 0, 0, 0, 0, time.UTC)
|
||||
chart, ok := TransitMapSVG(TransitVenus, date, TransitMapSVGOptions{Isochrones: TransitIsochroneAll, IsochroneStep: 30 * time.Second})
|
||||
if !ok {
|
||||
tester.Fatal("global partial transit render failed")
|
||||
}
|
||||
for _, expected := range []string{"2854-12-14", "transit-partial-region", "地心无接触", "周期族 4", "γ ", "c1-isochrone", "c4-isochrone"} {
|
||||
if !strings.Contains(chart, expected) {
|
||||
tester.Fatalf("missing %s", expected)
|
||||
}
|
||||
}
|
||||
for _, absent := range []string{"NaN", "Inf", "transit-sun-c1-shape", "c2-isochrone", "c3-isochrone"} {
|
||||
if strings.Contains(chart, absent) {
|
||||
tester.Fatalf("invalid SVG contains %s", absent)
|
||||
}
|
||||
}
|
||||
local, ok := TransitLocalSVG(TransitVenus, date, -135, -60, 0, TransitLocalSVGOptions{})
|
||||
if !ok || !strings.Contains(local, "transit-planet-c1") || !strings.Contains(local, "transit-planet-c4") || strings.Contains(local, "transit-planet-c2") {
|
||||
tester.Fatal("local partial-transit diagram has invalid contacts")
|
||||
}
|
||||
labels := regexp.MustCompile(`class="transit-event-label" x="[0-9.-]+" y="([0-9.-]+)"`).FindAllStringSubmatch(local, -1)
|
||||
if len(labels) != 3 {
|
||||
tester.Fatalf("grazing contact labels=%d, want 3", len(labels))
|
||||
}
|
||||
footer := regexp.MustCompile(`<text x="40" y="([0-9.-]+)" fill="#555"`).FindAllStringSubmatch(local, -1)
|
||||
if len(footer) == 0 {
|
||||
tester.Fatal("local partial-transit diagram has no footer")
|
||||
}
|
||||
firstFooterBaseline, _ := strconv.ParseFloat(footer[0][1], 64)
|
||||
for _, label := range labels {
|
||||
baseline, _ := strconv.ParseFloat(label[1], 64)
|
||||
if baseline > firstFooterBaseline-8 {
|
||||
tester.Fatal("contact label overlaps the footer")
|
||||
}
|
||||
}
|
||||
if _, ok := TransitLocalSVG(TransitVenus, date, 0, 45, 0, TransitLocalSVGOptions{}); ok {
|
||||
tester.Fatal("a northern site must miss the transit")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransitMapLegendListsDrawnIsochrones(tester *testing.T) {
|
||||
for _, test := range []struct {
|
||||
planet TransitPlanet
|
||||
date time.Time
|
||||
inner bool
|
||||
}{
|
||||
{TransitVenus, time.Date(554, 5, 22, 0, 0, 0, 0, time.UTC), true},
|
||||
{TransitMercury, time.Date(-513, 10, 22, 0, 0, 0, 0, time.UTC), false},
|
||||
} {
|
||||
chart, ok := TransitMapSVG(test.planet, test.date, TransitMapSVGOptions{Isochrones: TransitIsochroneAll, Language: "en"})
|
||||
if !ok {
|
||||
tester.Fatalf("%v: render failed", test.date)
|
||||
}
|
||||
for _, marker := range []string{"c2-isochrone", "C2 isochrones", "C3 isochrones"} {
|
||||
if strings.Contains(chart, marker) != test.inner {
|
||||
tester.Fatalf("%v: %s present=%v, want %v", test.date, marker, !test.inner, test.inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 地心无接触的部分凌日也要在图例里列出实际画出的一触、四触等时线;二触、三触不存在。
|
||||
func TestTransitPartialLegendListsDrawnIsochrones(tester *testing.T) {
|
||||
for _, language := range []string{"zh", "en"} {
|
||||
chart, ok := TransitMapSVG(TransitVenus, time.Date(2854, 12, 14, 0, 0, 0, 0, time.UTC), TransitMapSVGOptions{
|
||||
Isochrones: TransitIsochroneAll, Language: language,
|
||||
})
|
||||
if !ok {
|
||||
tester.Fatalf("%s: render failed", language)
|
||||
}
|
||||
partial, c1, c4 := "部分凌日可见区", "一触等时线", "四触等时线"
|
||||
if language == "en" {
|
||||
partial, c1, c4 = "Partial transit visible", "C1 isochrones", "C4 isochrones"
|
||||
}
|
||||
for _, expected := range []string{"c1-isochrone", "c4-isochrone", partial, c1, c4} {
|
||||
if !strings.Contains(chart, expected) {
|
||||
tester.Fatalf("%s: partial chart is missing %q", language, expected)
|
||||
}
|
||||
}
|
||||
for _, absent := range []string{"c2-isochrone", "c3-isochrone", "二触等时线", "三触等时线", "C2 isochrones", "C3 isochrones"} {
|
||||
if strings.Contains(chart, absent) {
|
||||
tester.Fatalf("%s: partial chart must not contain %q", language, absent)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 默认不画等时线时图例只留可见区色块,不凭空加等时线条目。
|
||||
chart, ok := TransitMapSVG(TransitVenus, time.Date(2854, 12, 14, 0, 0, 0, 0, time.UTC), TransitMapSVGOptions{Language: "en"})
|
||||
if !ok {
|
||||
tester.Fatal("default render failed")
|
||||
}
|
||||
for _, absent := range []string{"c1-isochrone", "C1 isochrones", "C4 isochrones"} {
|
||||
if strings.Contains(chart, absent) {
|
||||
tester.Fatalf("default chart must not contain %q", absent)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user