PHPで潮位を計算する

(1/1)
釣り人でなくても、潮干狩り鳴門の渦潮観光など、潮見表を見ること少なくない。台風による浸水被害を予測するときにも必要だ。
さて、「PHPで日出没・月出没・月齢・潮を計算」では潮の計算を行うプログラムを紹介したが、潮位を計算するには、はるかに複雑な計算を行う必要がある。幸い、コンピュータの計算能力が飛躍的に向上したおかげで、潮位の計算もストレスなく行えるようになった。

そこで、これまで作ってきた "pahooCalendar.php" に、あらた潮位計算クラス "pahooTide" を追加し、Googleマップに表示されている地点の近くの海岸において、指定日から1週間の毎日の満潮・干潮の時刻と潮位を一覧およびグラフ表示するサンプル・プログラムを作ってみることにする。

(2023年1月15日)計算精度向上,数値入力にpahooInputData導入

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

PHPで潮位を計算する
Googleマップ表示
PHPで潮位を計算する

目次

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

圧縮ファイルの内容
tide.phpサンプル・プログラム本体。
pahooCalendar.php暦・潮位計算クラス pahooCalendar。
暦・潮位計算クラスの使い方は「PHPで二十四節気・七十二候一覧を作成」「PHPで月齢を計算」「PHPで日出没・月出没・月齢・潮を計算」「PHPで潮位を計算する」などを参照。include_path が通ったディレクトリに配置すること。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
tideData.zip計算パラメータ。pahooTideが解凍せずに参照する圧縮ファイル。
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで住所・ランドマークから緯度・経度を求める」などを参照。include_path が通ったディレクトリに配置すること。
moon/moon_00.png~moon_30.png月齢画像。
makeTideDataFiles.phptideData.zip を自動生成する。
サンプル・プログラム実行時には不要。
table_C1C2.xlsx表-C.1, C.2の元データ。
サンプル・プログラム実行時には不要。
dispC1C2table.php表-C.1, C.2をTABLE表示する。
サンプル・プログラム実行時には不要。
tide.php 更新履歴
バージョン 更新日 内容
3.3.0 2022/07/09 数値入力にpahooInputData導入
3.21 2022/07/09 bug-fix
3.2 2022/06/04 PHP8対応,リファラ・チェック改良,計算パラメータ更新
3.11 2019/06/24 逆ジオコーディングサービスの選択肢を増やした
3.1 2019/06/24 地理院地図、OpenStreetMapも利用できるようにした
pahooCalendar.php 更新履歴
バージョン 更新日 内容
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() 表記改訂:水澤腹堅→水沢腹堅
4.3.1 2023/02/03 表記改訂:バクムーン→バックムーン,スタージャンムーン→スタージョンムーン,七十二候
pahooInputData.php 更新履歴
バージョン 更新日 内容
1.5.0 2024/01/28 exitIfExceedVersion() 追加
1.4.2 2024/01/28 exitIfLessVersion() メッセージ修正
1.4.1 2023/09/30 コメントの訂正
1.4.0 2023/09/09 $_GET, $_POST参照をfilter_input()関数に置換
1.3.0 2023/07/11 roundFloat() 追加
pahooGeoCode.php 更新履歴
バージョン 更新日 内容
6.3.3 2024/09/14 $this->NOMINATIM_EMAIL 追加
6.3.2 2024/02/14 getStaticMap() -- bug-fix
6.3.1 2023/07/09 bug-fix
6.3.0 2023/07/02 getPointsGSI()追加
6.2.0 2023/07/02 ip2address()追加

準備:初期値など

  43: //jqPlotのあるフォルダ
  44: define('JQPLOT', '../../../../common/jqplot/');
  45: 
  46: //月の満ち欠け画像ファイルの場所
  47: // 画像作成方法→https://www.pahoo.org/e-soul/webtech/phpgd/phpgd-17-01.shtm
  48: define('MOONAGE', './moon/');
  49: 
  50: //潮位表:計算期間(日)の初期値
  51: define('INTERVAL_DEF', 7);
  52: 
  53: //潮位グラフ:計算期間(日)の初期値
  54: define('INTERVAL_GRAPH_DEF', 5);
  55: 
  56: //潮位グラフのプロット間隔(日)
  57: define('INTERVAL_GRAPH', 0.02);
  58: 
  59: //潮位グラフの名前
  60: define('GRAPH_TIDE', 'jqPlot_tide');
  61: 
  62: //地図描画サービスの選択
  63: //    0:Google
  64: //    2:地理院地図・OSM
  65: define('MAPSERVICE', 0);
  66: 
  67: //住所検索サービスの選択
  68: //    0:Google
  69: //    1:Yahoo!JAPAN
  70: //   11:HeartRails Geo API
  71: define('GEOSERVICE', 1);
  72: 
  73: //逆ジオコーディングサービスの選択
  74: //    0:Google
  75: //    1:Yahoo!JAPAN
  76: //   11:HeartRails Geo API
  77: //   21:簡易ジオコーディングサービス
  78: define('REVGEOSERVICE', 21);
  79: 
  80: //指定できる西暦年の範囲
  81: define('MIN_YEAR', 1901);
  82: define('MAX_YEAR', 2099);
  83: 
  84: //表示言語(jp:日本語, en:英語, en3:英語略記)
  85: define('LANGUAGE', 'jp');
  86: 
  87: //世界時からの時差(日本標準時)
  88: define('UTCDIFF', +9.0);
  89: 
  90: //観測点のデフォルト値(東京駅)
  91: define('DEF_LOCATION', 'TK');   //東京
  92: define('DEF_LATITUDE',  35.681111);
  93: define('DEF_LONGITUDE', 139.766667);
  94: define('DEF_HEIGHT',    4.0);
  95: 
  96: //月齢計算時刻
  97: define('MOONAGE_HOUR', 21);
  98: 
  99: //マップID
 100: define('MAPID', 'map_id');
 101: //初期値
 102: define('MAP_WIDTH',     800);           //表示幅
 103: define('MAP_HEIGHT',    300);           //表示高
 104: define('DEF_TYPE',      'roadmap');     //デフォルトのマップタイプ
 105: define('DEF_ZOOM',      8);             //デフォルトの拡大率
 106: define('DEF_CAT',       'address');     //カテゴリ
 107: 
 108: //require_once()で呼ぶファイルはinclude_pathが通っているフォルダに配置すること.
 109: //暦計算クラス
 110: require_once('pahooCalendar.php');
 111: 
 112: //住所・緯度・経度に関わるクラス
 113: require_once('pahooGeoCode.php');
 114: 
 115: //データ入力に関わる関数群
 116: require_once('pahooInputData.php');

潮位、月齢、各種カレンダー計算は、ユーザークラス "pahooCalendar" および "pahooTide" を利用する。クラスファイル "pahooCalendar.php" をnclude_pathが通ったディレクトリに配置すること。
Googleマップの表示や住所検索には、ユーザークラス "pahooGeoCode" を利用する。クラスファイル "pahooGeoCode.php" をinclude_pathが通ったディレクトリに配置すること。
また、ユーザークラス "pahooTide" が参照するデータファイル "tideData.zip" はクラスファイルと同じディレクトリに配置すること。

準備:pahooGeoCode クラス

  37: class pahooGeoCode {
  38:     var $items;     //検索結果格納用
  39:     var $error;     //エラー・フラグ
  40:     var $errmsg;    //エラー・メッセージ
  41:     var $hits;      //検索ヒット件数
  42:     var $webapi;    //直前に呼び出したWebAPI URL
  43: 
  44:     //Google Cloud Platform APIキー
  45:     //https://cloud.google.com/maps-platform/
  46:     //※Google Maps APIを利用しないのなら登録不要
  47:     var $GOOGLE_API_KEY_1 = '**************************';   //HTTPリファラ用
  48:     var $GOOGLE_API_KEY_2 = '**************************';   //IP制限用
  49: 
  50:     //Yahoo! JAPAN Webサービス アプリケーションID
  51:     //https://e.developer.yahoo.co.jp/register
  52:     //※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  53:     var $YAHOO_APPLICATION_ID = '*****************************';

地図描画や住所検索を行うために、クラスファイル "pahooGeoCode.php" を使用する。組み込み関数  require_once  を使って読めるディレクトリに配置する。ディレクトリは、設定ファイル php.ini に記述されているオプション設定 include_path に設定しておく。
クラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

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

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

  48: //地図描画サービスの選択
  49: //    0:Google
  50: //    2:地理院地図・OSM
  51: define('MAPSERVICE', 2);
  52: 
  53: //住所検索サービスの選択
  54: //    0:Google
  55: //    1:Yahoo!JAPAN
  56: //   11:HeartRails Geo API
  57: //   12:OSM Nominatim Search API
  58: //   13:国土地理院ジオコーディングAPI
  59: define('GEOSERVICE', 12);
  60: 
  61: //逆ジオコーディングサービスの選択
  62: //    0:Google
  63: //    1:Yahoo!JAPAN
  64: //   11:HeartRails Geo API
  65: //   21:簡易ジオコーディングサービス
  66: define('REVGEOSERVICE', 21);

表示する地図は、Googleマップ地理院地図・オープンストリートマップ(OSM)から選べる。あらかじめ、定数 MAPSERVIC に値を設定すること。
住所検索サービスは、GoogleYahoo!JAPANHeartRails Geo APIOSM Nominatim Search API から選べる。あらかじめ、定数 GEOSERVICE に値を設定すること。
逆ジオコーディングサービスは、GoogleYahoo!JAPANHeartRails Geo API簡易ジオコーディングサービスから選べる。あらかじめ、定数 REVGEOSERVICE に値を設定すること。

全体の流れ

ここでは、『港湾空港技術研究所資料 No.1168』(2007年12月,独立行政法人 港湾空港技術研究所)の「付録C 潮汐の推算」を参考に、プログラムを作成していく。プログラムの動作確認にあたっては、気象庁の潮位表、および TIDE for WINを利用した。後者はVisual Basicのソースコードが公開されており、開発の参考になるだろう。

潮汐は複数の分潮の合成であり、下記の式で求めることができる。
\[ \displaystyle \eta\ =\ Z_0\ +\ \sum_{i=1}^{k}\ f_i\ H_i\ cos(V_i\ +\ u_i\ -\ k_i) \tag{C.1} \]
η潮位
Z0観測値の平均水面
fi分潮iの振幅に対する補正係数
Hi観測地において計算された振幅
Vi時間とともに変化する分潮引数
ui時間とともに変化する位相の補正係数
ti観測地において計算された位相遅れ
\( Z_0 \)、 \( H_i \)、 \( u_i \)は観測地に固有の値であり、後述するが、気象庁が公開している各観測地点における分潮一覧表から入手することができる。
ここからしばらくは、クラスファイル "pahooCalendar.php" にある潮位計算クラス "pahooTide" のコードと見比べながら計算原理を説明してゆく。

2779: // 潮位計算 ===============================================================
2780: // @参考URL https://www.pahoo.org/e-soul/webtech/php02/php02-51-01.shtm
2781: class pahooTide {
2782:     const FILE_ZIPNAME = 'tideData.zip';    //計算用パラメータ格納ZIPファイル
2783:     const FILE_C1      = '_C1.txt';         //表-C.1
2784:     const FILE_C2      = '_C2.txt';         //表-C.2
2785:     const FILE_INDEX   = '_index.txt';      //地点一覧
2786:     const FILE_EXT     = '.txt';            //拡張子
2787:     const JST          = -9;                //日本時の時差
2788:     const COMMENT = '#';                    //コメント文字
2789:     var $error, $errmsg;                    //エラーフラグ,エラーメッセージ
2790:     var $_s, $_h, $_p, $_N;                 //天文引数
2791: 
2792:     var $c1, $c2;                           //表-C.1, C.2
2793:     var $index;                             //地点一覧
2794:     var $port;                              //ある地点の分潮一覧表
2795: 
2796: //分潮記号
2797: var $keys = array('Sa', 'Ssa', 'Mm', 'MSf', 'Mf', '2Q1', 'σ1', 'Q1', 'ρ1', 'O1', 'MP1', 'M1', 'χ1', 'π1', 'P1', 'S1', 'K1', 'ψ1', 'φ1', 'θ1', 'J1', 'SO1', 'OO1', 'OQ2', 'MNS2', '2N2', 'μ2', 'N2', 'ν2', 'OP2', 'M2', 'MKS2', 'λ2', 'L2', 'T2', 'S2', 'R2', 'K2', 'MSN2', 'KJ2', '2SM2', 'MO3', 'M3', 'SO3', 'MK3', 'SK3', 'MN4', 'M4', 'SN4', 'MS4', 'MK4', 'S4', 'SK4', '2MN6', 'M6', 'MSN6', '2MS6', '2MK6', '2SM6', 'MSK6');

潮汐と分潮

潮汐は、月と太陽の引力によって起きるわけだが、地球や月の公転軌道が真円ではないため、潮汐力は単純な振動方程式にならない。そこで、複数の正弦周期(サインカーブ)の和によって潮汐力の周期変動を表すことが行われている。
1つ1つの周期を分潮 (ぶんちょう) と呼び、60種類が定義されている。このうち影響の大きい下記の4つを、主要4分潮を呼ぶ。
M2月の引力によるもので、周期は約12時間25分。
S2太陽の引力によるもので、周期は約12時間。
O1月の引力によるもので、周期は約25時間49分。
K1観月と太陽の合成引力によるもので、周期は約23時間56分。

天文引数の計算

まず、周期計算のベースになる天文引数を求める。
\[
\begin{eqnarray}
s &=& 211.728\ +\ 129.38471\ y\ +\ 13.176396\ d \tag{C.2} \\
h &=& 279.974\ -\ 0.23871\ y\ +\ 0.985647\ d \tag{C.3} \\
p &=& 83.298\ +\ 40.66229\ y\ +\ 0.111404\ d \tag{C.4} \\
N &=& 125.071\ -\ 19.32812\ y\ -\ 0.052954\ d \tag{C.5} \\
y &=& Y\ -\ 2000 \tag{C.6} \\
d &=& D\ +\ L \tag{C.7}
\end{eqnarray}
\]
Y西暦
Dその年の1月1日からの経過日数
L西暦2000年からその年の年初までの閏日の数
\[
\displaystyle
L\ =\ \bigg\{ \frac{(Y\ +\ 3)}{4}\ \bigg\} -\ 500
\]
{ }は中の数値を整数に丸めることを意味する。Lは2000年以前では負数とする。

2882: /**
2883:  * 指定した年月日から天文引数を求める.
2884:  * @param   int $year, $month, $day  グレゴリオ暦による年月日
2885:  * @return  なし
2886: */
2887: function sun_moon($year, $month, $day) {
2888:     $y = (float)$year - 2000.0;
2889:     $L = (float)floor(($year + 3.0) / 4.0- 500.0;
2890:     $d = (float)date('z', mktime(0, 0, 0, $month, $day, $year)) + $L;
2891: 
2892:     $this->_s = (float)211.728 + 129.38471 * $y + 13.176396 * $d;
2893:     $this->_h = (float)279.974 -   0.23871 * $y +  0.985647 * $d;
2894:     $this->_p = (float83.298 +  40.66229 * $y +  0.111404 * $d;
2895:     $this->_N = (float)125.071 -  19.32812 * $y -  0.052954 * $d;
2896: 
2897:     $this->_s = $this->_stdegree($this->_s);
2898:     $this->_h = $this->_stdegree($this->_h);
2899:     $this->_p = $this->_stdegree($this->_p);
2900:     $this->_N = $this->_stdegree($this->_N);
2901: }

分潮引数 Vi の計算

(C.1)式の \( V_i\ +\ u_i \) は次のように表せる。
\[ \displaystyle V_i\ +\ u_i\ =\ V_{0i}\ +\ u_i\ +\ nLat\ +\ \sigma _i(t_l\ +\ t_s) \tag{C.9} \]
V0i世界時0時における分潮引数 \( V_i \)
σi分潮iの角速度で、後述する表-C.2から取得する。
n1日周期は1、半日周期は2、1/4周期は4‥‥となる定数で、後述する表-C.2から取得する。
tlローカル時間(時)。
ts世界時との時差(時)。日本標準時の場合は -9。
Lat観測地点の経度。東経はプラス、西経はマイナス。

基準となる \( V_{0i} \) は次のようにして計算できる。
\[ V_{0i}\ =\ a_ss\ +\ a_hh\ +\ a_pp\ +\ c \tag{C.10} \]
\( a_s \)、 \( a_h \)、 \( a_p \)、 \( c \) は、後述する表-C.2から取得できる。

補正係数 fi、ui の計算

分潮によって \( f_i \)、 \( u_i \) の計算方法は3種類に分かれる。

1)L2、M1分潮
\[
\displaystyle
\begin{eqnarray}
(f\ cos\ u)(L_2) &=& 1 - 0.2505\ cos\ 2p - 0.1102\ cos(2p-N) - 0.0156\ cos(2p-2N)-0.0370\ cosN \tag{C.17} \\
(f sin\ u)(L_2) &=& - 0.2505\ sin\ 2p - 0.1102\ sin(2p-N) - 0.0156\ sin(2p-2N)-0.0370\ sinN \tag{C.18} \\
(f\ cos\ u)(M_1) &=& 2\ cos\ p + 0.4\ cos(p-N) \tag{C.19} \\
(f\ sin\ u)(M_1) &=& sin\ p + 0.2\ cos(p-N) \tag{C.20} \\
f_i &=& \sqrt{(f cos\ u)_{2}^{i} + (f\ sin\ u)_{2}^{i}} \tag{C.21} \\
u_i &=& tan^{-1}\frac{(f\ sin\ u)_i}{(f\ cos\ u)_i} \tag{C.22}
\end{eqnarray}
\]

2903: /**
2904:  * L2, M1分潮のfi, uiを求める.
2905:  * @param   string $i  分潮記号 'L2' または 'M1'
2906:  * @param   string $fn 'fi' または 'ui'
2907:  * @return  float 計算結果
2908: */
2909: function fiui_L2M1($i, $fn) {
2910:     //L2
2911:     if ($i == 'L2') {
2912:         $fcosu = (float)1 - 0.2505 * cos(deg2rad(2 * $this->_p))
2913:                 - 0.1102 * cos(deg2rad(2 * $this->_p - $this->_N))
2914:                 - 0.0156 * cos(deg2rad(2 * $this->_p - 2 * $this->_N))
2915:                 - 0.0370 * cos(deg2rad($this->_N));
2916:         $fsinu = (float)-0.2505 * sin(deg2rad(2 * $this->_p))
2917:                 - 0.1102 * sin(deg2rad(2 * $this->_p - $this->_N))
2918:                 - 0.0156 * sin(deg2rad(2 * $this->_p - 2 * $this->_N))
2919:                 - 0.0370 * sin(deg2rad($this->_N));
2920:     //M1
2921:     } else {
2922:         $fcosu = (float)2 * cos(deg2rad($this->_p))
2923:                 + 0.4 * cos(deg2rad($this->_p - $this->_N));
2924:         $fsinu = (float)sin(deg2rad($this->_p))
2925:                  + 0.2 * sin(deg2rad($this->_p - $this->_N));
2926:     }
2927: 
2928:     //fi
2929:     if ($fn == 'fi') {
2930:         $res = (float)sqrt($fcosu * $fcosu + $fsinu * $fsinu);
2931:     //ui
2932:     } else {
2933:         $res = (float)atan($fcosu / $fsinu);
2934:     }
2935: 
2936:     return $res;
2937: }

2)表-C.1の8分潮
\[
\displaystyle
\begin{eqnarray}
f_i &=& b_{i0} + b_{i1}cosN + b_{i2}\ cos2N\ + b_{i3}cos\ 3N \tag{C.11} \\
u_i &=& c_{i1}\ sinN\ +\ c_{i2}\ sin2N\ +\ c_{i3}\ sin3N \tag{C.12}
\end{eqnarray}
\]
3)1,2以外の分潮
表-C.2の列に記載した計算式によって求める。

2939: /**
2940:  * fi, uiを求める.
2941:  * @param   string $i  分潮記号
2942:  * @param   string $fn 'fi' または 'ui'
2943:  * @return  float 計算結果
2944: */
2945: function fiui($i, $fn) {
2946:     //L2 or M1
2947:     if (($i == 'L2'|| ($i == 'M1')) {
2948:         $res = (float)$this->fiui_L2M1($i, $fn);
2949: 
2950:     //fi
2951:     } else if ($fn == 'fi') {
2952:         //表-C.1による計算
2953:         if (isset($this->c1[$i])) {
2954:             $res = (float)$this->c1[$i][0]
2955:             + (float)$this->c1[$i][1* cos(deg2rad($this->_N))
2956:             + (float)$this->c1[$i][2* cos(2 * deg2rad($this->_N))
2957:             + (float)$this->c1[$i][3* cos(3 * deg2rad($this->_N));
2958:         //表-C.2の参照
2959:         } else {
2960:             $res = $this->c2[$i][5];
2961:             if (! is_numeric($res)) $res = (float)$this->fiui($res, $fn);
2962:         }
2963:     //ui
2964:     } else {
2965:         //表-C.1による計算
2966:         if (isset($this->c1[$i])) {
2967:             $res = (float)$this->c1[$i][4* sin(deg2rad($this->_N))
2968:             + (float)$this->c1[$i][5* sin(2 * deg2rad($this->_N))
2969:             + (float)$this->c1[$i][6* sin(3 * deg2rad($this->_N));
2970:         //表-C.2の参照
2971:         } else {
2972:             $res = (float)$this->c2[$i][6];
2973:             if (! is_numeric($res)) $res = (float)$this->fiui($res, $fn);
2974:         }
2975:     }
2976:     return $res;
2977: }

文字列として取得した計算式を評価し、結果の数値を出力するメソッド evalFiUi を用意した。

表-C.1、表-C.2

ダウンロードしたファイルを解凍して得られる "table_C1C2.xlsx" を元データとして、列区切りをタブ、行区切りを改行としたテキストファイル "_C1.txt" および "_C2.txt" をZIP圧縮ファイルに格納している。

2848: /**
2849:  * 表から配列へパラメータを格納する.
2850:  * @param   string $str パラメータ表
2851:  * @param   array  $arr パラメータを格納する配列
2852:  * @return  なし
2853: */
2854: function str2array($str, &$arr) {
2855:     $tok = strtok($str, "\n");
2856:     while ($tok !FALSE) {
2857:         $ss = trim($tok);
2858:         if ($ss == "")      continue;
2859:         $cols = preg_split("/\t/iu", $ss);
2860:         $key = trim($cols[0]);
2861:         if (mb_substr($key, 0, 1!self::COMMENT) {
2862:             for ($i = 1$i < count($cols); $i++) {
2863:                 if (mb_substr($cols[$i], 0, 1) == self::COMMENT)    break;      //コメントから行末まで無視
2864:                 $arr[$key][$i - 1] = trim($cols[$i]);
2865:             }
2866:         }
2867:         $tok = strtok("\n");
2868:     }
2869: }

PHPプログラムでは、ZIP圧縮ファイルからテキストを読み込み、計算しやすいように配列に格納する。
表-C.1 fi, Uiの係数
[海上保安庁(1992)]
分潮記号fiui
1cos Ncos 2Ncos 3Nsin Nsin 2Nsin 3N
Mm1.0000-0.13000.00130.00000.000.000.00
Mf1.04290.4135-0.00400.0000-23.742.68-0.38
O11.00890.1871-0.01470.001410.80-1.340.19
K11.00600.1150-0.00880.0006-8.860.68-0.07
J11.01290.1676-0.01700.0016-12.941.34-0.19
OO11.10270.65040.0317-0.0014-36.684.02-0.57
M21.0004-0.03730.00020.0000-2.140.000.00
K21.02410.28630.0083-0.0015-17.740.68-0.04
表-C.2 各分潮の補正係数、角速度など
[海上保安庁(1992),気象庁(1999)]
分潮記号shpcnfiuiσ
(deg/hour)
period
(hour)
Sa01000100.04106868765.8211
Ssa02000100.08213734382.9052
Mm10-100MmMm0.5443747661.3092
MSf2-2000M2-M21.0158958354.3671
Mf20000MfMf1.0980331327.8590
2Q1-4122701O1O112.854286228.0062
σ1-4302701O1O112.927139827.8484
Q1-3112701O1O112.398660926.8684
ρ1-33-12701O1O113.471514526.7231
O1-2102701O1O113.943035625.8193
MP1-230901M2M214.025172925.6681
M1-110901M1M114.492052124.8412
χ1-13-1901J1J114.569547624.7091
π10-2019311014.917864724.1321
P10-1027011014.958931424.0659
S100018011015.000000024.0000
K1010901K1K115.041068623.9345
ψ102016711015.082135323.8693
φ10309011015.123205923.8045
θ11-11901J1J115.512589723.2070
J111-1901J1J115.585443323.0985
SO12-10901J1J116.056964422.4202
OO1210901OO1OO116.139101722.3061
OQ2-5211802O1*Q1O1+Q127.341696413.1667
MNS2-54102M2^22*M227.423833713.1273
2N2-42202M2M227.895354812.9054
μ2-44002M2M227.968208412.8718
N2-32102M2M228.439729512.6583
ν2-34-102M2M228.512583112.6260
OP2-2001802O1*P1O1+P128.901966912.4559
M2-22002M2M228.984104212.4206
MKS2-24002M2*K2M2+K229.066241512.3855
λ2-1011802M2M229.455625312.2218
L2-12-11802L2L229.528478912.1916
T20-1028321029.958933312.0164
S2000021030.000000012.0000
R201025721030.041066711.9836
K202002K2K230.082137311.9672
MSN210-102M2^22*M230.544374711.7861
KJ212-11802K1*J1K1+J130.626512011.7545
2SM22-2002M2-M231.015895811.6070
MO3-4302703M2*O1M2+O142.92713988.3863
M3-3301803M2^1.51.5*M243.47615638.2804
SO3-2102703O1O143.94303568.1924
MK3-230903M2*K1M2+K144.02517298.1771
SK3010903K1K145.04106867.9927
MN4-54104M2^22*M257.42383376.2692
M4-44004M2^22*M257.96820846.2103
SN4-32104M2M258.43972956.1602
MS4-22004M2M258.98410426.1033
MK4-24004M2*K2M2+K259.06624156.0949
S4000041060.00000006.0000
SK402004K2K260.08213735.9918
2MN6-76106M2^33*M286.40793804.1663
M6-66006M2^33*M286.95231274.1402
MSN6-54106M2^22*M287.42383374.1179
2MS6-44006M2^22*M287.96820844.0924
2MK6-46006M2^2*K22*M2+K288.05034574.0886
2SM6-22006M2M288.98410424.0457
MSK6-24006M2*K2M2+K289.06624154.0419

Zi、Hi、ui の入手

前述の通り、 \( Z_o \)、 \( H_i \)、 \( u_i \) は観測地点の固有の値である。
これらの値は、気象庁の潮位表掲載地点一覧表から取得することができる。対象は、一覧表のうち、分潮一覧表の列のリンク先にコンテンツがあるもののみである。

これらのコンテンツを自動的に読み込んでゆき、各地点の分潮一覧表をZIP圧縮ファイルに格納していくプログラムが "makeTideDataFiles.php" である。

ある日の干潮、満潮時刻と潮位を求める

pahooTide::tide_level を繰り返すことで、指定地点のある日の干潮、満潮時刻と潮位を求めることができる。
干潮、満潮は、1日に各々最大4回起きる。1分ごとに潮位を計算し、上昇から下降へ転じる点が満潮時刻、その逆が干潮時刻である。だが、1分ごとに計算すると、1日で 60×24=1440回も計算しなければならない。
計算回数を減らすために、まず15分ごとに計算することで変化点を検出し、そこから±15分間を1分ごとに計算することで正確な時刻を求める。計算回数は、1日で4×24+15×8
=216回に減らすことができる。

3096: /**
3097:  * 指定地点のある日の干潮,満潮時刻と潮位を求める.
3098:  * @param   string $code 地点記号
3099:  * @param   int $year, $month, $day グレゴリオ暦による年月日
3100:  * @param   array $items 結果を格納する配列
3101:  *              array('high'=>array('hh:mm',潮位), 'low'=>array('hh:mm',潮位))
3102:  * @return  TRUE/FALSE
3103: */
3104: function tide_day($code, $year, $month, $day, &$items) {
3105:     $this->setLocation($code);
3106:     if ($this->error)   return FALSE;
3107: 
3108:     $this->sun_moon($year, $month, $day);
3109: 
3110:     $interval = 15.0;           //第1段階刻み(分)
3111:     $td0 = $this->tide_level($year, $month, $day, self::JST, -$interval);
3112:     $flag = 0;
3113:     $cnt_high = 0;
3114:     $cnt_low = 0;
3115:     for ($i = 0$i <24 * 60$i +$interval) {
3116:         //第1段階刻み
3117:         $hh = floor($i / 60.0);
3118:         $mm = $i - $hh * 60.0;
3119:         $td1 = $this->tide_level($year, $month, $day, $hh + self::JST, $mm);
3120:         if ($flag == 0) {
3121:             if ($td1 > $td0)    $flag = +1;     //上昇
3122:             else                $flag = -1;     //下降
3123:         } else if ($flag < 0) {
3124:             if ($td1 > $td0) {                      //上昇へ転じた
3125:                 //第2段階刻み
3126:                 $td0 = $this->tide_level($year, $month, $day, $hh + self::JST, $mm - $interval - 1);
3127:                 for ($j = -$interval$j < $interval$j++) {
3128:                     $hh = floor(($i + $j) / 60.0);
3129:                     $mm = ($i + $j- $hh * 60.0;
3130:                     $td1 = $this->tide_level($year, $month, $day, $hh + self::JST, $mm);
3131:                     if ($td1 > $td0) {              //上昇へ転じた
3132:                         $items['low'][$cnt_low]['hhmm'] = sprintf("%02d:%02d", $hh, $mm);
3133:                         $items['low'][$cnt_low]['lev'] = (int)$td0;
3134:                         $cnt_low++;
3135:                         $flag = +1;
3136:                         break;
3137:                     }
3138:                     $td0 = $td1;
3139:                 }
3140:             }
3141:         } else {
3142:             if ($td1 < $td0) {                       //下降へ転じた
3143:                 //第2段階刻み
3144:                 $td0 = $this->tide_level($year, $month, $day, self::JST, $mm - $interval - 1);
3145:                 for ($j = -$interval$j < $interval$j++) {
3146:                     $hh = floor(($i + $j) / 60.0);
3147:                     $mm = ($i + $j- $hh * 60.0;
3148:                     $td1 = $this->tide_level($year, $month, $day, $hh + self::JST, $mm);
3149:                     if ($td1 < $td0) {               //下降へ転じた
3150:                         $items['high'][$cnt_high]['hhmm'] = sprintf("%02d:%02d", $hh, $mm);
3151:                         $items['high'][$cnt_high]['lev'] = (int)$td0;
3152:                         $cnt_high++;
3153:                         $flag = -1;
3154:                         break;
3155:                     }
3156:                     $td0 = $td1;
3157:                 }
3158:             }
3159:         }
3160:         $td0 = $td1;
3161:     }
3162:     return TRUE;
3163: }

解説:各種定数

ここからは、サンプル・プログラム本体 "tide.php" の解説をしてゆく。

  43: //jqPlotのあるフォルダ
  44: define('JQPLOT', '../../../../common/jqplot/');
  45: 
  46: //月の満ち欠け画像ファイルの場所
  47: // 画像作成方法→https://www.pahoo.org/e-soul/webtech/phpgd/phpgd-17-01.shtm
  48: define('MOONAGE', './moon/');
  49: 
  50: //潮位表:計算期間(日)の初期値
  51: define('INTERVAL_DEF', 7);
  52: 
  53: //潮位グラフ:計算期間(日)の初期値
  54: define('INTERVAL_GRAPH_DEF', 5);
  55: 
  56: //潮位グラフのプロット間隔(日)
  57: define('INTERVAL_GRAPH', 0.02);
  58: 
  59: //潮位グラフの名前
  60: define('GRAPH_TIDE', 'jqPlot_tide');

これらの定数は自由に変更できる。
ただし、冒頭に述べたとおり計算量が大きいので、INTERVAL_DEFINTERVAL_GRAPH_DEF は、あまり大きな値にしない方がいいだろう。

潮位グラフを描くために、jQueryプラグイン「jqPlot」を利用する。使い方については、「PHPでNHK政治意識月例調査をグラフ表示」を参照のこと。定数 JQPLOT の示すディレクトリに配置する。
また、月齢を示す月の画像は、定数 MOONAGE の示すディレクトリに配置する。圧縮ファイルに含まれている画像は、「PHPで月の満ち欠けを描画」で作成したモノだ。

解説:地点セレクタ

 362: /**
 363:  * 地点セレクタを作成する.
 364:  * @param   pahooTide $pt  潮位計算クラス
 365:  * @param   string $code 地点記号
 366:  * @param   string $errmsg エラーメッセージ格納用;エラーなければ空文字
 367:  * @return  string HTML/FALSE:失敗
 368: */
 369: function makeJSlocation($pt, $code) {
 370:     static $prefs = array(
 371: '--選択--','北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県', 
 372: '茨城県', '栃木県', '群馬県', '埼玉県', '千葉県', '東京都', '神奈川県', 
 373: '新潟県', '富山県', '石川県', '福井県', '山梨県', '長野県', '岐阜県', '静岡県', 
 374: '愛知県', '三重県', '滋賀県', '京都府', '大阪府', '兵庫県', '奈良県',
 375: '和歌山県', '鳥取県', '島根県', '岡山県', '広島県', '山口県', '徳島県',
 376: '香川県', '愛媛県', '高知県', '福岡県', '佐賀県', '長崎県', '熊本県', '大分県', 
 377: '宮崎県', '鹿児島県', '沖縄県');
 378: 
 379:     if ($code == '') {
 380:         $pp = '';
 381:     } else if (! isset($pt->index[$code])) {
 382:         $errmsg = "not exist location '{$code}'";
 383:         return FALSE;
 384:     } else {
 385:         $pp = $pt->index[$code][4];
 386:     }
 387: 
 388:     //都道府県
 389:     $js = "var pref = [\n";
 390:     foreach ($prefs as $key=>$val) {
 391:         $selected = ($val == $pp? 'selected' : '';
 392:         $js ."{'type':{$key}, 'text':'{$val}', 'value':'{$val}', 'selected':'{$selected}'},\n";
 393:     }
 394:     //地点
 395:     $js ."];\nvar loc = [\n";
 396:     foreach ($prefs as $key=>$val) {
 397:         $js ."{'type':{$key}, 'text':'--選択--', 'value':''},\n";
 398:         foreach ($pt->index as $cd=>$arr) {
 399:             if ($arr[4] == $val) {
 400:                 $selected = ($cd == $code? 'selected' : '';
 401:                 $js ."{'type':{$key}, 'text':'{$arr[0]}', 'value':'{$cd}', 'selected':'{$selected}'},\n";
 402:             }
 403:         }
 404:     }
 405: 
 406:     //スクリプト
 407:     $js .=<<< EOT
 408: ];
 409: 
 410: $(function() {
 411:     var html = '';
 412:     for (var i in pref) {
 413:         html += '<option value="'+ pref[i].value + '" ' + pref[i].selected + '>'+ pref[i].text +'</option>';
 414:     }
 415:     $('#pref').append(html);
 416: 
 417:     var html = '';
 418:     var index = $('#pref option:selected').index();
 419:     for (var i in loc) {
 420:         if (loc[i].type == index) {
 421:             html += '<option value="'+ loc[i].value + '" ' + loc[i].selected + '>' + loc[i].text +'</option>';
 422:         }
 423:     }
 424:     $('#code').append(html);
 425: 
 426:     //都道府県を選択した時の挙動
 427:     $('#pref').change(function() {
 428:         var html = '';
 429:         var index = $('#pref option:selected').index();
 430:         //地点の内容を削除
 431:         $('#code').empty();
 432:         //対応する地点の内容を表示
 433:         for (var i in loc) {
 434:             if (loc[i].type == index) {
 435:                 html += '<option value="'+ loc[i].value +'">'+ loc[i].text +'</option>';
 436:             }
 437:         }
 438:         $('#code').append(html);
 439:     });
 440: });
 441: 
 442: EOT;
 443:     return $js;
 444: }

観測地点は、都道府県のセレクタと、観測地点のセレクタによって選択する。
観測地点セレクタを都道府県セレクタに連動させるために、jQuery を利用した。

解説:潮位表の計算と作成

 447: /**
 448:  * 潮位表:潮位・月齢を計算し,配列へ格納する.
 449:  * @param   pahooTide $pt  潮位計算クラス
 450:  * @param   pahooCalendar $pc  暦計算クラス
 451:  * @param   array  $inputs 計算用パラメータ
 452:  * @param   array  $items  計算結果格納用配列
 453:  * @param   array  $locs   地点情報格納用配列
 454:  * @param   string $errmsg エラーメッセージ格納用;エラーなければ空文字
 455:  * @return  bool TRUE:計算成功/FALSE:失敗
 456: */
 457: function calcTideTable($pt, $pc, $params, &$items, &$locs, &$errmsg) {
 458:     //地点を設定
 459:     $pt->setLocation($params['code']);
 460:     if ($pt->iserror()) return FALSE;
 461: 
 462:     //地点を取得
 463:     $pt->getLocation($params['code'], $locs);
 464:     if ($pt->iserror()) return FALSE;
 465: 
 466:     //月齢・潮位を計算
 467:     $res = TRUE;
 468:     $jd = $pc->Gregorian2JD($params['year'], $params['month'], $params['day'], 0, 0, 0);
 469:     for ($i = 0$i < $params['interval']; $i++) {
 470:         $arr = array();
 471:         list($year, $month, $day, $hour, $min, $sec) = $pc->JD2Gregorian($jd);
 472:         $yb = $pc->getWeekString($year, $month, $day);
 473:         $items[$i]['dt'] = sprintf("%04d-%02d-%02d(%s)", $year, $month, $day, $yb);
 474:         $items[$i]['moonage'] = $pc->moon_age($year, $month, $day, MOONAGE_HOUR, 0, 0);
 475:         $moonmeridian = $pc->moon_time(2, $params['longitude'], $params['latitude'], $params['height'], $year, $month, $day);
 476:         $moonmeridian = ($moonmeridian == FALSE? '---' : $pc->day2hhmm($moonmeridian);
 477:         $items[$i]['tide'] = (preg_match('/([0-9]+)\:([0-9]+)/', $moonmeridian, $arr> 0? $pc->tide($year, $month, $day, $arr[1], $arr[2], 0: '';
 478:         unset($arr);
 479: 
 480:         $arr = array();
 481:         $pt->tide_day($params['code'], $year, $month, $day, $arr);
 482:         //満潮
 483:         for ($j = 0$j < 4$j++) {
 484:             if (isset($arr['high'][$j])) {
 485:                 $items[$i]['high'][$j]['hhmm']  = $arr['high'][$j]['hhmm'];
 486:                 $items[$i]['high'][$j]['lev']   = sprintf("%d", $arr['high'][$j]['lev']);
 487:                 $items[$i]['high'][$j]['align'] = 'text-align:right;';
 488:             } else {
 489:                 $items[$i]['high'][$j]['hhmm']  = '*';
 490:                 $items[$i]['high'][$j]['lev']   = '*';
 491:                 $items[$i]['high'][$j]['align'] = 'text-align:center;';
 492:             }
 493:         }
 494:         //干潮
 495:         for ($j = 0$j < 4$j++) {
 496:             if (isset($arr['low'][$j])) {
 497:                 $items[$i]['low'][$j]['hhmm']  = $arr['low'][$j]['hhmm'];
 498:                 $items[$i]['low'][$j]['lev']   = sprintf("%d", $arr['low'][$j]['lev']);
 499:                 $items[$i]['low'][$j]['align'] = 'text-align:right;';
 500:             } else {
 501:                 $items[$i]['low'][$j]['hhmm']  = '*';
 502:                 $items[$i]['low'][$j]['lev']   = '*';
 503:                 $items[$i]['low'][$j]['align'] = 'text-align:center;';
 504:             }
 505:         }
 506:         $jd++;
 507:     }
 508: 
 509:     return $res;
 510: }

計算開始年月日と期間を指定して、tide::tide_day を繰り返し実行して満潮・干潮を計算してゆくのがユーザー関数 calcTideTable である。入力パラメータが多いので、配列で渡す。
月齢・潮の計算は、「PHPで日出没・月出没・月齢・潮を計算」で紹介したとおりである。

 512: /**
 513:  * 潮位表:表示用HTMLを作成する.
 514:  * @param   pahooTide     $pt      潮位計算クラス
 515:  * @param   pahooCalendar $pc      暦計算クラス
 516:  * @param   array         $params  計算用パラメータ
 517:  * @param   string        $js      スクリプト格納用
 518:  * @param   string        $html    HTML格納用
 519:  * @param   string        $errmsg  エラーメッセージ格納用
 520:  * @return  bool TRUE:成功/FALSE:失敗
 521:  * @return  表示用HTML
 522: */
 523: function makeTable($pt, $pc, $params, &$js, &$html, &$errmsg) {
 524:     $js = $html = '';
 525:     $items = array();
 526:     $locs  = array();
 527:     if (calcTideTable($pt, $pc, $params, $items, $locs, $errmsg) == FALSE)  return FALSE;
 528: 
 529:     $hour = MOONAGE_HOUR;
 530:     $html =<<< EOT
 531: <table class="tide">
 532: <caption>{$locs['title']}({$locs['prefecture']}{$locs['address']})</caption>
 533: <tr><th rowspan="2">年月日</th><th rowspan="2">月齢<br /><span style="font-size:small; font-weight:normal;">{$hour}時</span></th><th rowspan="2">潮</th><th colspan="8">満潮</th><th colspan="8">干潮</th></tr>
 534: 
 535: EOT;
 536:     $html ."<tr>";
 537:     for ($j = 0$j < 8$j++) {
 538:         $html ."<th class=\"index\">時刻</th><th class=\"index\">潮位<br />(cm)</th>";
 539:     }
 540:     $html ."</tr>\n";
 541:     foreach ($items as $item) {
 542:         $html .sprintf("<tr><td>%s</td><td>%.1f</td><td>%s</td>", $item['dt'], $item['moonage'], $item['tide']);
 543:         for ($j = 0$j < 4$j++) {
 544:             $html .sprintf("<td>%s</td><td style=\"%s\">%s</td>", $item['high'][$j]['hhmm'], $item['high'][$j]['align'], $item['high'][$j]['lev']);
 545:         }
 546:         for ($j = 0$j < 4$j++) {
 547:             $html .sprintf("<td>%s</td><td style=\"%s\">%s</td>", $item['low'][$j]['hhmm'], $item['low'][$j]['align'], $item['low'][$j]['lev']);
 548:         }
 549:         $html ."</tr>\n";
 550:     }
 551:     $html ."</table>\n";
 552: 
 553:     return TRUE;
 554: }

calcTideTable を呼び出し、ブラウザ上に潮位表を表示するためのユーザー関数が makeTable である。

解説:潮位グラフの計算と作成

 556: /**
 557:  * 潮位グラフ:潮位・月齢を計算し,配列に格納する.
 558:  * @param   pahooTide $pt  潮位計算クラス
 559:  * @param   pahooCalendar $pc  暦計算クラス
 560:  * @param   array  $params 計算用パラメータ
 561:  * @param   array  $items  潮位計算結果格納用配列
 562:  * @param   array  $moons  月齢計算結果格納用配列
 563:  * @param   array  $locs   地点情報格納用配列
 564:  * @param   string $errmsg エラーメッセージ格納用;エラーなければ空文字
 565:  * @return  bool TRUE:計算成功/FALSE:失敗
 566: */
 567: function calcTideGraph($pt, $pc, $params, &$items, &$moons, &$locs, &$errmsg) {
 568:     //地点を設定
 569:     $pt->setLocation($params['code']);
 570:     if ($pt->iserror()) return FALSE;
 571: 
 572:     //地点を取得
 573:     $pt->getLocation($params['code'], $locs);
 574:     if ($pt->iserror()) return FALSE;
 575: 
 576:     $res = TRUE;
 577: 
 578:     //潮位を計算
 579:     $jd = $pc->Gregorian2JD($params['year'], $params['month'], $params['day'], 0, 0);
 580:     $n = $params['interval'] / INTERVAL_GRAPH;
 581:     for ($i = 0$i < $n$i++) {
 582:         list($year, $month, $day, $hour, $min, $sec) = $pc->JD2Gregorian($jd);
 583:         $items[$i]['dt'] = sprintf("%04d/%02d/%02d %02d:%02d", $year, $month, $day, $hour, $min);
 584:         list($year, $month, $day, $hour, $min, $sec) = $pc->JD2Gregorian($jd);
 585:         $pt->sun_moon($year, $month, $day);
 586:         $items[$i]['tlevel'] = $pt->tide_level($year, $month, $day, $hour, $min);
 587:         $jd +INTERVAL_GRAPH;
 588:     }
 589: 
 590:     //月齢を計算
 591:     $height = 0;        //標高0メートルを仮定
 592:     $n = $params['interval'];
 593:     $jd = $pc->Gregorian2JD($params['year'], $params['month'], $params['day'], 0, 0, 0);
 594:     $i = $d = 0;
 595:     while ($i < $n) {
 596:         //月の南中時刻
 597:         list($year, $month, $day, $hour, $min, $sec) = $pc->JD2Gregorian($jd);
 598:         $moonmeridian = $pc->moon_time(2, $params['longitude'], $params['latitude'], $height, $year, $month, $day);
 599:         if ($moonmeridian !FALSE) {
 600:             $x = (double)$i + $moonmeridian;
 601:             $moons[$i]['t']   = $d + $moonmeridian;
 602:             $moons[$i]['age'] = $pc->moon_age($year, $month, $day, $moonmeridian * 24, 0, 0);
 603:             $i++;
 604:         }
 605:         $jd++;
 606:         $d++;
 607:     }
 608: 
 609:     return $res;
 610: }

ユーザー関数 calcTideGraph はメソッド pahooTide::tide_level を呼び出し、指定日時における潮位を配列 $items に格納してゆく。この配列を、「PHPでNHK政治意識月例調査をグラフ表示」で紹介したjQueryプラグイン「jqPlot」を用いてグラフ表示する。

月齢は、月の画像をグラフ上にオーバーライトすることを目指す。プロットする場所は、月の南中時刻とすべく、メソッド pahooCalendar::moon_time によって南中時刻を求める。

 612: /**
 613:  * 潮位グラフ:表示用スクリプトおよびHTMLを求める.
 614:  * @param   pahooTide     $pt      潮位計算クラス
 615:  * @param   pahooCalendar $pc      暦計算クラス
 616:  * @param   array         $params  計算用パラメータ
 617:  * @param   string        $js      スクリプト格納用
 618:  * @param   string        $html    HTML格納用
 619:  * @param   string        $errmsg  エラーメッセージ格納用
 620:  * @return  bool TRUE:成功/FALSE:失敗
 621: */
 622: function makeGraph($pt, $pc, $params, &$js, &$html, &$errmsg) {
 623:     $js = $html = '';
 624:     $items = array();
 625:     $moons = array();
 626:     $locs  = array();
 627:     if (calcTideGraph($pt, $pc, $params, $items, $moons, $locs, $errmsg) == FALSE)  return FALSE;
 628: 
 629:     $title = "{$locs['title']}({$locs['prefecture']}{$locs['address']})";
 630:     $name   = GRAPH_TIDE;
 631:     $width  = MAP_WIDTH;
 632:     $height = MAP_HEIGHT;
 633: 
 634:     //潮位プロット・データ作成
 635:     $data = '';
 636:     foreach ($items as $item) {
 637:         $data .sprintf("['%s', %f], ", $item['dt'], $item['tlevel']);
 638:     }
 639: 
 640:     //月齢データ作成
 641:     $moon = '';
 642:     $path = MOONAGE;
 643:     foreach ($moons as $val) {
 644:         $x = round(30 + (MAP_WIDTH - 70) / $params['interval'* $val['t']);
 645:         $fname = sprintf("{$path}moon_%02d.png", round($val['age']));
 646:         $moon .=<<< EOT
 647: <img style="position:absolute; top:35px; left:{$x}px; width:40px; height:40px; z-index:999;" src="{$fname}" />
 648: 
 649: EOT;
 650:     }
 651: 
 652:     $js =<<< EOT
 653: $(function() {
 654:     jQuery.jqplot('{$name}',
 655:     [
 656:         [ {$data} ]
 657:     ],
 658:     {
 659:         //タイトル
 660:         title: {
 661:             text: '{$title}',
 662:             show: true,
 663:             fontSize: '16px',
 664:             textAlign: 'center',
 665:             textColor: 'black'
 666:         },
 667:         //背景
 668:         grid: {
 669:             background: '#EEFFFF'
 670:         },
 671:         //グラフ
 672:         seriesDefaults: {
 673:             showLine: true,
 674:             rendererOptions: { smooth: false },
 675:             markerOptions: { size: 0 },
 676:             color: 'blue',
 677:         },
 678:         //軸ラベル
 679:         axes: {
 680:             xaxis: {
 681:                 renderer: $.jqplot.DateAxisRenderer,
 682:                 tickOptions: { formatString: '%m/%d' },
 683:                 tickInterval: '1 days'
 684:             },
 685:             yaxis: {
 686:                 label: '潮位(cm)'
 687:             }
 688:         }
 689:     }
 690:     );
 691: });
 692: 
 693: EOT;
 694:     $html =<<< EOT
 695: <div id="{$name}" style="width:{$width}px; height:{$height}px;">
 696: {$moon}
 697: </div>
 698: </body>
 699: 
 700: EOT;
 701: 
 702:     return TRUE;
 703: }

calcTideGraph を呼び出し、ブラウザ上に潮位グラフを表示するためのユーザー関数が makeGraph である。
jqPlot に渡すスクリプトと、表示するHTMLは別々に生成する。jqPlot で画像を扱えないため、無理をしてHTML側でグラフ上にオーバーライトしている。

解説:メインプログラム

メインプログラムは、これまで紹介してきたものを流用している。
Googleマップの表示や住所検索については「PHPでGoogle等を利用して住所から緯度・経度を求める」を、UI:Datepicker を利用した日付入力については「PHPで日付入力:カレンダーから選択」を参照してほしい。

参考サイト

(この項おわり)
header