目次
サンプル・プログラム:実行例

📅 の右側のテキストボックスをクリックすると、「PHPで日付入力:カレンダーから選択」で紹介したカレンダー入力を使った日付入力ができる。
このホロスコープは、左が春分点(黄経0度)で、反時計回りに黄道十二宮を配置している。
サンプル・プログラム
horoscope.php | サンプル・プログラム本体 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooAstronomy.php | 天文計算クラス pahooAstronomy。 使い方は「PHPでホロスコープを描く」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooCalendar.php | 暦計算クラス pahooCalendar。 暦計算クラスの使い方は「PHPで日出没・月出没・月齢・潮を計算」を参照。include_path が通ったディレクトリに配置すること。 |
/svg/*.svg | 黄道十二宮・惑星・月・太陽の記号(SVGファイル)。 |
バージョン | 更新日 | 内容 |
---|---|---|
2.2.0 | 2025/06/01 | 章動、光行差補正を追加 |
2.1 | 2022/04/24 | カラーコード計算修正,PHP8対応,リファラ・チェック改良 |
2.0 | 2019/06/02 | ラッキーカラーを追加 |
1.0 | 2019/03/23 | 初版 |
バージョン | 更新日 | 内容 |
---|---|---|
1.8.1 | 2025/03/15 | validRegexPattern() -- debug |
1.8.0 | 2024/11/12 | validRegexPattern() 追加 |
1.7.0 | 2024/10/09 | validURL() validEmail() 追加 |
1.6.0 | 2024/10/07 | isButton() -- buttonタグに対応 |
1.5.0 | 2024/01/28 | exitIfExceedVersion() 追加 |
バージョン | 更新日 | 内容 |
---|---|---|
4.5.1 | 2025/05/31 | deg2ddmm(), deg2hhmm() 不具合修正 |
4.5.0 | 2024/03/17 | ヒジュラ暦メソッドを追加 |
4.4.1 | 2024/03/17 | getCabinetOfficeHolidayTable() -- bug-fix |
4.4.0 | 2024/02/25 | 内閣府の祝日表を参照できるようにした |
4.3.2 | 2023/02/11 | getSolarTerm72() 表記改訂:水澤腹堅→水沢腹堅 |
バージョン | 更新日 | 内容 |
---|---|---|
2.1.0 | 2025/06/01 | euatorialCoordinate() を追加 |
2.0.0 | 2025/05/31 | 全面改訂, 天象を計算できるようにした. |
1.0 | 2019/03/23 | 初版 |
サンプル・プログラムの流れ
- 各惑星の日心黄道座標を計算する。
- 日心黄道座標から各惑星(太陽、月を含む)の地心黄道座標を計算する。
- ホロスコープを描く。
準備:定数
horoscope.php
37: //ホロスコープID
38: define('HOROSCOPE', 'horoscope');
39:
40: //ホロスコープを計算する時刻(日本標準時)
41: define('HOUR', 21);
42:
43: //ホロスコープの表示サイズ(単位:ピクセル)
44: define('RADIUS', 300); //外側の円の半径
45: define('WIDTH1', 50); //星座を描く部分の幅
46:
47: //ホロスコープの表示色
48: define('COLOR1', '#FFDD88'); //星座配置部分の色
49: define('COLOR2', '#FFFFCC'); //惑星配置部分の色
50: define('COLOR3', '#FFBB00'); //境界線の色
51: define('COLOR4', '#0000FF'); //星座アイコンの色
52: define('COLOR5', '#0000CC'); //惑星アイコンの色
53:
54: //ホロスコープの表示色
55: define('SVGPATH', './svg/'); //SVGアイコン・ファイルのパス名
56:
57: //誕生日の星座(初期値)
58: define('DEF_ZODIAC', 'Aries');
準備:アイコン・ファイルなど
horoscope.php
313: //黄道十二宮
314: $Zodiac = array(
315: // 英名 十二宮名 和名 記号 開始月日 開始黄経
316: array('Aries', '白羊宮', 'おひつじ座', 'U+2648', '0321', 0),
317: array('Taurus', '金牛宮', 'おうし座', 'U+2649', '0420', 30),
318: array('Gemini', '双児宮', 'ふたご座', 'U+264A', '0521', 60),
319: array('Cancer', '巨蟹宮', 'かに座', 'U+264B', '0622', 90),
320: array('Leo', '獅子宮', 'しし座', 'U+264C', '0723', 120),
321: array('Virgo', '処女宮', 'おとめ座', 'U+264D', '0823', 150),
322: array('Libra', '天秤宮', 'てんびん座', 'U+264E', '0923', 180),
323: array('Scorpio', '天蝎宮', 'さそり座', 'U+264F', '1024', 210),
324: array('Sagittarius', '人馬宮', 'いて座', 'U+2650', '1123', 240),
325: array('Capricorn', '磨羯宮', 'やぎ座', 'U+2651', '1222', 270),
326: array('Aquarius', '宝瓶宮', 'みずがめ座', 'U+2652', '0120', 300),
327: array('Pisces', '双魚宮', 'うお座', 'U+2653', '0219', 300)
328: );
horoscope.php
330: //惑星・太陽・月
331: $Planets = array(
332: // 英名 和名 記号 カラー
333: array('Sun', '太陽', 'U+2609', 'D68E31'),
334: array('Moon', '月', 'U+263D', 'DCDCDC'),
335: array('Mercury', '水星', 'U+263F', 'FFFF00'),
336: array('Venus', '金星', 'U+2640', '00FF00'),
337: array('Mars', '火星', 'U+2642', 'FF0000'),
338: array('Jupiter', '木星', 'U+2643', 'F312D8'),
339: array('Saturn', '土星', 'U+2644', '8B0000'),
340: array('Uranus', '天王星', 'U+2645', '00FFFF'),
341: array('Neptune', '海王星', 'U+2646', '00139F'),
342: array('Pluto', '冥王星', 'U+2647', '000000'),
343: array('Earth', '地球', 'U+1F728', '000000')
344: );
これらのファイルを、定数 SVGPATH に格納しておく。
準備:pahooAstronomy クラス
pahooAstronomy.php
11: require_once('pahooCalendar.php');
12:
13: // pahooAstronomyクラス ======================================================
14: class pahooAstronomy extends pahooCalendar {
解説:惑星の平均軌道要素

- 惑星は太陽を焦点とする楕円軌道を描く。
- 太陽から惑星に至る直線は、等時間に等面積を描く。
- 惑星の公転周期の二乗は、太陽からの平均距離の三乗に比例する。
惑星によって軌道の傾き方が異なる。そこで、基準面からの傾きを軌道傾角 $ i $ と呼ぶ。
すべての惑星は、反時計回りに公転している。基準面の南側から北側へ横切る位置を昇交点黄経 $ \Omega $ と呼ぶ。
公転軌道上で最も太陽に近づくときの黄経を近日点黄経 $ \omega $ と呼ぶ。
公転軌道(楕円)の長軸を半分にした長さを天文単位(au;地球と太陽の平均距離1とする)であらわしたものがきどうちょうはんけい $ a $ だ。
公転軌道(楕円)のつぶれ具合を軌道離心率 $ e $ と呼び、焦点と楕円の中心の距離を $ c $ とすると、$ \displaystyle e = \frac{c}{a} $ であらわすことができる。楕円軌道は $ 0 < e < 1 $ であり、$ e = 1 $ になると放物線軌道、$ e > 0 $ は双曲線軌道、$ e = 0 $ は円軌道になる。
軌道上の位置(黄経)は平均黄経 $ L $ と呼ぶ。

平均軌道要素は、国立天文台の暦Wiki に掲載されており、ここでは、「瞬時の平均春分点および黄道にもとづく座標系における平均軌道要素」を利用する。
ただし、冥王星は2006年(平成18年)に準惑星に降格された後は掲載されていないため、『天文年鑑』2002年(平成14年)版を参考にした。
pahooAstronomy.php
18: // 平均軌道要素
19: // 瞬時の平均春分点および黄道にもとづく座標系における平均軌道要素
20: // (出典)国立天文台 https://eco.mtk.nao.ac.jp/koyomi/wiki/CABFB6D1B5B0C6BBCDD7C1C7.html
21: var $PlanetOrbitalElements = array(
22: 'Mercury' => array(
23: 0.3870983098, +0.0, +0.0, // a 軌道長半径
24: 0.2056317526, +0.00002040653, -0.000000028349, // e 軌道離心率
25: 252.25090552, +538106659.820037, +1.0925943, // L 平均黄経
26: 77.45611904, +5603.042645, +1.0635716, // ω 近日点黄経
27: 7.00498625, +6.557301, -0.0651516, // i 軌道傾角
28: 48.33089304, 4270.001444, +0.6314994, // Ω 昇交点黄経
29: '内惑星',
30: ),
31: 'Venus' => array(
32: 0.7233298200, +0.0, +0.0, // a 軌道長半径
33: 0.0067719164, -0.00004776521, +0.000000098127, // e 軌道離心率
34: 181.97980085, +210669166.631989, +1.1165021, // L 平均黄経
35: 131.56370300, +5047.747081, -3.8742545, // ω 近日点黄経
36: 3.39466189, +3.613261, -0.0031523, // i 軌道傾角
37: 76.67992019, +3243.757636, +1.4622586, // Ω 昇交点黄経
38: '内惑星',
39: ),
40: 'Mars' => array(
41: 1.5236793419, +0.00000000003, +0.0, // a 軌道長半径
42: 0.0934006477, +0.00009048438, -0.000000080641, // e 軌道離心率
43: 355.43299958, +68910106.933069, 1.1178674, // L 平均黄経
44: 336.06023395, +6627.484990, +0.4851610, // ω 近日点黄経
45: 1.84972648, -2.163885, +0.0459350, // i 軌道傾角
46: 49.55809321, +2779.268736, +0.0560611, // Ω 昇交点黄経
47: '外惑星',
48: ),
49: 'Jupiter' => array(
50: 5.2026032092, +0.00000019132, -0.000000000039, // a 軌道長半径
51: 0.0484979255, +0.00016322542, -0.000000471366, // e 軌道離心率
52: 34.35151874, +10930689.989453, +0.8038700, // L 平均黄経
53: 14.33120687, +5805.486625, +3.7095016, // ω 近日点黄経
54: 1.30326698, -19.787442, +0.0167744, // i 軌道傾角
55: 100.46440702, +3675.518747, +1.4513295, // Ω 昇交点黄経
56: '外惑星',
57: ),
58: 'Saturn' => array(
59: 9.5549091915, -0.00000213896, +0.000000000444, // a 軌道長半径
60: 0.0555481426, -0.00034664062, -0.000000643639, // e 軌道離心率
61: 50.0774443, +4404639.847038, +1.8686817, // L 平均黄経
62: 93.05723748, +7069.540745, +3.0151155, // ω 近日点黄経
63: 2.48887878, -13.450388, -0.0546800, // i 軌道傾角
64: 113.66550252, +3157.516875, -0.4383321, // Ω 昇交点黄経
65: '外惑星',
66: ),
67: 'Uranus' => array(
68: 19.2184460618, -0.00000003716, +0.000000000979, // a 軌道長半径
69: 0.0463812221, -0.00002729293, +0.000000078913, // e 軌道離心率
70: 314.05500511, +1547510.601961, +1.0940272, // L 平均黄経
71: 173.00529106, +5350.964266, +0.7706068, // ω 近日点黄経
72: 0.77319689, +2.787845, +0.1349529, // i 軌道傾角
73: 74.00595701, +1876.059902, +4.8221068, // Ω 昇交点黄経
74: '外惑星',
75: ),
76: 'Neptune' => array(
77: 30.1103868694, -0.00000016635, +0.000000000686, // a 軌道長半径
78: 0.0094557470, +0.00000603263, +0.0, // e 軌道離心率
79: 304.34866548, +791579.913277, +1.1117536, // L 平均黄経
80: 48.12027554, +5134.664445, +1.3836149, // ω 近日点黄経
81: 1.76995259, -33.509412, -0.0254991, // i 軌道傾角
82: 131.78405702, +3967.934159, +0.9342773, // Ω 昇交点黄経
83: '外惑星',
84: ),
85: 'Pluto' => array(
86: 39.48168677, -0.00076912, +0.0, // a 軌道長半径
87: 0.24880766, +0.00006465, +0.0, // e 軌道離心率
88: 238.92881, (+145.2078 * 3600), -0.0, // L 平均黄経
89: 224.06676, (-0.0363 * 3600), +0.0, // ω 近日点黄経
90: 17.14175, (+0.00042 * 3600), +0.0, // i 軌道傾角
91: 110.30347, (+0.0112 * 3600), +0.0, // Ω 昇交点黄経
92: '外惑星',
93: ),
94: );
解説:惑星の日心黄道座標を求める

- $ E_0=L $
- $ \displaystyle \Delta E = L - E_0 + E\ sin \left( \dfrac{E_0}{1 - E \ cos(E_0)} \right) $
- $ E = E_0 + \Delta E $
- $ E_0 = E $
pahooAstronomy.php
130: /**
131: * ケプラー運動方程式の解法(漸化法)
132: * @param double $l 平均近点離角
133: * @param double $e 軌道離心率
134: * @return double 離心近点離角
135: */
136: function __kepler($M, $e, $eps = 1e-8) {
137: // 初期値
138: $M = deg2rad($M);
139: $E = $M;
140:
141: // ニュートン近似法
142: do {
143: $delta = ($E - $e * sin($E) - $M) / (1.0 - $e * cos($E));
144: $E -= $delta;
145: } while (abs($delta) > $eps);
146:
147: return rad2deg($E);
148: }
pahooAstronomy.php
150: /**
151: * 惑星の日心黄道座標を求める.
152: * @param string $planet 惑星名(Mercury, Venus, ... Pluto)
153: * @param int $year, $month, $day グレゴリオ暦による年月日
154: * @param double $hour, $min, $sec 時分秒(ローカル時間)
155: * @return array(黄経,黄緯,動径) (単位:度)/FALSE:惑星名の間違い
156: */
157: function zodiacSun($planet, $year, $month, $day, $hour, $min, $sec) {
158: // 惑星名のバリデーション
159: if (! isset($this->PlanetOrbitalElements[$planet])) return FALSE;
160:
161: // 平均軌道要素
162: $tbl = $this->PlanetOrbitalElements[$planet];
163:
164: // ユリウス世紀
165: $jd = $this->Gregorian2JD($year, $month, $day, $hour, $min, $sec, $this->TDIFF);
166: $T = $this->julianCentury($jd);
167:
168: // 平均軌道要素
169: $a = $tbl[0] + $tbl[1] * $T + $tbl[2] * $T * $T;
170: $e = $this->__angle($tbl[3] + $tbl[4] * $T + $tbl[5] * $T * $T);
171: $L = $this->__angle($tbl[6] + $tbl[7] / 3600.0 * $T + $tbl[8] / 3600.0 * $T * $T);
172: $omega = $this->__angle($tbl[9] + $tbl[10] / 3600.0 * $T + $tbl[11] / 3600.0 * $T * $T);
173: $i = $this->__angle($tbl[12] + $tbl[13] / 3600.0 * $T + $tbl[14] / 3600.0 * $T * $T);
174: $OMEGA = $this->__angle($tbl[15] + $tbl[16] / 3600.0 * $T + $tbl[17] / 3600.0 * $T * $T);
175:
176: // 平均近点角
177: $M = $this->__angle($L - $omega);
178: // 離心近点角
179: $E = $this->__kepler($M, $e);
180: // 真近点離角
181: $V = $this->__angle(2 * rad2deg(atan(sqrt((1 + $e) / (1 - $e)) * tan(deg2rad($E / 2)))));
182:
183: // 黄緯引数
184: $U = $this->__angle($omega + $V - $OMEGA);
185: // 動径
186: $r = $a * (1.0 - $e * $e) / (1.0 + $e * cos(deg2rad($V)));
187: $b = rad2deg(asin(sin(deg2rad($i)) * sin(deg2rad($U)))); //黄緯
188: $l = $this->__angle($OMEGA + rad2deg(atan(cos(deg2rad($i)) * sin(deg2rad($U)) / cos(deg2rad($U)))));
189: if (cos(deg2rad($U)) < 0) $l += 180.0; //黄経
190: $l = $this->__angle($l);
191:
192: return array($l, $b, $r);
193: }
解説:惑星の地心座標を求める

$$ \text{地心黄道座標} = \left\{ \begin{array}{l} r = \sqrt{X^2 + Y^2 + Z^2} \\ \beta = \arcsin \left( \dfrac{Z}{r} \right) \\ \lambda = \arctan2(Y, X) \end{array} \right. $$
$$ \arctan2(y, x) = \begin{cases} \tan^{-1} \left( \dfrac{y}{x} \right) & \text{if } x > 0 \\ \tan^{-1} \left( \dfrac{y}{x} \right) + \pi & \text{if } x < 0,\ y \geq 0 \\ \tan^{-1} \left( \dfrac{y}{x} \right) - \pi & \text{if } x < 0,\ y < 0 \\ +\dfrac{\pi}{2} & \text{if } x = 0,\ y > 0 \\ -\dfrac{\pi}{2} & \text{if } x = 0,\ y < 0 \\ \text{undefined} & \text{if } x = 0,\ y = 0 \end{cases} $$
pahooAstronomy.php
195: /**
196: * 惑星の地心黄道座標を求める.
197: * @param string $planet 惑星名(Mercury, Venus, ... Pluto)
198: * @param int $year, $month, $day グレゴリオ暦による年月日
199: * @param double $hour, $min, $sec 時分秒(ローカル時間)
200: * @return array(黄経,黄緯,動径) (単位:度)/FALSE:惑星名の間違い
201: */
202: function zodiacEarth($planet, $year, $month, $day, $hour, $min, $sec) {
203: // 惑星名のバリデーション
204: if (! isset($this->PlanetOrbitalElements[$planet])) return FALSE;
205:
206: // 日心黄道座標
207: list($l, $b, $r) = $this->zodiacSun($planet, $year, $month, $day, $hour, $min, $sec);
208: // 太陽黄経
209: $ls = $this->longitude_sun($year, $month, $day, $hour, $min, $sec, $this->TDIFF);
210: // 太陽距離
211: $rs = $this->distance_sun($year, $month, $day, $hour, $min, $sec, $this->TDIFF);
212:
213: // 直交座標へ変換
214: $X = $r * cos(deg2rad($b)) * cos(deg2rad($l)) + $rs * cos(deg2rad($ls));
215: $Y = $r * cos(deg2rad($b)) * sin(deg2rad($l)) + $rs * sin(deg2rad($ls));
216: $Z = $r * sin(deg2rad($b));
217:
218: // 地心黄道座標変換
219: $r1 = sqrt(pow($X, 2) + pow($Y, 2) + pow($Z, 2)); // 動径
220: $b1 = rad2deg(asin($Z / $r1)); // 黄緯
221: $l1 = rad2deg(atan($Y / $X));
222: if ($X < 0) $l1 += 180;
223: $l1 = $this->__angle($l1); // 黄経
224:
225: return array($l1, $b1, $r1);
226: }
解説:章動
歳差の運動に沿って、自転軸が小刻みに揺れることを章動と呼び、その主成分は18.6年周期である。
これらは、地心黄緯にはほどんど影響しないが、地心黄経に若干影響する。そこで、黄経の章動を求めるメソッド nutationInLongitude を用意した。
pahooAstronomy.php
228: /**
229: * 黄経の章動を求める.
230: * @param double $T ユリウス世紀
231: * @return double 黄経の章動(単位:度)
232: */
233: function nutationInLongitude($T) {
234: // 太陽の平均黄経(L)
235: $L = deg2rad(fmod(280.4665 + 36000.7698 * $T, 360.0));
236: // 月の昇交点の平均黄経(Ω)
237: $Omega = deg2rad(fmod(125.04452 - 1934.136261 * $T, 360.0));
238:
239: // 章動(経度)の近似式 [単位: 秒角]
240: $deltaPsi = -17.20 * sin($Omega) - 1.32 * sin(2 * $L);
241: $deltaPsi /= 3600.0; // 秒角 → 度
242:
243: return $deltaPsi; // Δψ [deg]
244: }
解説:光行差
こちらも地心黄緯にはほどんど影響しないが、地心黄経に若干影響する。そこで、黄経の章動を求めるメソッド aberrationCorrection を用意した。
pahooAstronomy.php
246: /**
247: * 黄経の光行差補正を求める.
248: * @param double $T ユリウス世紀
249: * @param double $sun_long_deg ユリウス世紀
250: * @return double 平均黄道傾斜(単位:度)
251: */
252: function aberrationCorrection($T, $sunLongDeg) {
253: // 地球軌道離心率と近日点黄経
254: $e = 0.016708634 - 0.000042037 * $T - 0.0000001267 * $T * $T;
255: $Pi = 102.93735 + 1.71946 * $T + 0.00046 * $T * $T; // 日心近日点黄経
256:
257: // 光行差補正 Δλ = -20.4898 / r * cos(λ - Π)(度)
258: $sunLongRad = deg2rad($sunLongDeg);
259: $PiRad = deg2rad($Pi);
260: $deltaLambda = -20.4898 * cos($sunLongRad - $PiRad) / 3600.0;
261:
262: return $deltaLambda;
263: }
解説:地心黄道座標の補正
pahooAstronomy.php
278: /**
279: * 惑星の地心黄道座標を求める.
280: * 光行差と章動を補正した視黄経を計算する。
281: * @param string $planet 惑星名(Mercury, Venus, ... Pluto)
282: * @param int $year, $month, $day グレゴリオ暦による年月日
283: * @param double $hour, $min, $sec 時分秒(ローカル時間)
284: * @return array(黄経,黄緯,動径) (単位:度)/FALSE:惑星名の間違い
285: */
286: function zodiacEarthAP($planet, $year, $month, $day, $hour, $min, $sec) {
287: // 惑星名のバリデーション
288: if (! isset($this->PlanetOrbitalElements[$planet])) return FALSE;
289:
290: list($lngE, $latE, $radE) = $this->zodiacEarth($planet, $year, $month, $day, $hour, $min, $sec);
291:
292: // ユリウス世紀
293: $jd = $this->AD2JD($year, $month, $day, $hour, $min, $sec, $this->TDIFF);
294: $T = $this->julianCentury($jd);
295:
296: $deltaPsi = $this->nutationInLongitude($T);
297: $aberration = $this->aberrationCorrection($T, $lngE);
298:
299: // 視黄経 = 幾何学黄経 + 光行差補正 + 章動補正
300: $lng2 = $lngE + $deltaPsi + $aberration;
301: $lngAP = fmod($lng2 + 360.0, 360.0); // 正規化
302:
303: return array($lngAP, $latE, $radE);
304: }
準備:ホロスコープを描く
horoscope.php
472: /**
473: * ホロスコープを描く
474: * @param int $year, $month, $day グレゴリオ暦による年月日
475: * @param string $zd 星座名(英名)
476: * @return string HTML BODY
477: */
478: function drawHoroscope($year, $month, $day, $zd) {
479: $id = HOROSCOPE;
480: $radius = RADIUS;
481: $width1 = WIDTH1;
482: $color1 = COLOR1;
483: $color2 = COLOR2;
484: $color3 = COLOR3;
485: $js1 = drawZodiac();
486: $js2 = drawPlanets($year, $month, $day, $zd);
487: $js =<<< EOT
488: <script>
489: onload = function() {
490: initJsdate({$year}, {$month}, {$day}); //年月日セレクタ
491:
492: var canvas = document.getElementById('{$id}');
493: if ( ! canvas || ! canvas.getContext ) { return false; }
494: var ctx = canvas.getContext('2d');
495: var r = {$radius};
496: var cx = r;
497: var cy = r;
498: var x, y;
499:
500: ctx.strokeStyle ='{$color3}';
501:
502: ctx.fillStyle = '{$color1}';
503: ctx.beginPath();
504: ctx.arc(cx, cx, r, 0, Math.PI * 2, false);
505: ctx.stroke();
506: ctx.fill();
507:
508: ctx.fillStyle = '{$color2}';
509: ctx.beginPath();
510: ctx.arc(cx, cy, r - {$width1}, 0, Math.PI * 2, false);
511: ctx.stroke();
512: ctx.fill();
513:
514: //12分割
515: for (var i = 0; i < 12; i++) {
516: var th = Math.PI - Math.PI * 2 / 12 * i;
517: x = r + r * Math.cos(th);
518: y = r + r * Math.sin(th);
519: ctx.moveTo(cx, cy);
520: ctx.lineTo(x, y);
521: ctx.stroke();
522: }
523: //黄道十二宮
524: {$js1}
525: //惑星・太陽・月
526: {$js2}
527: }
528: </script>
529:
530: EOT;
531:
532: return $js;
533: }

ユーザー関数 drawHoroscope では、まず、「jQueryで年月日セレクタを用意する」で紹介した年月日選択プルダウンをJavaScriptに実装する。

続いて、ホロスコープの円盤を描き、黄道十二宮と惑星・太陽・月のアイコンを配置する。
準備:黄道十二宮と惑星・太陽・月
horoscope.php
451: /**
452: * 黄道十二宮アイコンを配置
453: * @param int $year, $month, $day グレゴリオ暦による年月日
454: * @return string 描画スクリプト
455: */
456: function drawZodiac() {
457: global $Zodiac;
458:
459: $id = HOROSCOPE; //CANVASのID
460: $rd = RADIUS - (WIDTH1 * 0.5); //中心からの距離
461: $size = WIDTH1 * 0.7; //アイコンのサイズ
462: $color = COLOR4; //アイコンのカラー
463: $js = '';
464: for ($i = 0; $i < 12; $i++) {
465: $name = $Zodiac[$i][0];
466: $js .= drawIcon($i * 30 + 15, $rd, $name, $size, $color, $id);
467: }
468:
469: return $js;
470: }
horoscope.php
411: /**
412: * 惑星アイコンを配置+ラッキーカラー計算
413: * @param int $year, $month, $day グレゴリオ暦による年月日
414: * @param string $zd 星座名(英名)
415: * @return string 描画スクリプト
416: */
417: function drawPlanets($year, $month, $day, $zd) {
418: global $Planets;
419:
420: //オブジェクト生成
421: $pas = new pahooAstronomy();
422:
423: $id = HOROSCOPE; //CANVASのID
424: $size = WIDTH1 * 0.7; //アイコンのサイズ
425: $color = COLOR5; //アイコンのカラー
426: $js = '';
427: for ($i = 0; $i < 10; $i++) {
428: $name = $Planets[$i][0];
429: $rd = (RADIUS - WIDTH1 * 2) / 10 * $i + WIDTH1;
430: //太陽
431: if ($i == 0) {
432: $l = $pas->longitude_sun($year, $month, $day, HOUR, 0, 0);
433: //月
434: } else if ($i == 1) {
435: $l = $pas->longitude_moon($year, $month, $day, HOUR, 0, 0);
436: //惑星
437: } else {
438: $items = $pas->zodiacEarthAP($name, $year, $month, $day, HOUR - $pas->TDIFF, 0, 0);
439: $l = $items[0];
440: }
441: $js .= drawIcon($l, $rd, $name, $size, $color, $id);
442: calcColor($i, $l, $zd);
443: }
444:
445: //オブジェクト解放
446: $pas = NULL;
447:
448: return $js;
449: }
ホロスコープは平面なので、必要なのは地心黄経だけである。drawPlanets では、前述のメソッド zodiacEarth を使って惑星の地心黄経を、メソッド longitude_sun を使って太陽の黄経を、メソッド longitude_moon を使って月の黄経を求める。
準備:SVGアイコンを1つ描く
horoscope.php
375: /**
376: * SVGアイコンを1つ描く
377: * @param string $th 黄経(度)
378: * @param string $rd 中心からの距離(ピクセル)
379: * @param string $name アイコン名(主ファイル名)
380: * @param string $size アイコンのサイズ(ピクセル)
381: * @param string $color アイコンのカラー(RGB指定)
382: * @param string $id CANVASのID
383: * @return string 描画スクリプト
384: */
385: function drawIcon($th, $rd, $name, $size, $color, $id) {
386: //描画座標
387: $th = 180 - $th;
388: $th = deg2rad($th);
389: $x = RADIUS + $rd * cos($th) - $size / 2;
390: $y = RADIUS + $rd * sin($th) - $size / 2;
391:
392: //SVGファイルの読み込み
393: $fname = SVGPATH . $name . '.svg';
394: $svg = file_get_contents($fname);
395: $svg = preg_replace('/\#000000/ums', $color, $svg); //色指定
396: $svg = 'data:image/svg+xml;base64,' . base64_encode($svg);
397:
398: //スクリプト生成
399: $js = <<< EOD
400: var img_{$name} = new Image();
401: img_{$name}.src = '{$svg}';
402: img_{$name}.onload = function() {
403: var ctx = document.getElementById('{$id}').getContext('2d');
404: ctx.drawImage(img_{$name}, {$x}, {$y}, {$size}, {$size});
405: }
406:
407: EOD;
408: return $js;
409: }
SVGファイルを読み込み、デフォルトでは黒(#000000)で描画されている部分を指定カラーに置換する。
つづいて BASE64 エンコードを行い、JavaScriptの Image オブジェクトのソースとして展開する。

配置場所は地心黄経(度)$th を代入するだけなので、準惑星や彗星でも地心黄道座標さえ分かれば、なんでも配置できる。
準備:ラッキーカラー計算
horoscope.php
349: /**
350: * ラッキーカラー計算
351: * @param int $i 惑星番号
352: * @param float $th 黄経(度)
353: * @param string $zd 星座名(英名)
354: * @return string 描画スクリプト
355: */
356: function calcColor($i, $th, $zd) {
357: global $Zodiac, $Planets, $Pcolor;
358:
359: foreach ($Zodiac as $val) {
360: if ($val[0] == $zd) {
361: $dd = ($th - $val[5] - 15);
362: if ($dd < (-180)) $dd += 360;
363: $dd = (180 - abs($dd)) / 180;
364: $Pcolor[0] += $dd;
365: for ($j = 0; $j < 3; $j++) {
366: $cc = hexdec(substr($Planets[$i][3], $j * 2, 2));
367: $cc *= $dd;
368: $Pcolor[$j + 1] += $cc;
369: }
370: break;
371: }
372: }
373: }
ラッキーカラーの計算アルゴリズムは、$Planets に定義した惑星カラーを合成するものである。誕生日星座の中心座標と各惑星の座標の黄経差に応じて、離れているものほど色が暗くなるように合成している。
参考サイト
- PHPで二十四節気・七十二候一覧を作成:ぱふぅ家のホームページ
- PHPで月齢を計算:ぱふぅ家のホームページ
- jQueryで年月日セレクタを用意する:ぱふぅ家のホームページ
- PHPで日付入力:カレンダーから選択:ぱふぅ家のホームページ
- 『かくして冥王星は降格された』(ニール・ド・グラス・タイソン/吉田三知世,2009年08月)
- 暦Wiki:国立天文台
余談になるが、参考書籍に紹介している『天文計算入門』の初版は1978年(昭和53年)に発刊され、これを買って、関数電卓「FX-31」でハレー彗星の位置計算を行ったのが、私のプログラミングの事始めで、もう40年も前の話になる。
今回のプログラムのアルゴリズムは、当時のものを踏襲している。地心黄経さえ求められれば、準惑星や彗星もホロスコープ上に配置することができる。
(2025年6月1日)章動、光行差補正を追加.pahooAstronomyクラスを全面改訂.