feat: 完善水星与金星全球凌日搜索及制图导出

- 基于平均下合周期与节点相位预筛候选,减少无效星历计算;跳过无法求解的单个会合周期,避免有限覆盖星历导致搜索提前终止
- 引入影轴 γ、半影半径及地球尺度几何判定,结合站心可见性识别地心无接触、仅部分地区可见的掠凌
- 添加金星 243 年、水星 46 年周期族编号,并明确编号适用范围及未分配时的零值语义
- 为 SVG、GeoJSON 和 KML 增加站心部分凌日可见区,适配接触等时线、几何元数据、图层样式及取景;为地心无接触凌日事件增加正射图,按可见区球面面积加权居中
This commit is contained in:
b612 committed 2026-10-20 22:35:39 +08:00
1 parent 72460fa228
commit ccf5880269
41 files changed
+1554 -307

No files matched your search

+13 -2
View File
@@ -33,6 +33,7 @@
- [凌日出图](#凌日出图)
- [水星:2032-11-13(北京)](#水星2032-11-13北京)
- [金星:2012-06-06(北京)](#金星2012-06-06北京)
- [特例:地心无接触的部分凌日](#特例地心无接触的部分凌日)
## 简单示例:2009长江大日食,上海某地见食情况
@@ -990,10 +991,14 @@ ut1, ok := eclipsesvg.SolarEclipseMapSVG(
| 入口 | 画面 | 画布建议 |
| --- | --- | --- |
| `TransitMapSVG` | 地心几何的全球可见图:全程可见、日出时已在凌日、日落时仍在凌日、不可见四区 | 960×640 起 |
| `TransitMapSVG` | 全球可见图;地心无接触时绘制站心部分凌日可见区 | 960×640 起 |
| `TransitLocalSVG` | 站心日面图:上北左东,行星中心轨迹、各接触与凌甚的行星圆面、接触时刻表 | 960×680 起 |
可见区按一触、凌甚、四触三刻太阳中心是否在视地平上划分,计入标准大气折射(地平圈半径 90°34′)。等时线默认不画,用 `Isochrones` 按位开启:`TransitIsochroneC1` … `TransitIsochroneC4`,或组合 `TransitIsochroneExternal`(一触、四触)、`TransitIsochroneAll`;掠凌没有内切接触时 C2/C3 自动略去。等时线是站心接触时刻,只画太阳在视地平上的部分;`IsochroneStep` 非正时水星取 20 秒、金星取 1 分钟。凌日可见范围接近半个地球,地图始终画全球,`Projection` 可选四种投影。
普通凌日可见区按一触、凌甚、四触三刻太阳中心是否在视地平上划分,计入标准大气折射(地平圈半径 90°34′);地心无接触事件改用实际站心可见区。等时线默认不画,用 `Isochrones` 按位开启:`TransitIsochroneC1` … `TransitIsochroneC4`,或组合 `TransitIsochroneExternal`(一触、四触)、`TransitIsochroneAll`;地表没有站心内切接触时 C2/C3 不画,图例也不列出;地心只有外切的掠凌仍可能在部分地区出现站心二、三触,此时照常绘制。等时线是站心接触时刻,只画太阳在视地平上的部分;`IsochroneStep` 非正时水星取 20 秒、金星取 1 分钟。
地心无接触事件的部分凌日可见区按 2° 经度、1° 纬度探测并细化已检出的边界,这只是制图采样,不是站心接触求解精度;比采样间距更窄的可见区可能未被检出,需要精确的地点判断时直接用 `LocalTransit`。
`Projection` 可选四种投影,默认等经纬图展示全球。正射图只展示朝向视点的半个地球:水星、金星在地心无接触时以站心可见区的球面面积加权中心取景,例如 `1937-05-11` 水星凌日和 `2854-12-14` 金星凌日;普通凌日仍以凌甚太阳直射点取景。极区事件也可显式选择南、北极投影。
```go
venus := time.Date(2012, 6, 6, 0, 0, 0, 0, time.UTC)
@@ -1022,3 +1027,9 @@ local, ok := eclipsesvg.TransitLocalSVG(eclipsesvg.TransitVenus, venus, 116.4, 3
![2012 金星凌日北京站心图](../img/transit-venus-beijing-2012.svg)
![2012 金星凌日全球可见图](../img/transit-venus-beijing-2012-global.svg)
### 特例:地心无接触的部分凌日
1937-05-11 水星凌日即为一例,可见区横跨南大西洋、非洲南端与印度洋,东至澳大利亚东侧。`2854-12-14` 金星凌日同属此类,可见区跨越南极圈,集中在南纬 50° 以南。
![1937 水星凌日(地心无接触)全球可见图](../img/transit-mercury-1937-partial.svg)
+13 -2
View File
@@ -33,6 +33,7 @@ This manual covers solar- and lunar-eclipse queries and charts, plus the two Mer
- [Transit charts](#transit-charts)
- [Mercury: 2032-11-13 (Beijing)](#mercury-2032-11-13-beijing)
- [Venus: 2012-06-06 (Beijing)](#venus-2012-06-06-beijing)
- [Special case: partial transits without geocentric contacts](#special-case-partial-transits-without-geocentric-contacts)
## Simple example: the 2009 Great Yangtze Eclipse at a site in Shanghai
@@ -1064,10 +1065,14 @@ Transit contact times, topocentric visibility and `LocalTransit` live in [Planet
| Entry | Chart | Suggested canvas |
| --- | --- | --- |
| `TransitMapSVG` | Geocentric global visibility: entire transit, transit at sunrise, transit at sunset, not visible | 960×640 and up |
| `TransitMapSVG` | Global visibility, including topocentric partial-only events without geocentric contacts | 960×640 and up |
| `TransitLocalSVG` | Topocentric solar disk: north up, east left, planet-center track, planet disk at each contact and at greatest, contact table | 960×680 and up |
Regions follow whether the Sun's center is above the apparent horizon at C1, greatest and C4, with standard refraction (a horizon circle of 90°34′). Isochrones are off by default; enable them bitwise with `Isochrones`: `TransitIsochroneC1` … `TransitIsochroneC4`, or the combinations `TransitIsochroneExternal` (C1 and C4) and `TransitIsochroneAll`. C2/C3 are dropped for a grazing transit without internal contacts. Isochrones are topocentric contact times drawn only where the Sun is above the apparent horizon; a non-positive `IsochroneStep` uses 20 s for Mercury and 1 min for Venus. A transit is visible from roughly half the globe, so the map always shows the whole world; `Projection` selects one of the four projections.
For ordinary transits, regions follow whether the Sun's center is above the apparent horizon at C1, greatest and C4, with standard refraction (a horizon circle of 90°34′); events without geocentric contacts use the actual topocentric visible footprint. Isochrones are off by default; enable them bitwise with `Isochrones`: `TransitIsochroneC1` … `TransitIsochroneC4`, or the combinations `TransitIsochroneExternal` (C1 and C4) and `TransitIsochroneAll`. C2/C3 are omitted, including from the legend, when no site has an internal contact; a graze with only geocentric external contacts can still have topocentric C2/C3 in some regions, and those are drawn. Isochrones are topocentric contact times drawn only where the Sun is above the apparent horizon; a non-positive `IsochroneStep` uses 20 s for Mercury and 1 min for Venus.
For events without geocentric contacts the partial footprint is sampled on a 2° longitude by 1° latitude grid and detected boundaries are refined. That is chart sampling, not contact accuracy: a footprint narrower than the grid may go undetected, so use `LocalTransit` for exact site decisions.
`Projection` selects one of four projections; the default equirectangular map shows the whole world. Orthographic maps show only the facing hemisphere. For both Mercury and Venus, events without geocentric contacts centre on the spherical area-weighted visible footprint, for example Mercury on `1937-05-11` and Venus on `2854-12-14`. Ordinary transits retain the subsolar centre at greatest. Polar events may also use an explicit north- or south-polar projection.
```go
venus := time.Date(2012, 6, 6, 0, 0, 0, 0, time.UTC)
@@ -1097,3 +1102,9 @@ The Venus transit of 2012-06-06 was visible in full from Beijing, with `6h39m4s`
![Venus transit of 2012-06-06 from Beijing](../../img/transit-venus-beijing-2012-en.svg)
![Venus transit of 2012-06-06 global visibility](../../img/transit-venus-beijing-2012-global-en.svg)
### Special case: partial transits without geocentric contacts
The Mercury transit of 1937-05-11 is one such event: with no geocentric contacts, its footprint spans the South Atlantic, southern Africa and the Indian Ocean east to eastern Australia. The Venus transit of `2854-12-14` belongs to the same class, with a footprint that crosses the Antarctic Circle, all south of 50°S.
![Mercury transit of 1937-05-11 without geocentric contacts, global visibility](../../img/transit-mercury-1937-partial-en.svg)
+8 -4
View File
@@ -73,7 +73,11 @@ A partial eclipse may have no central path, so `centralPath` may be `nil`. This
## Exporting transit GeoJSON
The transit entry points take a geocentric `TransitInfo` and partition the globe exactly like the transit visibility map:
The transit entry points take a global-event `TransitInfo`; contact fields remain geocentric, and regions match the transit visibility map.
Events without geocentric contacts, such as the Venus transit of 2854-12-14, export the actual topocentric
`transit-partial` footprint and omit nonexistent geocentric C1/C4 horizons. Properties also carry
`has_geocentric_contacts`, `gamma`, `penumbral_radius`, `series` and `series_period_years`. The footprint is sampled on a 2° longitude by 1° latitude grid with boundary refinement; that is chart sampling rather than contact accuracy, so a footprint narrower than the grid may go undetected — use `LocalTransit` for exact site decisions.
```go
m := mercury.NextTransit(time.Date(2026, 10, 12, 0, 0, 0, 0, cst))
@@ -194,7 +198,7 @@ Grouped by figure family, the `data-source` values are listed below; the `eclips
- Solar-eclipse instants and magnitude lines: `rise-set-phase-lines`, `magnitude-contours`, `greatest-time-isochrones`
- Instantaneous outlines: `penumbral-outlines`, `central-shadow-outlines`
- Lunar eclipses: `p1-p4-visibility-regions`, `p1-p4-horizon-boundaries`
- Transits: `c1-c4-visibility-regions`, `c1-c4-horizon-boundaries`, `transit-contact-isochrones`
- Transits: `c1-c4-visibility-regions`, `c1-c4-horizon-boundaries`, `transit-contact-isochrones`; events without geocentric contacts fill the footprint from `topocentric-transit-visibility`
## Map Projections
@@ -312,7 +316,7 @@ Each event type has plain and time-marker variants:
- `MarshalLunarEclipseWithOptions`: one `LunarEclipseOptions` value carrying the time markers, `SkipRoles` and the time-envelope sampling parameters. `SkipRoles` can omit envelopes and penumbra-only bands; skipping both envelopes also skips their sampling. `EnvelopeSweepSamples` defaults to 48 and is clamped to `[2, 192]`; `EnvelopeLongitudePoints` defaults to `max(360, boundaryPoints)` and is clamped to `[12, 720]`.
- `MarshalStarOccultation` / `MarshalStarOccultationWithTimeMarkers`
- `MarshalPlanetOccultation` / `MarshalPlanetOccultationWithTimeMarkers`
- `MarshalMercuryTransit` / `MarshalVenusTransit`: take `mercury.TransitInfo` / `venus.TransitInfo` and partition the globe like the transit SVG map (whether the Sun's center is above the apparent horizon, standard refraction, at C1, greatest and C4). `BoundaryPoints` is the horizon sample count and also sets the region longitude columns to `max(360, BoundaryPoints)`, capped at 720. Roles are the three regions `transit-entire`, `transit-at-sunrise` and `transit-at-sunset`, the visible hemispheres and horizons `visible-at-c1` / `visible-at-c4` and `c1-horizon` / `c4-horizon`, `greatest` (the subsolar point) and the time markers `time-marker`. A positive `IsochroneStep` (at least 1 s) adds topocentric `c1-isochrone` through `c4-isochrone` (no C2/C3 for a grazing transit; the times are topocentric contacts and parallax can place them outside the geocentric C1–C4 interval), and a contact whose isochrone does not reach the visible hemisphere omits that role; skipping all three region roles skips the region computation.
- `MarshalMercuryTransit` / `MarshalVenusTransit`: take `mercury.TransitInfo` / `venus.TransitInfo` and partition the globe like the transit SVG map (whether the Sun's center is above the apparent horizon, standard refraction, at C1, greatest and C4). `BoundaryPoints` is the horizon sample count and also sets the region longitude columns to `max(360, BoundaryPoints)`, capped at 720. Roles are the three regions `transit-entire`, `transit-at-sunrise` and `transit-at-sunset`, the visible hemispheres and horizons `visible-at-c1` / `visible-at-c4` and `c1-horizon` / `c4-horizon`, `greatest` (the subsolar point) and the time markers `subsolar-track`. Events without geocentric contacts switch to a `transit-partial` region and omit the three visibility regions, the horizons and the visible hemispheres. A positive `IsochroneStep` (at least 1 s) adds topocentric `c1-isochrone` through `c4-isochrone` (no C2/C3 when no site has an internal contact, though a graze with only geocentric external contacts can still have them in some regions; the times are topocentric contacts and parallax can place them outside the geocentric C1–C4 interval), and a contact whose isochrone does not reach the visible hemisphere omits that role; skipping all three region roles skips the region computation.
- `MarshalSolarEclipseWithOptions`: one `SolarEclipseOptions` value carrying both the time markers and `SkipRoles`, equivalent to the solar entry points above plus layer trimming.
The usual entry in `SkipRoles` is `partial-footprint` (the instantaneous penumbral outlines); `partial-band` is the edge of the eclipse band (the magnitude-0 limit) and is normally kept.
@@ -472,7 +476,7 @@ Features are grouped into Folders by `event` and `role`. Collections containing
| Total and partial occultation bands | `total-band`, `partial-band`, `total-band-outline`, `occultation-band` | Yellow with translucent band fill |
| Rise/set visibility edges, lunar time envelopes and solar partial-band edge | `visibility-boundary`, `p1-horizon`, `p4-horizon`, `visible-at-p1`, `visible-at-p4`, `visible-during-eclipse`, `visible-throughout-eclipse`, solar `partial-band` | Orange |
| Penumbra-only moonrise/moonset bands | `penumbra-moonrise`, `penumbra-moonset` | Blue-violet for moonrise, violet for moonset, with a translucent fill |
| Transit visibility regions and contact lines | `transit-entire`, `transit-at-sunrise`, `transit-at-sunset`, `c1-horizon`, `c4-horizon`, `visible-at-c1`, `visible-at-c4`, `c1-isochrone` … `c4-isochrone` | Each of the three regions has its own fill; C1/C4 horizons and visible hemispheres are orange; the four contact isochrones each get a color |
| Transit visibility regions and contact lines | `transit-entire`, `transit-at-sunrise`, `transit-at-sunset`, `transit-partial`, `c1-horizon`, `c4-horizon`, `visible-at-c1`, `visible-at-c4`, `c1-isochrone` … `c4-isochrone` | Each of the three regions and the partial-transit footprint has its own fill; C1/C4 horizons and visible hemispheres are orange; the four contact isochrones each get a color |
| Other limits, outlines, footprints and time markers | Other roles | Grey; polygons are outline-only by default |
Zero-valued `Style` fields retain palette defaults:
+15 -13
View File
@@ -38,7 +38,7 @@ The inner planets (Mercury and Venus) add superior/inferior conjunction, greates
- [Position and coordinates](#position-and-coordinates)
- [Rise, set and culmination](#rise-set-and-culmination)
- [Conjunctions, oppositions, stations and quadratures](#conjunctions-oppositions-stations-and-quadratures)
- [Greatest elongation and geocentric transits](#greatest-elongation-and-geocentric-transits)
- [Greatest elongation and transits](#greatest-elongation-and-transits)
- [Nodes, phase, magnitude, diameter and parallactic angle](#nodes-phase-magnitude-diameter-and-parallactic-angle)
- [Division of labour with other manuals](#division-of-labour-with-other-manuals)
- [Physical ephemerides](#physical-ephemerides)
@@ -188,22 +188,22 @@ fmt.Println(saturn.NextProgradeToRetrograde(date)) // Saturn's next prograde-to-
Event searches return the nearest event at or after the input instant and keep its time zone; the paired `Last...` functions and the direction-agnostic `NextRetrograde` are in [Conjunctions, oppositions, stations and quadratures](#conjunctions-oppositions-stations-and-quadratures);
Mercury's and Venus's `NextGreatestElongationEast` / `...West` are in [Greatest elongation and geocentric transits](#greatest-elongation-and-geocentric-transits).
Mercury's and Venus's `NextGreatestElongationEast` / `...West` are in [Greatest elongation and transits](#greatest-elongation-and-transits).
### Mercury and Venus transits
```go
transit := mercury.NextTransit(date) // next geocentric Mercury transit after 2020
transit := mercury.NextTransit(date) // next Mercury transit after 2020
fmt.Println(transit.Valid, transit.Start, transit.Greatest) // whether one was found, first contact, greatest transit
fmt.Println(transit.Duration, transit.MinimumSeparationArcsec) // duration and minimum separation at greatest transit
```
```text
true 2032-11-13 14:41:13.161198198 +0800 CST 2032-11-13 16:54:12.821315824 +0800 CST
4h26m2.695272267s 572.0643215495325
true 2032-11-13 14:41:13.691189289 +0800 CST 2032-11-13 16:54:13.351347148 +0800 CST
4h26m2.484410405s 572.0831814505963
```
`TransitInfo.Valid` false means no transit inside the search window and every other field is the zero value; `TransitInfo` is the geocentric geometry. For the contact times seen from one site, `LocalTransit` returns the topocentric result:
`TransitInfo.Valid` false means no transit inside the search window and every other field is the zero value; otherwise `TransitInfo` describes a global event whose contact fields are geocentric reference times. Without geocentric contacts `HasExternal` is false, `Start` / `End` are zero, and only the `WindowStart` / `WindowEnd` search window is set. For the contact times seen from one site, `LocalTransit` returns the topocentric result:
```go
transit := mercury.NextTransit(time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC))
@@ -214,12 +214,14 @@ fmt.Println(local.Start.Time, local.Start.SunAltitude) // topocentric C1
```text
true true true
2019-11-11 12:36:09.037762284 +0000 UTC 7.933256722170642
2019-11-11 12:36:08.979182839 +0000 UTC 7.933092450591312
```
Topocentric contacts are re-solved after applying parallax to the Sun and the planet separately; Venus contacts can shift by about ±7 minutes from the geocentric ones across the globe, Mercury by about ±2 minutes. `SunAltitude` is the geometric altitude of the Sun's center; `Visible`, `Sunrise` and `Sunset` test whether the Sun's center is above the apparent horizon with standard refraction (1010 hPa, 10 °C), a geometric threshold of about −34′. A site may see only a grazing transit even when the geocentric one has internal contacts (the 1999-11-15 Mercury transit at high southern latitudes); then `HasInternal` is false and `InternalStart` / `InternalEnd` are zero. Global maps and topocentric disk charts are in [Eclipses and transits](eclipse.md#transit-charts).
The four contacts, partial transits and the internal-contact fields are in [Greatest elongation and geocentric transits](#greatest-elongation-and-geocentric-transits).
The four contacts, partial transits and the internal-contact fields are in [Greatest elongation and transits](#greatest-elongation-and-transits).
`Gamma` is the signed distance from Earth's centre to the shadow axis at greatest (positive to the north) and `PenumbralRadius` is the penumbral radius on the fundamental plane, both in Earth equatorial radii. The transit penumbra is far larger than Earth, so the solar-eclipse test `|Gamma| < 1` does not apply. `Series` is the transit family: Venus families average 243 years and are numbered for astronomical years −2000 to +4000, Mercury families average 46 years and are numbered for +1601 to +2300; outside those spans, or for an unnumbered family, `Number` is zero while `PeriodYears` still gives the mean period.
### Phase, diameter, magnitude and nodes
@@ -580,15 +582,15 @@ fmt.Println(saturn.LastProgradeToRetrograde(date), saturn.NextProgradeToRetrogra
fmt.Println(saturn.LastRetrogradeToPrograde(date), saturn.NextRetrogradeToPrograde(date))
```
### Greatest elongation and geocentric transits
### Greatest elongation and transits
Greatest elongation only makes sense for Mercury and Venus: `LastGreatestElongation` / `NextGreatestElongation` ignore the side, while `LastGreatestElongationEast` / `NextGreatestElongationEast` and the `...West` forms distinguish it.
The public entry points for geocentric transits are likewise only in `mercury` / `venus`: `LastTransit` / `NextTransit` / `ClosestTransit` return a `TransitInfo`.
The public transit entry points are likewise only in `mercury` / `venus`: `LastTransit` / `NextTransit` / `ClosestTransit` return a `TransitInfo`.
`Valid == false` means no transit inside the search window and every other field is a zero value; a partial transit has no internal contacts, so `HasInternal` is false and `InternalStart` / `InternalEnd` are zero.
`Valid == false` means no transit inside the search window and every other field is a zero value. Without geocentric contacts `HasExternal` is false and `Start` / `End` are zero; the event is then accepted or rejected by topocentric surface visibility. Without a topocentric internal contact `HasInternal` is false and `InternalStart` / `InternalEnd` are zero.
A transit is a purely geocentric geometry test and does not check whether the Sun is above the horizon at a given site.
Contact fields come from the geocentric geometry, but whether a site can see the transit, and which contacts it sees, is decided by `LocalTransit`.
```go
// Greatest elongation: use ...East / ...West to pick a side, or the plain form for either.
@@ -902,7 +904,7 @@ Geocentric, topocentric, and distance are three different conventions: `Apparent
### Zero values, out-of-range input and sentinel errors
When an event search finds nothing inside its window it returns zero values or a struct with `Valid == false` (`TransitInfo.Valid`, `GalileanPhenomenonEvent.Valid`, `GalileanPhenomenonContactEvent.Valid`) instead of an error; when `TransitInfo.HasInternal` is false, `InternalStart` / `InternalEnd` are zero values because a partial transit has no internal contacts.
When an event search finds nothing inside its window it returns zero values or a struct with `Valid == false` (`TransitInfo.Valid`, `GalileanPhenomenonEvent.Valid`, `GalileanPhenomenonContactEvent.Valid`) instead of an error; when `TransitInfo.HasExternal` is false, `Start` / `End` are zero values, and when `TransitInfo.HasInternal` is false, `InternalStart` / `InternalEnd` are zero values.
`planet.WherePlanet` / `planet.WherePlanetN` return `NaN` instead of panicking when `xt` / `zn` is out of range. `n < 0` selects the full series; all nonnegative `n` select one semianalytic fast table, while Legacy truncates according to `n`.
+8 -4
View File
@@ -73,7 +73,11 @@ func main() {
## 导出凌日 GeoJSON
凌日入口接收地心 `TransitInfo`,分区口径与凌日全球图一致:
凌日入口接收全球事件的 `TransitInfo`,接触字段仍为地心参考时刻,分区口径与凌日全球图一致:
地心无接触的边缘事件(如 2854-12-14 金星凌日)导出站心实际可见的 `transit-partial` 区域,
不生成不存在的地心 C1/C4 地平线。属性还包含 `has_geocentric_contacts`、`gamma`、`penumbral_radius`、
`series`、`series_period_years`。足迹按 2° 经度、1° 纬度采样并细化边界,这是制图采样而不是接触求解精度,比采样间距更窄的可见区可能未检出;精确判断请用 `LocalTransit`。
```go
m := mercury.NextTransit(time.Date(2026, 10, 12, 0, 0, 0, 0, cst))
@@ -190,7 +194,7 @@ true <nil> true 4217
- 日食时刻与食分线:`rise-set-phase-lines`、`magnitude-contours`、`greatest-time-isochrones`
- 瞬时轮廓:`penumbral-outlines`、`central-shadow-outlines`
- 月食:`p1-p4-visibility-regions`、`p1-p4-horizon-boundaries`
- 凌日:`c1-c4-visibility-regions`、`c1-c4-horizon-boundaries`、`transit-contact-isochrones`
- 凌日:`c1-c4-visibility-regions`、`c1-c4-horizon-boundaries`、`transit-contact-isochrones`;地心无接触时可见区填充改用 `topocentric-transit-visibility`
## 地图投影
@@ -294,7 +298,7 @@ func main() {
- `MarshalLunarEclipseWithOptions`:用 `LunarEclipseOptions` 一次给出时间标记、`SkipRoles` 与时间包络的采样参数。`SkipRoles` 可跳过时间包络和仅见半影带;跳过两个时间包络时不会执行包络采样。`EnvelopeSweepSamples` 默认 48,限制在 `[2, 192]`;`EnvelopeLongitudePoints` 默认 `max(360, boundaryPoints)`,限制在 `[12, 720]`。
- `MarshalStarOccultation` / `MarshalStarOccultationWithTimeMarkers`
- `MarshalPlanetOccultation` / `MarshalPlanetOccultationWithTimeMarkers`
- `MarshalMercuryTransit` / `MarshalVenusTransit`:接收 `mercury.TransitInfo` / `venus.TransitInfo`,分区口径同凌日 SVG 全球图(一触、凌甚、四触太阳中心是否在视地平上,计入标准大气折射)。`BoundaryPoints` 是地平线采样点数,同时决定分区的经度列数 `max(360, BoundaryPoints)`(上限 720)。role 有 `transit-entire`、`transit-at-sunrise`、`transit-at-sunset` 三个分区,`visible-at-c1` / `visible-at-c4` 与 `c1-horizon` / `c4-horizon`,`greatest`(太阳直射点)与时间标记 `time-marker`;`IsochroneStep` 为正(至少 1 秒)时追加 `c1-isochrone` 到 `c4-isochrone` 站心等时线(掠凌无二、三触;时刻是站心接触时刻,受视差影响可落在地心一触到四触之外),某个接触的等时线不落在可见半球上时该 role 不出现;`SkipRoles` 跳过全部三个分区时不做分区计算。
- `MarshalMercuryTransit` / `MarshalVenusTransit`:接收 `mercury.TransitInfo` / `venus.TransitInfo`,分区口径同凌日 SVG 全球图(一触、凌甚、四触太阳中心是否在视地平上,计入标准大气折射)。`BoundaryPoints` 是地平线采样点数,同时决定分区的经度列数 `max(360, BoundaryPoints)`(上限 720)。role 有 `transit-entire`、`transit-at-sunrise`、`transit-at-sunset` 三个分区,`visible-at-c1` / `visible-at-c4` 与 `c1-horizon` / `c4-horizon`,`greatest`(太阳直射点)与时间标记 `subsolar-track`;地心无接触事件改用 `transit-partial` 分区,不生成三个可见分区、视地平与可见半球 role;`IsochroneStep` 为正(至少 1 秒)时追加 `c1-isochrone` 到 `c4-isochrone` 站心等时线(地表没有站心内切接触时无二、三触,地心只有外切的掠凌仍可能在部分地区出现;时刻是站心接触时刻,受视差影响可落在地心一触到四触之外),某个接触的等时线不落在可见半球上时该 role 不出现;`SkipRoles` 跳过全部三个分区时不做分区计算。
- `MarshalSolarEclipseWithOptions`:用 `SolarEclipseOptions` 一次给出时间标记与 `SkipRoles`,等价于上面的日食入口再加图层裁剪。`SkipRoles` 里最常用的是 `partial-footprint`(瞬时半影轮廓);`partial-band` 是日食带边缘(食分 0 界限),通常要留着。
### 图层筛选
@@ -434,7 +438,7 @@ func main() {
| 掩星全掩与偏掩带 | `total-band`、`partial-band`、`total-band-outline`、`occultation-band` | 黄色,带半透明填充 |
| 升落可见边界、月食时间包络、日食偏食带边缘 | `visibility-boundary`、`p1-horizon`、`p4-horizon`、`visible-at-p1`、`visible-at-p4`、`visible-during-eclipse`、`visible-throughout-eclipse`、日食的 `partial-band` | 橙色 |
| 仅见半影的月出/月落带 | `penumbra-moonrise`、`penumbra-moonset` | 月出蓝紫、月落紫红,带半透明填充 |
| 凌日可见分区与接触线 | `transit-entire`、`transit-at-sunrise`、`transit-at-sunset`、`c1-horizon`、`c4-horizon`、`visible-at-c1`、`visible-at-c4`、`c1-isochrone` … `c4-isochrone` | 三个分区各有填充色;C1/C4 视地平与可见半球橙色;四触等时线各一色 |
| 凌日可见分区与接触线 | `transit-entire`、`transit-at-sunrise`、`transit-at-sunset`、`transit-partial`、`c1-horizon`、`c4-horizon`、`visible-at-c1`、`visible-at-c4`、`c1-isochrone` … `c4-isochrone` | 三个分区与部分凌日可见区各有填充色;C1/C4 视地平与可见半球橙色;四触等时线各一色 |
| 其他限界、轮廓、足迹与时间标记 | 其他 `role` | 灰色,面默认只画轮廓 |
`Style` 的零值字段沿用默认样式:
+16 -14
View File
@@ -32,7 +32,7 @@
- [位置与坐标](#位置与坐标)
- [升落与中天](#升落与中天)
- [合冲留与方照](#合冲留与方照)
- [大距与地心凌日](#大距与地心凌日)
- [大距与凌日](#大距与凌日)
- [节点、相位、视星等、视直径与视差角](#节点相位视星等视直径与视差角)
- [与其他手册的分工](#与其他手册的分工)
- [物理星历](#物理星历)
@@ -174,22 +174,22 @@ fmt.Println(saturn.NextProgradeToRetrograde(date)) // 土星下次顺转逆的
2020-05-11 17:26:53.961271941 +0800 CST
```
事件搜索取"当前或之后最近一次"并保持输入时区,成对的 `Last...` 与不区分方向的 `NextRetrograde` 见[合冲留与方照](#合冲留与方照);水星、金星的 `NextGreatestElongationEast` / `...West` 见[大距与地心凌日](#大距与地心凌日)。
事件搜索取"当前或之后最近一次"并保持输入时区,成对的 `Last...` 与不区分方向的 `NextRetrograde` 见[合冲留与方照](#合冲留与方照);水星、金星的 `NextGreatestElongationEast` / `...West` 见[大距与凌日](#大距与凌日)。
### 水星与金星凌日
```go
transit := mercury.NextTransit(date) // 2020 年之后下一场地心水星凌日
transit := mercury.NextTransit(date) // 2020 年之后下一场水星凌日
fmt.Println(transit.Valid, transit.Start, transit.Greatest) // 是否有凌日、一触与凌甚
fmt.Println(transit.Duration, transit.MinimumSeparationArcsec) // 历时与凌甚最小角距
```
```text
true 2032-11-13 14:41:13.161198198 +0800 CST 2032-11-13 16:54:12.821315824 +0800 CST
4h26m2.695272267s 572.0643215495325
true 2032-11-13 14:41:13.691189289 +0800 CST 2032-11-13 16:54:13.351347148 +0800 CST
4h26m2.484410405s 572.0831814505963
```
`TransitInfo.Valid` 为假表示搜索窗口内没有凌日、其余字段是零值;`TransitInfo` 是地心几何结果。某个地点看到的接触时刻用 `LocalTransit` 求站心结果:
`TransitInfo.Valid` 为假表示搜索窗口内没有凌日、其余字段是零值;其余情况下 `TransitInfo` 表示全球事件,接触字段是地心参考时刻。地心无接触时 `HasExternal` 为假,`Start` / `End` 也是零值,只有 `WindowStart` / `WindowEnd` 站心求解窗口有值。某个地点看到的接触时刻用 `LocalTransit` 求站心结果:
```go
transit := mercury.NextTransit(time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC))
@@ -200,15 +200,17 @@ fmt.Println(local.Start.Time, local.Start.SunAltitude) // 站心一触
```text
true true true
2019-11-11 12:36:09.037762284 +0000 UTC 7.933256722170642
2019-11-11 12:36:08.979182839 +0000 UTC 7.933092450591312
```
站心接触对太阳与行星分别做视差修正后重解,所以各地接触时刻与地心值不同:金星可达约 ±7 分钟,水星约 ±2 分钟。
- `SunAltitude` 是日心几何高度。
- `SunAltitude` 是太阳中心的几何高度,不含折射。
- `Visible`、`Sunrise`、`Sunset` 按太阳中心是否在视地平上判定,计入标准大气(1010 hPa、10 °C)折射,几何阈值约 −34′。
- 地心有内切接触、站心可能只是掠凌(例如 1999-11-15 水星凌日在南半球高纬),此时 `HasInternal` 为假,`InternalStart` / `InternalEnd` 是零值。
- 全球可见图与站心日面图见[日月食与凌日](eclipse.md#凌日出图);四触、偏凌与内切口径见[大距与地心凌日](#大距与地心凌日)。
- 全球可见图与站心日面图见[日月食与凌日](eclipse.md#凌日出图);四触、偏凌与内切口径见[大距与凌日](#大距与凌日)。
`Gamma` 是凌甚时影轴到地心的有符号距离(北侧为正),`PenumbralRadius` 是地心基本面上的半影半径,两者都以地球赤道半径为单位。凌日半影远大于地球,不要套用日食的 `|Gamma| < 1` 判断。`Series` 是周期族:金星平均 243 年、编号适用于天文年 −2000 至 +4000,水星平均 46 年、适用于 +1601 至 +2300;超出该范围或不属于已编号族时 `Number` 为 0,`PeriodYears` 仍给出平均周期。
### 相位、视直径、视星等与节点
@@ -348,7 +350,7 @@ fmt.Println(venus.AscendingNode(date), venus.DescendingNode(date))
76.86008484515058 256.8600848451506 // 金星升交点、降交点黄经,单位度
```
水星和金星还提供 `NextTransit` / `LastTransit` / `ClosestTransit` 地心凌日查询。这里的“地心”指从地球中心看到的行星圆面经过太阳圆面,不判断某个地点当时太阳是否在地平线上;观测计划用 `LocalTransit` 求站心接触与当时太阳高度(见[水星与金星凌日](#水星与金星凌日))。
水星和金星还提供 `NextTransit` / `LastTransit` / `ClosestTransit` 凌日查询。搜索返回全球事件,接触字段是地心参考时刻;地心无接触、只有部分地区可见的掠凌也会返回,这类事件是否成立按地表站心可见性判定。某个地点当时太阳是否在地平线上、当地看到哪些接触,用 `LocalTransit` 求站心结果(见[水星与金星凌日](#水星与金星凌日))。
```go
package main
@@ -553,11 +555,11 @@ fmt.Println(saturn.LastProgradeToRetrograde(date), saturn.NextProgradeToRetrogra
fmt.Println(saturn.LastRetrogradeToPrograde(date), saturn.NextRetrogradeToPrograde(date))
```
### 大距与地心凌日
### 大距与凌日
大距只对水星、金星有意义:`LastGreatestElongation` / `NextGreatestElongation` 不区分东西,`LastGreatestElongationEast` / `NextGreatestElongationEast` 与 `...West` 区分。
地心凌日的公开入口同样只在 `mercury` / `venus`:`LastTransit` / `NextTransit` / `ClosestTransit` 返回 `TransitInfo`。`Valid` 为假表示搜索窗口内没有凌日,其余字段都是零值;偏凌日没有内切,此时 `HasInternal` 为假、`InternalStart` / `InternalEnd` 是零值。凌日只判断地心几何,不判断某地当时太阳是否在地平线上。
凌日的公开入口同样只在 `mercury` / `venus`:`LastTransit` / `NextTransit` / `ClosestTransit` 返回 `TransitInfo`。`Valid` 为假表示搜索窗口内没有凌日,其余字段都是零值。地心无接触时 `HasExternal` 为假、`Start` / `End` 为零值,事件是否成立按地表站心可见性判定;站心内切不存在时 `HasInternal` 为假、`InternalStart` / `InternalEnd` 是零值。某个地点是否可见、看到哪些接触用 `LocalTransit` 判定。
```go
// 大距:区分东西用 ...East / ...West,不区分时用 NextGreatestElongation。
@@ -566,7 +568,7 @@ fmt.Println(venus.NextGreatestElongation(date))
```
```go
// 地心凌日:Valid 为假时其余字段为零值。
// 凌日:Valid 为假时其余字段为零值。
transit := mercury.NextTransit(date)
if transit.Valid {
fmt.Println(transit.Start, transit.InternalStart, transit.Greatest, transit.InternalEnd, transit.End)
@@ -859,7 +861,7 @@ fmt.Println(planet.WherePlanet(-1, 0, 2460000.5), planet.WherePlanet(4, 0, 24600
### 零值、越界与哨兵错误
事件搜索在窗口内没有事件时返回零值或 `Valid=false` 的结构(`TransitInfo.Valid`、`GalileanPhenomenonEvent.Valid`、`GalileanPhenomenonContactEvent.Valid`),不返回错误;`TransitInfo` 在 `HasInternal` 为假时 `InternalStart` / `InternalEnd` 为零值,偏凌日没有内切。
事件搜索在窗口内没有事件时返回零值或 `Valid=false` 的结构(`TransitInfo.Valid`、`GalileanPhenomenonEvent.Valid`、`GalileanPhenomenonContactEvent.Valid`),不返回错误;`TransitInfo` 在 `HasExternal` 为假时 `Start` / `End` 为零值,`HasInternal` 为假时 `InternalStart` / `InternalEnd` 为零值。
`planet.WherePlanet` / `planet.WherePlanetN` 的 `xt` / `zn` 越界返回 `NaN` 而不 panic;`...N` 的 `n < 0` 用完整级数,半解析的非负 `n` 用同一张快速表,Legacy 按 `n` 截断。`RiseTime` / `SetTime` / `DownTime`(含 `N` 版)当天没有几何升/落时返回下面的哨兵错误,时刻为零值。