astro_chart 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/lib/astro_chart/astrocartography.rb +109 -0
- data/lib/astro_chart/ephemeris.rb +6 -0
- data/lib/astro_chart/pure/moon.rb +8 -2
- data/lib/astro_chart/pure/pluto.rb +10 -3
- data/lib/astro_chart/pure/vsop87.rb +25 -3
- data/lib/astro_chart/pure.rb +17 -0
- data/lib/astro_chart/version.rb +1 -1
- data/lib/astro_chart.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 373643f3dc987aeb880aad6a15a5dd6a509367683c7ee1463ce7086b3e06980f
|
|
4
|
+
data.tar.gz: ec28b6b542ae7aaaa03997e744718b62dcf6a69c4372e1fcdb5196cb87110e4e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e5a812f264e71b82bbe09489d7098254b29f0e7fb648c2eb84aa244091d7e62cebab9cfaa7420da59b44392227bc3dc1b110c1aaa6f6dbe02de60ab6a80e5a3a
|
|
7
|
+
data.tar.gz: 9c8e709366b24a5c28db55223c68edbfe1e705f9b9ec4d95f1e5dae1a6a72e6d8419597d900c80f832126b2bb53c930ddf636d4e7db93bc4ca7208346f8e8905
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.1 (2026-08-07)
|
|
4
|
+
|
|
5
|
+
**Ecliptic latitude → accurate astrocartography.** Additive.
|
|
6
|
+
|
|
7
|
+
- New `AstroChart::Ephemeris.ecliptic_latlon(jd, id)` — apparent geocentric
|
|
8
|
+
ecliptic [longitude, latitude] for the Sun, Moon, VSOP87 planets and Pluto
|
|
9
|
+
(the geocentric vector was already computed; latitude was simply discarded).
|
|
10
|
+
- `Astrocartography.lines` now forms RA/Dec from each body's **true** ecliptic
|
|
11
|
+
latitude instead of β = 0, so the Moon and Pluto lines (β up to ~5° / ~17°)
|
|
12
|
+
are placed correctly. The longitude methods delegate to the new latitude-
|
|
13
|
+
aware ones, so planetary longitudes remain byte-identical (Swiss oracle spec
|
|
14
|
+
still passes).
|
|
15
|
+
|
|
16
|
+
## 0.5.0 (2026-08-07)
|
|
17
|
+
|
|
18
|
+
**Astrocartography (星象地圖).** All pure Ruby, additive.
|
|
19
|
+
|
|
20
|
+
- New `AstroChart::Astrocartography.lines(jd)` — the relocational map lines for
|
|
21
|
+
the ten bodies at a birth instant: the MC and IC meridian longitudes, and
|
|
22
|
+
the ASC (rising) and DSC (setting) horizon curves as latitude/longitude
|
|
23
|
+
segments (broken where a body is circumpolar). Built from the body's RA/Dec
|
|
24
|
+
and Greenwich apparent sidereal time; verified independently (body altitude
|
|
25
|
+
≈ 0 along every ASC/DSC point, LST = RA on the MC). Ecliptic latitude is
|
|
26
|
+
approximated as 0 (exact for the Sun; largest error for the Moon/Pluto).
|
|
27
|
+
|
|
3
28
|
## 0.4.0 (2026-08-06)
|
|
4
29
|
|
|
5
30
|
**Traditional dignities, transit timing, two more house systems, minor
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
require_relative "ephemeris"
|
|
2
|
+
require_relative "pure/core"
|
|
3
|
+
|
|
4
|
+
module AstroChart
|
|
5
|
+
# Astrocartography (星象地圖 / relocational lines).
|
|
6
|
+
#
|
|
7
|
+
# For a fixed birth instant, every body is angular (on the horizon or the
|
|
8
|
+
# meridian) along particular curves across the globe. We return, per body,
|
|
9
|
+
# four lines in geographic coordinates (longitude east-positive, −180..180):
|
|
10
|
+
#
|
|
11
|
+
# MC — the body culminates on the upper meridian (a vertical meridian).
|
|
12
|
+
# IC — the body is on the lower meridian (a vertical meridian).
|
|
13
|
+
# ASC — the body rises on the eastern horizon (a curve of latitude points).
|
|
14
|
+
# DSC — the body sets on the western horizon (a curve of latitude points).
|
|
15
|
+
#
|
|
16
|
+
# Method (Meeus, positional astronomy): from the body's apparent ecliptic
|
|
17
|
+
# longitude λ and the true obliquity ε we form its equatorial coordinates
|
|
18
|
+
# (RA α, Dec δ); with the Greenwich apparent sidereal time (GST):
|
|
19
|
+
# MC longitude = α − GST
|
|
20
|
+
# IC longitude = α − GST + 180°
|
|
21
|
+
# and at latitude φ the body is on the horizon when its hour angle is
|
|
22
|
+
# H = ±arccos(−tanφ·tanδ) (no solution ⇒ circumpolar, the line ends),
|
|
23
|
+
# rising at H = −H0 (eastern), setting at H = +H0 (western), giving
|
|
24
|
+
# longitude = α + H − GST.
|
|
25
|
+
#
|
|
26
|
+
# RA/Dec use each body's true apparent ecliptic latitude (via
|
|
27
|
+
# Ephemeris.ecliptic_latlon), so the lines are accurate for the high-latitude
|
|
28
|
+
# bodies (Moon, Pluto) too — not just longitude-only approximations.
|
|
29
|
+
module Astrocartography
|
|
30
|
+
Core = Pure::Core
|
|
31
|
+
DEG2RAD = Core::DEG2RAD
|
|
32
|
+
RAD2DEG = Core::RAD2DEG
|
|
33
|
+
|
|
34
|
+
# The ten bodies conventionally mapped.
|
|
35
|
+
BODIES = ["太陽", "月亮", "水星", "金星", "火星", "木星",
|
|
36
|
+
"土星", "天王星", "海王星", "冥王星"].freeze
|
|
37
|
+
|
|
38
|
+
# Latitude span and step for the rising/setting curves (degrees).
|
|
39
|
+
LAT_MIN = -75
|
|
40
|
+
LAT_MAX = 75
|
|
41
|
+
LAT_STEP = 1
|
|
42
|
+
|
|
43
|
+
module_function
|
|
44
|
+
|
|
45
|
+
# jd_ut: birth Julian Day (UT).
|
|
46
|
+
# Returns Array of:
|
|
47
|
+
# { "planet" => "太陽",
|
|
48
|
+
# "mc" => <lon>, "ic" => <lon>, # single geographic longitudes
|
|
49
|
+
# "asc" => [ [ [lat,lon], ... ], ... ], # rising curve, as segments
|
|
50
|
+
# "dsc" => [ [ [lat,lon], ... ], ... ] } # setting curve, as segments
|
|
51
|
+
def lines(jd_ut)
|
|
52
|
+
gst = Core.apparent_sidereal_deg(jd_ut)
|
|
53
|
+
eps = Core.true_obliquity(Core.jd_tt(jd_ut)) * DEG2RAD
|
|
54
|
+
|
|
55
|
+
BODIES.map do |name|
|
|
56
|
+
lam_deg, beta_deg = Ephemeris.ecliptic_latlon(jd_ut, Ephemeris::PLANETS[name])
|
|
57
|
+
lam = lam_deg * DEG2RAD
|
|
58
|
+
beta = beta_deg * DEG2RAD
|
|
59
|
+
# RA/Dec from apparent ecliptic longitude, latitude and obliquity
|
|
60
|
+
# (Meeus, Astronomical Algorithms, eqs. 13.3–13.4).
|
|
61
|
+
ra = Core.norm360(Math.atan2(
|
|
62
|
+
Math.sin(lam) * Math.cos(eps) - Math.tan(beta) * Math.sin(eps),
|
|
63
|
+
Math.cos(lam)
|
|
64
|
+
) * RAD2DEG)
|
|
65
|
+
dec = Math.asin(Math.sin(beta) * Math.cos(eps) + Math.cos(beta) * Math.sin(eps) * Math.sin(lam))
|
|
66
|
+
|
|
67
|
+
{
|
|
68
|
+
"planet" => name,
|
|
69
|
+
"mc" => norm180(ra - gst),
|
|
70
|
+
"ic" => norm180(ra - gst + 180.0),
|
|
71
|
+
"asc" => horizon_curve(ra, dec, gst, :rising),
|
|
72
|
+
"dsc" => horizon_curve(ra, dec, gst, :setting),
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Segments of [lat, lon] points where the body is on the eastern (rising)
|
|
78
|
+
# or western (setting) horizon. A circumpolar latitude breaks the curve, so
|
|
79
|
+
# the result is an array of contiguous segments (each a polyline).
|
|
80
|
+
def horizon_curve(ra_deg, dec_rad, gst, mode)
|
|
81
|
+
tan_dec = Math.tan(dec_rad)
|
|
82
|
+
segments = []
|
|
83
|
+
current = []
|
|
84
|
+
lat = LAT_MIN.to_f
|
|
85
|
+
while lat <= LAT_MAX
|
|
86
|
+
x = -Math.tan(lat * DEG2RAD) * tan_dec
|
|
87
|
+
if x.abs <= 1.0
|
|
88
|
+
h0 = Math.acos(x) * RAD2DEG
|
|
89
|
+
hour = mode == :rising ? -h0 : h0
|
|
90
|
+
current << [lat.round(2), norm180(ra_deg + hour - gst)]
|
|
91
|
+
elsif !current.empty?
|
|
92
|
+
segments << current
|
|
93
|
+
current = []
|
|
94
|
+
end
|
|
95
|
+
lat += LAT_STEP
|
|
96
|
+
end
|
|
97
|
+
segments << current unless current.empty?
|
|
98
|
+
segments
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Normalize degrees to (−180, 180].
|
|
102
|
+
def norm180(deg)
|
|
103
|
+
d = Core.norm360(deg)
|
|
104
|
+
d > 180.0 ? d - 360.0 : d
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private_class_method :horizon_curve, :norm180
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -102,6 +102,12 @@ module AstroChart
|
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
+
# Apparent geocentric ecliptic [longitude, latitude] in degrees. Pure
|
|
106
|
+
# backend only (the Swiss extension exposes latitude via its own API).
|
|
107
|
+
def self.ecliptic_latlon(jd, planet_id)
|
|
108
|
+
Pure.ecliptic_latlon(jd, planet_id)
|
|
109
|
+
end
|
|
110
|
+
|
|
105
111
|
# Apparent daily motion in ecliptic longitude (degrees/day), via central
|
|
106
112
|
# difference of calc_ut at jd ± 0.5 day. The difference is folded into
|
|
107
113
|
# (-180, 180] so the 0°/360° wraparound never produces a spurious value.
|
|
@@ -182,10 +182,16 @@ module AstroChart
|
|
|
182
182
|
# --- 月球視黃經(度,[0,360))。引數 **JD(UT)**。 ---
|
|
183
183
|
# 幾何黃經(平春分點 of date)+ 章動 Δψ = 視黃經(真春分點 of date)。
|
|
184
184
|
def apparent_longitude(jd_ut)
|
|
185
|
+
apparent_ecliptic(jd_ut)[0]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Apparent geocentric ecliptic [longitude, latitude] in degrees. JD(UT).
|
|
189
|
+
# ELP-2000 gives β directly; nutation shifts longitude only.
|
|
190
|
+
def apparent_ecliptic(jd_ut)
|
|
185
191
|
tt = Core.jd_tt(jd_ut)
|
|
186
|
-
lam,
|
|
192
|
+
lam, beta, = geometric_position(tt)
|
|
187
193
|
dpsi_deg, = Core.nutation(tt)
|
|
188
|
-
Core.norm360(lam + dpsi_deg)
|
|
194
|
+
[Core.norm360(lam + dpsi_deg), beta]
|
|
189
195
|
end
|
|
190
196
|
|
|
191
197
|
# --- 真(密切)北交點視黃經(度,[0,360))。引數 **JD(UT)**。 ---
|
|
@@ -94,6 +94,11 @@ module AstroChart
|
|
|
94
94
|
# 冥王星視黃道經度(度,真春分點 of date)。
|
|
95
95
|
# jd_ut: JD(UT)。超出 Meeus Ch. 37 適用範圍(1885–2099)raise DomainError。
|
|
96
96
|
def apparent_longitude(jd_ut)
|
|
97
|
+
apparent_ecliptic(jd_ut)[0]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Apparent geocentric ecliptic [longitude, latitude] in degrees. JD(UT).
|
|
101
|
+
def apparent_ecliptic(jd_ut)
|
|
97
102
|
jd_tt = Core.jd_tt(jd_ut)
|
|
98
103
|
unless jd_tt >= JD_TT_MIN && jd_tt < JD_TT_MAX
|
|
99
104
|
raise Core::DomainError,
|
|
@@ -121,9 +126,11 @@ module AstroChart
|
|
|
121
126
|
tau = new_tau
|
|
122
127
|
end
|
|
123
128
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
dpsi, = Core.nutation(jd_tt) # 平春分點 of date → 真春分點
|
|
130
|
+
[
|
|
131
|
+
Core.norm360(Math.atan2(gy, gx) * RAD2DEG + dpsi),
|
|
132
|
+
Math.asin(gz / Math.sqrt(gx * gx + gy * gy + gz * gz)) * RAD2DEG,
|
|
133
|
+
]
|
|
127
134
|
end
|
|
128
135
|
|
|
129
136
|
# --- 冥王星日心直角座標(AU,黃道座標,旋轉到 jd_frame_tt 的平春分點) ---
|
|
@@ -61,6 +61,20 @@ module AstroChart
|
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
# Apparent geocentric ecliptic [longitude, latitude] in degrees. The Sun's
|
|
65
|
+
# geocentric ecliptic latitude is ~0 (well under 1″), returned as 0.0.
|
|
66
|
+
def apparent_ecliptic(planet_id, jd_ut)
|
|
67
|
+
tt = Core.jd_tt(jd_ut)
|
|
68
|
+
if planet_id == SUN_ID
|
|
69
|
+
[sun_apparent_longitude(tt), 0.0]
|
|
70
|
+
elsif PLANET_KEYS.key?(planet_id)
|
|
71
|
+
planet_apparent_ecliptic(PLANET_KEYS.fetch(planet_id), tt)
|
|
72
|
+
else
|
|
73
|
+
raise Core::DomainError,
|
|
74
|
+
"Vsop87 不支援 planet_id=#{planet_id}(僅太陽 0 與行星 2..8)"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
64
78
|
# --- 太陽(Meeus Ch. 25 高精度法) ---
|
|
65
79
|
def sun_apparent_longitude(jd_tt)
|
|
66
80
|
l, _b, r = heliocentric_fk5(:earth, jd_tt)
|
|
@@ -75,8 +89,14 @@ module AstroChart
|
|
|
75
89
|
# 重算——兩者同取 t-τ 等效把光行時與(地球速度造成的)光行差
|
|
76
90
|
# 一併涵蓋(planetary aberration;Meeus Ch. 33 註)。τ 迭代兩輪。
|
|
77
91
|
def planet_apparent_longitude(planet_key, jd_tt)
|
|
92
|
+
planet_apparent_ecliptic(planet_key, jd_tt)[0]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Geocentric apparent ecliptic [longitude, latitude] (degrees) for a VSOP87
|
|
96
|
+
# planet, via the light-time-corrected geocentric rectangular vector.
|
|
97
|
+
def planet_apparent_ecliptic(planet_key, jd_tt)
|
|
78
98
|
tau = 0.0
|
|
79
|
-
x = y = 0.0
|
|
99
|
+
x = y = z = 0.0
|
|
80
100
|
2.times do
|
|
81
101
|
ex, ey, ez = heliocentric_rect(:earth, jd_tt - tau)
|
|
82
102
|
px, py, pz = heliocentric_rect(planet_key, jd_tt - tau)
|
|
@@ -86,9 +106,11 @@ module AstroChart
|
|
|
86
106
|
delta = Math.sqrt(x * x + y * y + z * z)
|
|
87
107
|
tau = LIGHT_TIME_DAYS_PER_AU * delta
|
|
88
108
|
end
|
|
89
|
-
lambda_deg = Math.atan2(y, x) * RAD2DEG
|
|
90
109
|
dpsi_deg, = Core.nutation(jd_tt)
|
|
91
|
-
|
|
110
|
+
[
|
|
111
|
+
Core.norm360(Math.atan2(y, x) * RAD2DEG + dpsi_deg),
|
|
112
|
+
Math.asin(z / Math.sqrt(x * x + y * y + z * z)) * RAD2DEG,
|
|
113
|
+
]
|
|
92
114
|
end
|
|
93
115
|
|
|
94
116
|
# --- 日心黃道直角座標(FK5 修正後;黃道與分點皆為 of date) ---
|
data/lib/astro_chart/pure.rb
CHANGED
|
@@ -49,6 +49,23 @@ module AstroChart
|
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
# Apparent geocentric ecliptic [longitude, latitude] in degrees for the Sun,
|
|
53
|
+
# Moon, VSOP87 planets and Pluto (nodes are not physical bodies).
|
|
54
|
+
def ecliptic_latlon(jd_ut, planet_id)
|
|
55
|
+
case planet_id
|
|
56
|
+
when *VSOP87_PLANET_IDS
|
|
57
|
+
Vsop87.apparent_ecliptic(planet_id, jd_ut)
|
|
58
|
+
when MOON_ID
|
|
59
|
+
Moon.apparent_ecliptic(jd_ut)
|
|
60
|
+
when PLUTO_ID
|
|
61
|
+
Pluto.apparent_ecliptic(jd_ut)
|
|
62
|
+
else
|
|
63
|
+
raise ArgumentError,
|
|
64
|
+
"ecliptic_latlon unsupported planet_id #{planet_id.inspect} " \
|
|
65
|
+
"(supported: Sun 0, planets 2-8, Moon, Pluto)"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
52
69
|
# House cusps + ascendant + MC. Placidus ("P") and Whole Sign ("W").
|
|
53
70
|
# hsys accepts "P"/"W" or 80/87 (ord values) to mirror the C extension's int argument.
|
|
54
71
|
def houses(jd_ut, latitude, longitude, hsys = "P")
|
data/lib/astro_chart/version.rb
CHANGED
data/lib/astro_chart.rb
CHANGED
|
@@ -20,6 +20,7 @@ require_relative "astro_chart/progressions"
|
|
|
20
20
|
require_relative "astro_chart/composite"
|
|
21
21
|
require_relative "astro_chart/solar_return"
|
|
22
22
|
require_relative "astro_chart/draconic"
|
|
23
|
+
require_relative "astro_chart/astrocartography"
|
|
23
24
|
require_relative "astro_chart/dignities"
|
|
24
25
|
require_relative "astro_chart/profection"
|
|
25
26
|
require_relative "astro_chart/transit_timing"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: astro_chart
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Huang Yudi
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: tzinfo
|
|
@@ -69,6 +69,7 @@ files:
|
|
|
69
69
|
- astro_chart.gemspec
|
|
70
70
|
- lib/astro_chart.rb
|
|
71
71
|
- lib/astro_chart/aspects.rb
|
|
72
|
+
- lib/astro_chart/astrocartography.rb
|
|
72
73
|
- lib/astro_chart/chart.rb
|
|
73
74
|
- lib/astro_chart/composite.rb
|
|
74
75
|
- lib/astro_chart/dignities.rb
|