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

📅 の右側のテキストボックスをクリックすると、「PHPで日付入力:カレンダーから選択」で紹介したカレンダー入力を使った日付入力ができる。
このホロスコープは、左が春分点(黄経0度)で、反時計回りに黄道十二宮を配置している。
サンプル・プログラム
horoscope.php | サンプル・プログラム本体 |
pahooAstronomy.php | 天文計算クラス pahooAstronomy。 使い方は「PHPでホロスコープを描く」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooCalendar.php | 暦計算クラス pahooCalendar。 暦計算クラスの使い方は「PHPで日出没・月出没・月齢・潮を計算」を参照。include_path が通ったディレクトリに配置すること。 |
jsdate.js | 年月日セレクタを用意するJavaScript。 使い方は「jQueryで年月日セレクタを用意する」を参照。 |
/svg/*.svg | 黄道十二宮・惑星・月・太陽の記号(SVGファイル)。 |
サンプル・プログラムの流れ
- 各惑星の日心座標を計算する。
- 各惑星(太陽、月を含む)の地心座標を計算する。
- ホロスコープを描く。
準備:定数
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');
準備:アイコン・ファイルなど
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: );
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 クラス
10: require_once('pahooCalendar.php');
11:
12: // pahooAstronomyクラス ======================================================
13: class pahooAstronomy extends pahooCalendar {
解説:惑星の日心座標を求める
17: // 平均軌道要素
18: var $PlanetOrbitalElements = array(
19: 'Mercury' => array(
20: 252.2509, +4.0932377062, +0.000303, //L 平均黄経
21: 77.4561, +1.556401, +0.000295, //ω 近日点黄経
22: 48.3309, +1.186112, +0.000175, //Ω 昇交点黄経
23: 7.0050, +0.001821, //i 軌道傾角
24: 0.205632, +0.00002040, //e 軌道離心率
25: +0.387098, 0.0 //a 軌道長半径
26: ),
27: 'Venus' => array(
28: 181.9798, +1.602168732, +0.000310, //L 平均黄経
29: 131.5637, +1.402152, -0.001076, //ω 近日点黄経
30: 76.6799, +0.901044, +0.000406, //Ω 昇交点黄経
31: 3.3947, +0.001004, //i 軌道傾角
32: 0.006772, -0.00004778, //e 軌道離心率
33: 0.723330, 0.0 //a 軌道長半径
34: ),
35: 'Mars' => array(
36: 355.4330, +0.524071085, +0.000311, //L 平均黄経
37: 336.0602, +1.840968, +0.000135, //ω 近日点黄経
38: 49.5581, +0.772019, +0.0, //Ω 昇交点黄経
39: 1.8497, -0.000601, //i 軌道傾角
40: 0.093401, +0.00009048, //e 軌道離心率
41: +1.523679, 0.0 //a 軌道長半径
42: ),
43: 'Jupiter' => array(
44: 34.3515, +0.083129439, +0.000223, //L 平均黄経
45: 14.3312, +1.612635, +0.001030, //ω 近日点黄経
46: 100.4644, +1.020977, +0.000403, //Ω 昇交点黄経
47: 1.3033, -0.005496, //i 軌道傾角
48: 0.048498, +0.00016323, //e 軌道離心率
49: 5.202603, 0.0 //a 軌道長半径
50: ),
51: 'Saturn' => array(
52: 50.0774, +0.033497907, +0.000519, //L 平均黄経
53: 93.0572, +1.963761, +0.000838, //ω 近日点黄経
54: 113.665, +0.877088, -0.000121, //Ω 昇交点黄経
55: 2.4889, -0.003736, //i 軌道傾角
56: 0.055548, -0.00034664, //e 軌道離心率
57: 9.554909, -0.0000021 //a 軌道長半径
58: ),
59: 'Uranus' => array(
60: 314.0550, +0.011769036, +0.000304, //L 平均黄経
61: 173.0053, +1.486378, +0.000214, //ω 近日点黄経
62: 74.0060, +0.521127, +0.001339, //Ω 昇交点黄経
63: 0.7732, +0.000774, //i 軌道傾角
64: 0.046381, -0.00002729, //e 軌道離心率
65: 19.218446, -0.000003 //a 軌道長半径
66: ),
67: 'Neptune' => array(
68: 304.3487, +0.006020077, +0.000309, //L 平均黄経
69: 48.1203, +1.426296, +0.000384, //ω 近日点黄経
70: 131.784, +1.102204, +0.000260, //Ω 昇交点黄経
71: 1.7700, -0.009308, //i 軌道傾角
72: 0.009456, +0.00000603, //e 軌道離心率
73: 30.110387, 0.0 //a 軌道長半径
74: ),
75: 'Pluto' => array(
76: 238.4670, +0.00401596, -0.0091, //L 平均黄経
77: 224.1416, +1.3901, +0.0003, //ω 近日点黄経
78: 110.3182, +1.3507, +0.0004, //Ω 昇交点黄経
79: 17.1451, -0.0055, //i 軌道傾角
80: 0.249005, +0.000039, //e 軌道離心率
81: 39.540343, +0.003131 //a 軌道長半径
82: )
83: );





惑星は、太陽を焦点の1つとする楕円軌道を描く。これは、1639年(寛永16年)に発表されたケプラーの法則の第1法則である。

日心黄道座標を求めるには、まず、指定された日時の軌道6要素(黄経






この計算式は『天文年鑑』に掲載されている。水星から海王星までは2019年(平成31年)版を、冥王星は2006年(平成18年)に準惑星に降格された後は掲載されていないため2002年(平成14年)版を参考にした。計算に使う係数はグローバル変数 $PlanetOrbitalElements に、計算式そのものはメソッド zodiacSun に実装した。

軌道6要素から日心黄道座標を求める計算式を示す。
















真近点角


解説:惑星の地心座標を求める

準備:ホロスコープを描く
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に実装する。

続いて、ホロスコープの円盤を描き、黄道十二宮と惑星・太陽・月のアイコンを配置する。
準備:黄道十二宮と惑星・太陽・月
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: }
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->zodiacEarth($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つ描く
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 を代入するだけなので、準惑星や彗星でも地心黄道座標さえ分かれば、なんでも配置できる。
準備:ラッキーカラー計算
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で日付入力:カレンダーから選択:ぱふぅ家のホームページ
- 天文年鑑 2019年(平成31年)版:誠文堂新光社
余談になるが、参考書籍に紹介している『天文計算入門』の初版は1978年(昭和53年)に発刊され、これを買って、関数電卓「FX-31」でハレー彗星の位置計算を行ったのが、私のプログラミングの事始めで、もう40年も前の話になる。
今回のプログラムのアルゴリズムは、当時のものを踏襲している。地心黄経さえ求められれば、準惑星や彗星もホロスコープ上に配置することができる。
(2022年4月24日)カラーコード計算修正,PHP8対応,リファラ・チェック改良