PHPで地図上に恵方を表示

(1/1)
PHPで二十四節気・七十二候一覧を作成」では、毎年の節分の日を計算するプログラムを作成した。節分の日に恵方の方角を向いて恵方巻きを無言で食べると良いとされるが、この恵方は、年によって方角が変化する。そこで今回は、PHPを使い、指定した年の恵方の方角を地図上に矢印で描くPHPプログラムを作ってみることにする。

(2025年8月31日).pahooEnv対応, pahooInputData.php導入
(2025年7月20日)矢印の視点にマーカーを描くようにした.
(2025年6月14日)GoogleMaps JavaScript APIの変更に対応した.

目次

サンプル・プログラムの実行例

PHPで地図上に恵方を表示
Googleマップ

サンプル・プログラムのダウンロード

圧縮ファイルの内容
eho.phpサンプル・プログラム本体
.pahooEnvクラウドサービスを利用するためのアカウント情報などを記入する .env ファイル。
使い方は「各種クラウド連携サービス(WebAPI)の登録方法」を参照。include_path が通ったディレクトリに配置すること。
pahooCalendar.php暦計算クラス pahooCalendar。
暦計算クラスの使い方は「PHPで日出没・月出没・月齢・潮を計算」を参照。include_path が通ったディレクトリに配置すること。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」などを参照。include_path が通ったディレクトリに配置すること。
searchCafeHotpepper.php 更新履歴
バージョン 更新日 内容
1.1.0 2025/08/13 .pahooEnv導入
1.0 2022/01/10 初版
pahooGeoCode.php 更新履歴
バージョン 更新日 内容
6.8.0 2025/08/10 アクセスキーなどを ".pahooEnd" に分離
6.7.1 2025/07/26 jsLine_Gmap() - bug-fix
6.7.0 2025/07/20 drawJSmap,drawGMap -- 引数 $markerLevel 追加
6.6.0 2025/07/19 drawJSmap,drawGMap,drawLeaflet -- マップ中心マーカー表示引数を追加
6.5.0 2025/06/14 GoogleMaps JavaScript APIの変更に対応
pahooCalendar.php 更新履歴
バージョン 更新日 内容
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() 表記改訂:水澤腹堅→水沢腹堅
pahooInputData.php 更新履歴
バージョン 更新日 内容
2.0.1 2025/08/11 getParam() bug-fix
2.0.0 2025/08/11 pahooLoadEnv() 追加
1.9.0 2025/07/26 getParam() 引数に$trim追加
1.8.1 2025/03/15 validRegexPattern() debug
1.8.0 2024/11/12 validRegexPattern() 追加

恵方とは

恵方ロールケーキを食べる男の子のイラスト
節分の日に恵方の方角を向いて恵方巻きを無言で食べると良いとされるが、この恵方は、年によって方角が変化する。

もともとは、正月に各家庭で迎える歳神 (としがみ) 様がやって来る方角を意味していた。旧暦では立春が正月にあたるので、その前日の節分に、歳神様を迎える準備をする。
陰陽道が普及すると、恵方の方角に、その年の歳徳神 (としとくじん) (恵方神)がいて、祟り神が巡ってこない良い方角とされた。
恵方は、その年の十干 (じっかん) によって決まる。十干は、甲・乙・丙・丁・戊・己・庚・辛・壬・癸の10の要素が割り当てられている。つまり、年号を10で割った余りで、その年の十干を知ることができる。
恵方は4種類しかなく、たとえば甲の年と己の年の恵方は同じである。
十干と恵方の対応を整理すると、下表のようになる。
十干 西暦の下1桁 恵方
4 東北東微東 75度
5 西南西微西 255度
6 南南東微南 165度
7 北北西微北 345度
8 南南東微南 165度
9 東北東微東 75度
0 西南西微西 255度
1 南南東微南 165度
2 北北西微北 345度
3 南南東微南 165度

準備:PHP の https対応

クラウド連携や相手先サイトのデータを読み込むのに https通信を使うため、PHPに OpenSSLモジュールが組み込まれている必要がある。関数  phpinfo  を使って、下図のように表示されればOKだ。
OpenSSL - PHP
そうでない場合は、次の手順に従ってOpenSSLを有効化し、PHPを再起動させる必要がある。

Windowsでは、"php.ini" の下記の行を有効化する。
extension=php_openssl.dll
Linuxでは --with-openssl=/usr オプションを付けて再ビルドする。→OpenSSLインストール手順

これで準備は完了だ。

準備:pahooInputData 関数群

PHPのバージョンや入力データのバリデーションなど、汎用的に使う関数群を収めたファイル "pahooInputData.php" が同梱されているが、include_path が通ったディレクトリに配置してほしい。他のプログラムでも "pahooInputData.php" を利用するが、常に最新のファイルを1つ配置すればよい。

また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。

準備:pahooCalendar クラス

pahooCalendar.php

  11: class pahooCalendar {
  12:     var $CONVERGE = 0.00005;            //逐次近似計算収束判定値
  13:     var $ASTRO_REFRACT = 0.585556;      //大気差
  14:     var $TDIFF = +9.0;          //世界時との時差
  15:     var $error, $errmsg;        //エラーフラグ,エラーメッセージ
  16:     var $year, $month, $day;    //西暦年月日
  17:     var $tblmoon;               //グレゴリオ暦=旧暦テーブル
  18:     var $language;              //表示言語(jp:日本語, en:英語, en3:英語略記)
  19:     var $resolve2033;           //旧暦2033年問題解決案 0:解決しない,1:案1,2:案2,3:対応案3 → https://www.pahoo.org/e-soul/webtech/php02/php02-45-01.shtm#php_resolveLunarCalendar2033
  20:     var $pcc;                   //pahooCacheインスタンス
  21:     var $CabinetOfficeHolidayTables;    //内閣府が公開している祝日表
  22:     const CABINETOFFICE_HOLIDAY_FILE = 'https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv';   //内閣府が公開している祝日表URL
  23: 
  24: /**
  25:  * コンストラクタ
  26:  * @param   string $language 表示言語;省略時 jp
  27:  * @param   float  $tdiff    世界時との時差(省略時 +9.0;日本標準時)
  28:  * @param   object $pcc      pahooCacheインスタンス;省略時 NULL
  29:  *              インターネット経由で内閣府の国民の祝日を参照するときに指定
  30:  * @return  bool オブジェクト/FALSE:$tdiffが不正
  31: */
  32: function __construct($language='jp', $tdiff=+9.0, $pcc=NULL) {
  33:     $this->error  = FALSE;
  34:     $this->errmsg = '';
  35:     $this->year  = date('Y');
  36:     $this->month = date('n');
  37:     $this->day   = date('j');
  38:     $this->resolve2033 = 0;
  39:     $this->pcc = $pcc;
  40:     $this->CabinetOfficeHolidayTables = array();
  41: 
  42:     $this->setLanguage($language);
  43:     if ($this->setTimeDifference($tdiff) == FALSE) {
  44:         $this->error = TRUE;
  45:         $this->errmsg = 'illegal tdiff';
  46:     }
  47: }

西暦(グレゴリオ暦)計算やヒジュラ暦(イスラム暦)への変換、祝祭日、六曜、二十四節気の算出などの暦関係の計算、太陽や月の位置計算、潮位などを求めるクラス・ファイル "pahooCalendar.php" が同梱されているが、include_path が通ったディレクトリに配置してほしい。他のプログラムでも "pahooCalendar.php" を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。

準備:pahooGeoCode クラス

pahooGeoCode.php

  40: class pahooGeoCode {
  41:     public $items;      // 検索結果格納用
  42:     public $error;      // エラー・フラグ
  43:     public $errmsg;     // エラー・メッセージ
  44:     public $hits;       // 検索ヒット件数
  45:     public $webapi// 直前に呼び出したWebAPI URL
  46: 
  47:     // -- 以下のデータは .env ファイルに記述可能
  48:     // Google Cloud Platform APIキー
  49:     // https://cloud.google.com/maps-platform/
  50:     // ※Google Maps APIを利用しないのなら登録不要
  51:     public $GOOGLE_API_KEY_1 = '';      // HTTPリファラ用
  52:     public $GOOGLE_API_KEY_2 = '';      // IP制限用
  53:     public $GOOGLE_MAP_ID    = '';      // GoogleMaps ID
  54: 
  55:     // Yahoo! JAPAN Webサービス アプリケーションID
  56:     // https://e.developer.yahoo.co.jp/register
  57:     // ※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  58:     public $YAHOO_APPLICATION_ID = '';
  59: 
  60:     // OSM Nominatim Search API利用時に知らせるメールアドレス
  61:     // https://wiki.openstreetmap.org/wiki/JA:Nominatim#.E6.A4.9C.E7.B4.A2
  62:     // ※OSM Nominatim Search APIを利用しないのなら登録不要
  63:     public $NOMINATIM_EMAIL = '';
  64: 
  65:     // IP2Location.io APIキー
  66:     // https://www.ip2location.io/
  67:     // ※IP2Location.ioを利用しないのなら登録不要
  68:     public $IP2LOCATION_API_KEY = '';

GoogleマップやLeafletなどによる地図描画や住所検索を行うためのクラスが pahooGeoCode である。同梱のクラス・ファイル "pahooGeoCode.php" は include_path が通ったディレクトリに配置してほしい。他のプログラムでも pahooGeoCodeクラス を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。

地図や住所検索として Google を利用するのであれば Google Cloud Platform APIキーマップID が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、IP2Location.ioを利用するのであれば「PHPでIPアドレスやホスト名から住所を求める」を、それぞれ参照されたい。

PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

準備:地図サービス(WebAPI)の選択

eho.php

  57: // 地図サービス(WebAPI)の選択
  58: //    0:Google
  59: //    2:地理院地図・OSM
  60: define('MAPSERVICE', 2);

表示する地図は、Googleマップと地理院地図・OSMから選べる。
あらかじめ、定数 MAPSERVICE に値を設定すること。

準備:住所検索サービス(WebAPI)の選択

eho.php

  62: // 住所検索サービスの選択
  63: //    0:Google
  64: //    1:Yahoo!JAPAN
  65: //   11:HeartRails Geo API
  66: //   12:OSM Nominatim Search API
  67: define('GEOSERVICE', 0);

住所やワンドマークから緯度・軽度を検索するWebAPIを選ぶことができる。
あらかじめ、定数 GEOSERVICE に値を設定すること。

準備:各種パラメータ

eho.php

  76: // マップの表示サイズ(単位:ピクセル)
  77: define('MAP_WIDTH',  600);
  78: define('MAP_HEIGHT', 400);
  79: // マップID
  80: define('MAPID', 'map_id');
  81: // マップ中心マーカーのURL;表示しなくなければNULLにする
  82: define('CENTER_MARKER', 'https://maps.google.com/mapfiles/ms/micons/ltblu-pushpin.png');
  83: 
  84: // 初期値
  85: define('DEF_LONGITUDE', 139.766667);    // 地図中心(経度)
  86: define('DEF_LATITUDE',  35.681111);     //    (緯度)
  87: define('DEF_QUERY',     '東京駅');      // 検索クエリ
  88: define('DEF_TYPE',      'roadmap');     // マップタイプ
  89: define('DEF_ZOOM',      12);            // ズーム
  90: define('DEF_CAT',       'address');     // カテゴリ(Yahoo!)
  91: define('LINE_COLOR',    '#FF0000');     // 恵方の色
  92: define('LINE_OPACITY',  0.6);           // 恵方の透明度
  93: define('LINE_WEIGHT',   5);             // 恵方の太さ
  94: define('LINE_LENGTH',   5000);          // 恵方の全長(メートル)
  95: define('ARROW_ANGLE',   20);            // 恵方:矢印の角度
  96: define('ARROW_LENGTH',  0.1);           // 恵方:矢の長さ(全長に対する比率)

地図や矢印の表示レイアウトを決めるための各種パラメータである。変更不可としているもの以外は、任意の値を設定できる。

解説:恵方の方位角を求める

pahooCalendar.php

1205: /**
1206:  * 指定した年の恵方の方位角(度)を求める.
1207:  * 参考サイト https://www.pahoo.org/e-soul/webtech/phpgd/phpgd-35-01.shtm
1208:  * @param   int $year 西暦年
1209:  * @return  float 恵方の方位角(北を0度として時計回り)
1210: */
1211: function eho($year) {
1212:     static $table = array(
1213:         255,        //庚年(西南西微西)
1214:         165,        //辛年(南南東微南)
1215:         345,        //壬年(北北西微北)
1216:         165,        //癸年(南南東微南)
1217:          75,        //甲年(東北東微東)
1218:         255,        //乙年(西南西微西)
1219:         165,        //丙年(南南東微南)
1220:         345,        //丁年(北北西微北)
1221:         165         //戊年(南南東微南)
1222:     );
1223:     $i = $year % 10;
1224: 
1225:     return $table[$i];
1226: }

恵方の方位角を求めるには、前述の「恵方とは」で紹介した一覧を配列として用意しておき、西暦年を10で割った剰余と紐付けてやる。

解説:地図上に矢印を描く

eho.php

 182: /**
 183:  * 地図上に矢印を描くスクリプトを生成
 184:  * @param   object $pgc       pahooGeoCodeクラス
 185:  * @param   float  $lat, $lng 開始点の緯度・経度
 186:  * @param   float  $angle     方位角(北を0度として時計回り)
 187:  * @param   int    $api   0:Google Maps JavaScript(省略時)
 188:  *                       11:地理院地図・OSM(Leaflet使用)
 189:  * @return  string JavaScript
 190: */
 191: function jsArrow($pgc, $latitude, $longitude, $angle, $api=0) {
 192:     // 本線
 193:     list($lat1, $lng1) = $pgc->getPointAngle($longitude, $latitude, $angle, LINE_LENGTH);
 194:     $points[0]['latitude']  = $latitude;
 195:     $points[0]['longitude'] = $longitude;
 196:     $points[1]['latitude']  = $lat1;
 197:     $points[1]['longitude'] = $lng1;
 198:     $js = $pgc->jsLine($points, LINE_COLOR, LINE_OPACITY, LINE_WEIGHT, MAPSERVICE);
 199: 
 200:     // 矢印
 201:     $a = $angle - 180 - ARROW_ANGLE;
 202:     if ($a < 0)      $a +360;
 203:     list($lat2, $lng2) = $pgc->getPointAngle($lng1, $lat1, $a, LINE_LENGTH * ARROW_LENGTH);
 204:     $points[0]['latitude']  = $lat1;
 205:     $points[0]['longitude'] = $lng1;
 206:     $points[1]['latitude']  = $lat2;
 207:     $points[1]['longitude'] = $lng2;
 208:     $js .$pgc->jsLine($points, LINE_COLOR, LINE_OPACITY, LINE_WEIGHT, MAPSERVICE);
 209: 
 210:     $a = $angle - 180 + ARROW_ANGLE;
 211:     if ($a < 0)      $a +360;
 212:     list($lat3, $lng3) = $pgc->getPointAngle($lng1, $lat1, $a, LINE_LENGTH * ARROW_LENGTH);
 213:     $points[1]['latitude']  = $lat3;
 214:     $points[1]['longitude'] = $lng3;
 215:     $js .$pgc->jsLine($points, LINE_COLOR, LINE_OPACITY, LINE_WEIGHT, MAPSERVICE);
 216: 
 217:     return $js;
 218: }

恵方の方角へ向かって、地図上に矢印を描く。
矢印を3本の直線に分解して描くことを考える。方位角を示す本線と、その終点にぶら下がる矢印(2本の短い線分)である。

本線は、eho 関数で得られた方位角へ向かって直線を描けばいい。始点と終点は緯度・経度で指定する必要があるので、始点から、方位角と距離を指定して終点を算出するユーザー関数 getPointAngle を用意した(後述)。

次に矢印部分であるが、これは、終点から見て、角度 +ARROW_ANGLE 方向、-ARROW_ANGLE 方向へ短い線分を描けばいい。線分の長さは、本線との比率 ARROW_LENGTH で計算している。

解説:方位角と距離を指定した地点の緯度・経度を求める

pahooGeoCode.php

 683: /**
 684:  * ある地点から方位角と距離を指定した地点の緯度・経度を求める
 685:  * @param   float $longitude 経度(世界測地系)
 686:  * @param   float $latitude  緯度(世界測地系)
 687:  * @param   float $angle     方位角(度)
 688:  * @param   float $distance  距離(メートル)
 689:  * @return  float array(緯度,経度)
 690: */
 691: function getPointAngle($longitude, $latitude, $angle, $distance) {
 692:     $rad = 6378137.0;           // 地球の半径(メートル)
 693:     $e2  = 6.69437999019758E-03;
 694: 
 695:     $wt  = sqrt(1.0 - $e2 * pow(sin($latitude * pi() / 180.0), 2));
 696:     $mt  = $rad * (1.0 - $e2) / pow($wt, 3);
 697:     $dit = $distance * cos($angle * pi() / 180.0) / $mt;
 698:     $i   = $latitude * pi() / 180.0 + $dit / 2;
 699:     $w   = sqrt(1.0 - $e2 * pow(sin($i), 2));
 700: 
 701:     // 緯度
 702:     $m   = $rad * (1 - $e2) / pow($w, 3);
 703:     $di  = $distance * cos($angle * pi() / 180) / $m;
 704:     $lat = $latitude + $di * 180 / pi();
 705: 
 706:     // 経度
 707:     $n   = $rad / $w;
 708:     $dk  = $distance * sin($angle * pi() / 180) / ($n * cos($i));
 709:     $lng = $longitude + $dk * 180 / pi();
 710: 
 711:     return array($lat, $lng);
 712: }

ある地点から方位角と距離を指定した地点の緯度・経度を求めるユーザー関数が getPointAngle である。球面三角法の方程式を解くことで計算している。

解説:Google JavaScriptマップ用スクリプト生成(直線描画)

pahooGeoCode.php

1141: /**
1142:  * 直線描画スクリプト:Googleマップ用
1143:  * @param   array  $points  直線の座標配列
1144:  *                      [$n]['longitude'] 経度(世界測地系)
1145:  *                      [$n]['latitude']  緯度(世界測地系)
1146:  * @param   string $color   描画色(省略時=#FF0000)
1147:  * @param   float  $opacity 透明度(省略時=1)
1148:  * @param   int    $weight  線の太さ(省略時=1)
1149:  * @return  string JavaScript
1150: */
1151: function jsLine_Gmap($points, $color='#FF0000', $opacity=1.0, $weight=1) {
1152:     $ss = '';
1153:     $cnt = 0;
1154:     foreach ($points as $pt) {
1155:         if ($cnt > 0)   $ss .",\n";
1156:         $ss ."\t\t{ lat: {$pt['latitude']}, lng: {$pt['longitude']} }";
1157:         $cnt++;
1158:     }
1159: 
1160:     $js =<<< EOT
1161:     new google.maps.Polyline({
1162:         map: map,
1163:         path: [ {$ss} ],
1164:         strokeColor: '{$color}',
1165:         strokeOpacity: {$opacity},
1166:         strokeWeight: {$weight}
1167:     }).setMap(map);
1168: 
1169: EOT;
1170:     return $js;
1171: }

Googleマップ上に直線(折れ線)を描くスクリプトを生成する。緯度・経度座標は配列で渡す。

解説:Leaflet用スクリプト生成(直線描画)

pahooGeoCode.php

2136: /**
2137:  * 直線描画スクリプト:Leaflet用
2138:  * @param   array  $points  直線の座標配列
2139:  *                      [$n]['longitude'] 経度(世界測地系)
2140:  *                      [$n]['latitude']  緯度(世界測地系)
2141:  * @param   string $color   描画色(省略時=#FF0000)
2142:  * @param   float  $opacity 透明度(省略時=1)
2143:  * @param   int    $weight  線の太さ(省略時=1)
2144:  * @return  string JavaScript
2145: */
2146: function jsLine_Leaflet($points, $color='#FF0000', $opacity='1.0', $weight=1) {
2147:     $ss = '';
2148:     $cnt = 0;
2149:     foreach ($points as $pt) {
2150:         if ($cnt > 0)   $ss .', ';
2151:         $ss ."[{$pt['latitude']}, {$pt['longitude']}]";
2152:         $cnt++;
2153:     }
2154: 
2155:     $js =<<< EOT
2156:     L.polyline(
2157:         [{$ss}], {
2158:         'color':  '{$color}',
2159:         'opacity': {$opacity},
2160:         'weight':  {$weight}
2161:     }).addTo(map);
2162: 
2163: EOT;
2164:     return $js;
2165: }

Googleマップ上に直線(折れ線)を描くスクリプトを生成する。緯度・経度座標は配列で渡す。

解説:マップ上に直線を描くスクリプト生成

pahooGeoCode.php

2560: /**
2561:  * マップ上に直線を描くスクリプト生成
2562:  * @param   array  $points  直線の座標配列
2563:  *                      [$n]['longitude'] 経度(世界測地系)
2564:  *                      [$n]['latitude']  緯度(世界測地系)
2565:  * @param   string $color   描画色(省略時=#FF0000)
2566:  * @param   float  $opacity 透明度(省略時=1)
2567:  * @param   int    $weight  線の太さ(省略時=1)
2568:  * @param   int    $api   0:Google Maps JavaScript(省略時)
2569:  *                        2:地理院地図・OSM(Leaflet使用)
2570:  * @return  string JavaScript
2571: */
2572: function jsLine($points, $color='#FF0000', $opacity='1.0', $weight=1, $api=0) {
2573:     switch ($api) {
2574:     // Google Maps JavaScript
2575:     case 0;
2576:         $js = $this->jsLine_Gmap($points, $color, $opacity, $weight, $api);
2577:         break;
2578:     // 地理院地図・OSM(Leaflet使用)
2579:     case 2:
2580:         $js = $this->jsLine_Leaflet($points, $color, $opacity, $weight, $api);
2581:         break;
2582:     }
2583: 
2584:     return $js;
2585: }

jsLine_Gmap または jsLine_Leaflet を呼び出し、マップ上に直線を描くスクリプトを生成する。緯度・経度座標は配列で渡す。
#jsLine_Leaflet:title=jsLine_Leaflet] で生成したスクリプトは、drawJSmap メソッドの引数 $call に渡してやる。

参考サイト

(この項おわり)
header