astro_chart 0.1.0 → 0.4.0

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +122 -0
  3. data/LICENSE +17 -16
  4. data/README.md +417 -0
  5. data/astro_chart.gemspec +11 -6
  6. data/lib/astro_chart/aspects.rb +31 -2
  7. data/lib/astro_chart/chart.rb +94 -12
  8. data/lib/astro_chart/composite.rb +101 -0
  9. data/lib/astro_chart/dignities.rb +220 -0
  10. data/lib/astro_chart/draconic.rb +64 -0
  11. data/lib/astro_chart/ephemeris.rb +125 -18
  12. data/lib/astro_chart/houses.rb +2 -1
  13. data/lib/astro_chart/lunar_return.rb +90 -0
  14. data/lib/astro_chart/patterns.rb +248 -0
  15. data/lib/astro_chart/points.rb +82 -0
  16. data/lib/astro_chart/profection.rb +56 -0
  17. data/lib/astro_chart/progressions.rb +68 -0
  18. data/lib/astro_chart/pure/core.rb +209 -0
  19. data/lib/astro_chart/pure/houses.rb +207 -0
  20. data/lib/astro_chart/pure/moon.rb +341 -0
  21. data/lib/astro_chart/pure/moon_elp.rb +931 -0
  22. data/lib/astro_chart/pure/pluto.rb +220 -0
  23. data/lib/astro_chart/pure/vsop87.rb +152 -0
  24. data/lib/astro_chart/pure/vsop87_data.rb +210 -0
  25. data/lib/astro_chart/pure.rb +68 -0
  26. data/lib/astro_chart/solar_arc.rb +59 -0
  27. data/lib/astro_chart/solar_return.rb +193 -0
  28. data/lib/astro_chart/stats.rb +34 -0
  29. data/lib/astro_chart/synastry.rb +118 -0
  30. data/lib/astro_chart/transit_timing.rb +186 -0
  31. data/lib/astro_chart/transits.rb +108 -0
  32. data/lib/astro_chart/version.rb +1 -1
  33. data/lib/astro_chart.rb +19 -1
  34. metadata +36 -45
  35. data/ext/astro_chart/astro_chart_ext.c +0 -99
  36. data/ext/astro_chart/extconf.rb +0 -8
  37. data/ext/astro_chart/swecl.c +0 -6428
  38. data/ext/astro_chart/swedate.c +0 -588
  39. data/ext/astro_chart/swedate.h +0 -81
  40. data/ext/astro_chart/swedll.h +0 -403
  41. data/ext/astro_chart/sweephe4.c +0 -702
  42. data/ext/astro_chart/sweephe4.h +0 -239
  43. data/ext/astro_chart/swehel.c +0 -3511
  44. data/ext/astro_chart/swehouse.c +0 -3143
  45. data/ext/astro_chart/swehouse.h +0 -98
  46. data/ext/astro_chart/swejpl.c +0 -958
  47. data/ext/astro_chart/swejpl.h +0 -103
  48. data/ext/astro_chart/swemmoon.c +0 -1930
  49. data/ext/astro_chart/swemplan.c +0 -967
  50. data/ext/astro_chart/swemptab.h +0 -10640
  51. data/ext/astro_chart/swenut2000a.h +0 -2819
  52. data/ext/astro_chart/sweodef.h +0 -326
  53. data/ext/astro_chart/sweph.c +0 -8614
  54. data/ext/astro_chart/sweph.h +0 -849
  55. data/ext/astro_chart/swephexp.h +0 -1020
  56. data/ext/astro_chart/swephlib.c +0 -4634
  57. data/ext/astro_chart/swephlib.h +0 -189
@@ -0,0 +1,108 @@
1
+ require_relative "pure"
2
+ require_relative "ephemeris"
3
+ require_relative "zodiac"
4
+ require_relative "aspects"
5
+ require_relative "houses"
6
+ require_relative "planets"
7
+ require_relative "synastry"
8
+
9
+ module AstroChart
10
+ # Transits (行運): where the planets are in the sky right now (or at any
11
+ # moment), compared against a natal chart.
12
+ #
13
+ # Pure composition of existing modules — Planets.calculate_positions gives
14
+ # the sky positions for any JD, Houses.find_house places them into the
15
+ # natal houses, and Aspects.calculate scores transit-to-natal contacts.
16
+ #
17
+ # Typical usage with a Chart#generate result:
18
+ #
19
+ # jd = AstroChart::TimeConversion.to_julian_day("2026-07-24", "12:00", "Asia/Taipei")
20
+ # AstroChart::Transits.at(jd) # 天象快照 { "太陽" => 121.9, ... }
21
+ # AstroChart::Transits.against(natal_chart, jd) # 行運行星落入本命宮位 + 行運相位
22
+ module Transits
23
+ # Bodies used for transit-to-natal aspects. Mirrors Synastry: 南交點 is
24
+ # excluded because it sits exactly opposite 北交點 — every south-node
25
+ # aspect would just mirror a north-node one and double the noise.
26
+ ASPECT_BODIES = Synastry::BODIES
27
+
28
+ # Sky snapshot at a Julian Day.
29
+ #
30
+ # Returns { "太陽" => 123.45, ..., "南交點" => 303.45 } — ecliptic
31
+ # longitudes (total degrees 0-360) for the 12 bodies
32
+ # (Ephemeris::PLANETS + 南交點 = 北交點 + 180°).
33
+ def self.at(jd)
34
+ Planets.calculate_positions(jd)
35
+ end
36
+
37
+ # Transits against a natal chart (a Chart#generate result hash).
38
+ #
39
+ # jd: Julian Day of the transit moment.
40
+ # orb_limit: keep only aspects with orb <= limit (default 3.0 — transit
41
+ # practice uses much tighter orbs than the natal defaults in Aspects).
42
+ #
43
+ # Returns:
44
+ # {
45
+ # "planets" => [ { "planet" => "木星", "zodiac" => "獅子座",
46
+ # "degree" => 5.1, "total_degree" => 125.1,
47
+ # "natal_house" => 7 }, ... 12 entries ],
48
+ # "aspects" => [ { "transit_planet" => "土星", "natal_planet" => "太陽",
49
+ # "aspect_type" => "四分相", "orb" => 1.23 }, ... ]
50
+ # }
51
+ #
52
+ # aspects are sorted by orb (tightest first).
53
+ def self.against(natal_chart, jd, orb_limit: 3.0)
54
+ transit_positions = at(jd)
55
+ natal_positions = Synastry.positions_from_chart(natal_chart)
56
+ natal_cusps = Synastry.cusps_from_chart(natal_chart)
57
+
58
+ {
59
+ "planets" => planet_details(transit_positions, natal_cusps),
60
+ "aspects" => aspects_to_natal(transit_positions, natal_positions,
61
+ orb_limit: orb_limit,
62
+ keys: %w[transit_planet natal_planet]),
63
+ }
64
+ end
65
+
66
+ # Build the per-planet detail list, placing each transiting body into
67
+ # the natal houses.
68
+ def self.planet_details(positions, natal_cusps)
69
+ positions.map do |name, pos|
70
+ {
71
+ "planet" => name,
72
+ "zodiac" => Zodiac.sign_name(pos),
73
+ "degree" => (pos % 30).round(4),
74
+ "total_degree" => pos.round(4),
75
+ "natal_house" => Houses.find_house(pos, natal_cusps),
76
+ }
77
+ end
78
+ end
79
+
80
+ # Aspects from moving positions to natal positions, filtered by
81
+ # orb_limit and sorted by orb. `keys` names the two hash keys so
82
+ # Progressions can reuse this with "progressed_planet".
83
+ def self.aspects_to_natal(moving_positions, natal_positions, orb_limit:,
84
+ keys: %w[transit_planet natal_planet])
85
+ moving_key, natal_key = keys
86
+ results = []
87
+
88
+ moving_positions.each do |m_name, m_pos|
89
+ next unless ASPECT_BODIES.include?(m_name)
90
+
91
+ natal_positions.each do |n_name, n_pos|
92
+ aspect_type, orb = Aspects.calculate(m_pos, n_pos)
93
+ next if aspect_type.nil?
94
+ next if orb_limit && orb > orb_limit
95
+
96
+ results << {
97
+ moving_key => m_name,
98
+ natal_key => n_name,
99
+ "aspect_type" => aspect_type,
100
+ "orb" => orb,
101
+ }
102
+ end
103
+ end
104
+
105
+ results.sort_by { |r| r["orb"] }
106
+ end
107
+ end
108
+ end
@@ -1,3 +1,3 @@
1
1
  module AstroChart
2
- VERSION = "0.1.0"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/astro_chart.rb CHANGED
@@ -1,12 +1,30 @@
1
1
  require_relative "astro_chart/version"
2
- require_relative "astro_chart/astro_chart_ext"
2
+ # NOTE: the Swiss Ephemeris C extension (astro_chart_ext) is NOT loaded here.
3
+ # The default backend is pure Ruby; the extension is required on demand by
4
+ # `AstroChart.backend = :swiss` so environments without a compiled extension
5
+ # still work out of the box.
6
+ require_relative "astro_chart/pure"
3
7
  require_relative "astro_chart/ephemeris"
4
8
  require_relative "astro_chart/zodiac"
5
9
  require_relative "astro_chart/aspects"
6
10
  require_relative "astro_chart/houses"
7
11
  require_relative "astro_chart/time_conversion"
8
12
  require_relative "astro_chart/planets"
13
+ require_relative "astro_chart/points"
14
+ require_relative "astro_chart/patterns"
15
+ require_relative "astro_chart/stats"
16
+ require_relative "astro_chart/synastry"
9
17
  require_relative "astro_chart/chart"
18
+ require_relative "astro_chart/transits"
19
+ require_relative "astro_chart/progressions"
20
+ require_relative "astro_chart/composite"
21
+ require_relative "astro_chart/solar_return"
22
+ require_relative "astro_chart/draconic"
23
+ require_relative "astro_chart/dignities"
24
+ require_relative "astro_chart/profection"
25
+ require_relative "astro_chart/transit_timing"
26
+ require_relative "astro_chart/solar_arc"
27
+ require_relative "astro_chart/lunar_return"
10
28
 
11
29
  module AstroChart
12
30
  end
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.1.0
4
+ version: 0.4.0
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-02-01 00:00:00.000000000 Z
11
+ date: 2026-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tzinfo
@@ -52,65 +52,55 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '13.0'
55
- - !ruby/object:Gem::Dependency
56
- name: rake-compiler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.2'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.2'
69
- description: A Ruby gem for natal astrology chart calculation, powered by Swiss Ephemeris
70
- C library with Moshier ephemeris. No external data files needed.
55
+ description: 'Astrology chart calculation in pure Ruby: apparent planetary longitudes
56
+ (VSOP87D, ELP-2000/82B moon, Meeus Pluto), Placidus and whole-sign houses, retrograde
57
+ flags, aspects, derived points (Part of Fortune, mean Lilith), aspect-pattern detection
58
+ and element statistics, plus synastry, transits, secondary progressions, composite
59
+ charts and solar returns. No C extension, no external data files. Implemented from
60
+ public formulas (Meeus, Astronomical Algorithms 2nd ed.).'
71
61
  email:
72
62
  executables: []
73
- extensions:
74
- - ext/astro_chart/extconf.rb
63
+ extensions: []
75
64
  extra_rdoc_files: []
76
65
  files:
66
+ - CHANGELOG.md
77
67
  - LICENSE
68
+ - README.md
78
69
  - astro_chart.gemspec
79
- - ext/astro_chart/astro_chart_ext.c
80
- - ext/astro_chart/extconf.rb
81
- - ext/astro_chart/swecl.c
82
- - ext/astro_chart/swedate.c
83
- - ext/astro_chart/swedate.h
84
- - ext/astro_chart/swedll.h
85
- - ext/astro_chart/sweephe4.c
86
- - ext/astro_chart/sweephe4.h
87
- - ext/astro_chart/swehel.c
88
- - ext/astro_chart/swehouse.c
89
- - ext/astro_chart/swehouse.h
90
- - ext/astro_chart/swejpl.c
91
- - ext/astro_chart/swejpl.h
92
- - ext/astro_chart/swemmoon.c
93
- - ext/astro_chart/swemplan.c
94
- - ext/astro_chart/swemptab.h
95
- - ext/astro_chart/swenut2000a.h
96
- - ext/astro_chart/sweodef.h
97
- - ext/astro_chart/sweph.c
98
- - ext/astro_chart/sweph.h
99
- - ext/astro_chart/swephexp.h
100
- - ext/astro_chart/swephlib.c
101
- - ext/astro_chart/swephlib.h
102
70
  - lib/astro_chart.rb
103
71
  - lib/astro_chart/aspects.rb
104
72
  - lib/astro_chart/chart.rb
73
+ - lib/astro_chart/composite.rb
74
+ - lib/astro_chart/dignities.rb
75
+ - lib/astro_chart/draconic.rb
105
76
  - lib/astro_chart/ephemeris.rb
106
77
  - lib/astro_chart/houses.rb
78
+ - lib/astro_chart/lunar_return.rb
79
+ - lib/astro_chart/patterns.rb
107
80
  - lib/astro_chart/planets.rb
81
+ - lib/astro_chart/points.rb
82
+ - lib/astro_chart/profection.rb
83
+ - lib/astro_chart/progressions.rb
84
+ - lib/astro_chart/pure.rb
85
+ - lib/astro_chart/pure/core.rb
86
+ - lib/astro_chart/pure/houses.rb
87
+ - lib/astro_chart/pure/moon.rb
88
+ - lib/astro_chart/pure/moon_elp.rb
89
+ - lib/astro_chart/pure/pluto.rb
90
+ - lib/astro_chart/pure/vsop87.rb
91
+ - lib/astro_chart/pure/vsop87_data.rb
92
+ - lib/astro_chart/solar_arc.rb
93
+ - lib/astro_chart/solar_return.rb
94
+ - lib/astro_chart/stats.rb
95
+ - lib/astro_chart/synastry.rb
108
96
  - lib/astro_chart/time_conversion.rb
97
+ - lib/astro_chart/transit_timing.rb
98
+ - lib/astro_chart/transits.rb
109
99
  - lib/astro_chart/version.rb
110
100
  - lib/astro_chart/zodiac.rb
111
101
  homepage: https://github.com/morriedig/astro_chart
112
102
  licenses:
113
- - AGPL-3.0
103
+ - MIT
114
104
  metadata: {}
115
105
  post_install_message:
116
106
  rdoc_options: []
@@ -130,5 +120,6 @@ requirements: []
130
120
  rubygems_version: 3.4.10
131
121
  signing_key:
132
122
  specification_version: 4
133
- summary: Natal chart calculation using Swiss Ephemeris
123
+ summary: Pure-Ruby astrology chart calculation (planets, Placidus/whole-sign houses,
124
+ aspects, synastry, transits, progressions, composite, solar returns)
134
125
  test_files: []
@@ -1,99 +0,0 @@
1
- #include <ruby.h>
2
- #include "swephexp.h"
3
-
4
- static VALUE mAstroChart;
5
- static VALUE mExt;
6
-
7
- /*
8
- * AstroChart::Ext.julday(year, month, day, hour) -> Float
9
- *
10
- * Convert a date/time to Julian Day number using Gregorian calendar.
11
- */
12
- static VALUE rb_julday(VALUE self, VALUE year, VALUE month, VALUE day, VALUE hour) {
13
- int y = NUM2INT(year);
14
- int m = NUM2INT(month);
15
- int d = NUM2INT(day);
16
- double h = NUM2DBL(hour);
17
-
18
- double jd = swe_julday(y, m, d, h, SE_GREG_CAL);
19
- return DBL2NUM(jd);
20
- }
21
-
22
- /*
23
- * AstroChart::Ext.calc_ut(jd, planet_id) -> Float
24
- *
25
- * Calculate planet ecliptic longitude using Moshier ephemeris.
26
- * Returns the longitude in degrees (0-360).
27
- */
28
- static VALUE rb_calc_ut(VALUE self, VALUE jd, VALUE planet_id) {
29
- double tjd = NUM2DBL(jd);
30
- int ipl = NUM2INT(planet_id);
31
- double xx[6];
32
- char serr[256];
33
-
34
- int32 ret = swe_calc_ut(tjd, ipl, SEFLG_MOSEPH, xx, serr);
35
- if (ret < 0) {
36
- rb_raise(rb_eRuntimeError, "swe_calc_ut failed: %s", serr);
37
- }
38
-
39
- return DBL2NUM(xx[0]); /* ecliptic longitude */
40
- }
41
-
42
- /*
43
- * AstroChart::Ext.houses(jd, latitude, longitude, system) -> Hash
44
- *
45
- * Calculate house cusps and ascendant/MC.
46
- * system: ASCII code for house system (e.g. 'P' = 80 for Placidus)
47
- *
48
- * Returns a Hash with:
49
- * "cusps" => Array of 12 house cusp degrees
50
- * "ascendant" => Ascendant degree
51
- * "mc" => MC degree
52
- */
53
- static VALUE rb_houses(VALUE self, VALUE jd, VALUE lat, VALUE lon, VALUE hsys) {
54
- double tjd = NUM2DBL(jd);
55
- double geolat = NUM2DBL(lat);
56
- double geolon = NUM2DBL(lon);
57
- int system = NUM2INT(hsys);
58
-
59
- double cusps[13]; /* cusps[0] unused, cusps[1..12] */
60
- double ascmc[10];
61
-
62
- swe_houses(tjd, geolat, geolon, system, cusps, ascmc);
63
-
64
- VALUE result = rb_hash_new();
65
- VALUE cusps_ary = rb_ary_new_capa(12);
66
-
67
- int i;
68
- for (i = 1; i <= 12; i++) {
69
- rb_ary_push(cusps_ary, DBL2NUM(cusps[i]));
70
- }
71
-
72
- rb_hash_aset(result, rb_str_new_cstr("cusps"), cusps_ary);
73
- rb_hash_aset(result, rb_str_new_cstr("ascendant"), DBL2NUM(ascmc[0]));
74
- rb_hash_aset(result, rb_str_new_cstr("mc"), DBL2NUM(ascmc[1]));
75
-
76
- return result;
77
- }
78
-
79
- void Init_astro_chart_ext(void) {
80
- mAstroChart = rb_define_module("AstroChart");
81
- mExt = rb_define_module_under(mAstroChart, "Ext");
82
-
83
- rb_define_module_function(mExt, "julday", rb_julday, 4);
84
- rb_define_module_function(mExt, "calc_ut", rb_calc_ut, 2);
85
- rb_define_module_function(mExt, "houses", rb_houses, 4);
86
-
87
- /* Planet ID constants */
88
- rb_define_const(mExt, "SUN", INT2NUM(SE_SUN));
89
- rb_define_const(mExt, "MOON", INT2NUM(SE_MOON));
90
- rb_define_const(mExt, "MERCURY", INT2NUM(SE_MERCURY));
91
- rb_define_const(mExt, "VENUS", INT2NUM(SE_VENUS));
92
- rb_define_const(mExt, "MARS", INT2NUM(SE_MARS));
93
- rb_define_const(mExt, "JUPITER", INT2NUM(SE_JUPITER));
94
- rb_define_const(mExt, "SATURN", INT2NUM(SE_SATURN));
95
- rb_define_const(mExt, "URANUS", INT2NUM(SE_URANUS));
96
- rb_define_const(mExt, "NEPTUNE", INT2NUM(SE_NEPTUNE));
97
- rb_define_const(mExt, "PLUTO", INT2NUM(SE_PLUTO));
98
- rb_define_const(mExt, "TRUE_NODE", INT2NUM(SE_TRUE_NODE));
99
- }
@@ -1,8 +0,0 @@
1
- require "mkmf"
2
-
3
- # Swiss Ephemeris source files to compile alongside our extension
4
- $srcs = Dir.glob("#{$srcdir}/*.c").map { |f| File.basename(f) }
5
-
6
- $CFLAGS << " -DNO_SWE_GLP"
7
-
8
- create_makefile("astro_chart/astro_chart_ext")