package geojson_test import ( "encoding/json" "math" "testing" "time" "b612.me/astro/eclipse" "b612.me/astro/geojson" ) // TestLunarGeoJSONDropsAntimeridianSlivers 固定月食可见区的环卫生契约:日界线剪裁会在相邻 // 世界各输出一次"全部顶点落在同一条子午线、平面面积只剩浮点噪声"的零宽薄片(实测 // 1.8e-12 deg²,刚好越过共享剪裁器 1e-12 的零面积阈值),导出时必须在月食这一层丢弃, // 同时不能连带丢掉有面积的面。 // TestLunarGeoJSONDropsAntimeridianSlivers pins the ring-hygiene contract of the lunar // visibility export: the antimeridian split emits one zero-width sliver per adjacent world whose // vertices all sit on one meridian with a planar area of floating-point noise (measured // 1.8e-12 deg^2, just past the shared splitter's 1e-12 zero-area floor). The lunar export must // drop it without dropping polygons that do have area. func TestLunarGeoJSONDropsAntimeridianSlivers(t *testing.T) { for _, day := range []string{"2022-11-08", "2026-03-03", "4026-03-16", "1904-09-24", "2025-03-14"} { t.Run(day, func(t *testing.T) { date, err := time.Parse("2006-01-02", day) if err != nil { t.Fatal(err) } info, ok := eclipse.LunarEclipseOnDate(date) if !ok { t.Fatal("missing lunar eclipse") } data, err := geojson.MarshalLunarEclipse(info, 360) if err != nil { t.Fatal(err) } collection := decodeCollection(t, data) for _, role := range []string{"visible-at-p1", "visible-at-p4"} { feature := featureWithRole(t, collection, role) var polygons [][][][]float64 if err := json.Unmarshal(feature.Geometry.Coordinates, &polygons); err != nil { t.Fatal(err) } if len(polygons) == 0 { t.Fatalf("%s has no polygons", role) } for index, polygon := range polygons { area := 0.0 for _, ring := range polygon { if len(ring) < 4 { t.Fatalf("%s polygon %d ring has %d positions", role, index, len(ring)) } distinct := 0 for position, point := range ring { if position == 0 || math.Abs(point[0]-ring[position-1][0]) > 1e-9 || math.Abs(point[1]-ring[position-1][1]) > 1e-9 { distinct++ } } if distinct > 1 && math.Abs(ring[0][0]-ring[len(ring)-1][0]) <= 1e-9 && math.Abs(ring[0][1]-ring[len(ring)-1][1]) <= 1e-9 { // 闭合点不是独立顶点 / The closing position is not a distinct vertex. distinct-- } if distinct < 3 { t.Fatalf("%s polygon %d is a zero-width sliver: %v", role, index, ring) } for position := 0; position+1 < len(ring); position++ { area += ring[position][0]*ring[position+1][1] - ring[position+1][0]*ring[position][1] } } if math.Abs(area/2) < 1e-12 { t.Fatalf("%s polygon %d has no area: %v", role, index, polygon) } } } }) } }