目次
サンプル・プログラムの実行例
YOLPコンテンツジオコーダAPI(Yahoo!JAPAN)は、世界のキーワードから緯度・経度を求める機能が弱い。たとえば「サンティアゴ」でキーワード検索すると、Google Geocoding API チリの首都を第一候補として返すが、YOLPコンテンツジオコーダAPIはドミニカ共和国の県都しか返さない。
そこで、地図上のマーカーをドラッグし、描画ボタンを押すことで航路を再描画する機能を採り入れた。これは Googleマップ でも利用できる。
サンプル・プログラムのダウンロード
| greatCircleSailing.php | サンプル・プログラム本体 |
| pahooGeoCode.php | 住所・緯度・経度に関わるクラス pahooGeoCode。 使い方は「PHPで住所・ランドマークから最寄り駅を求める」などを参照。include_path が通ったディレクトリに配置すること。 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 1.6.1 | 2025/09/19 | マーカードラッグ後に再描画で位置ズレを解消 |
| 1.6.0 | 2025/08/30 | .pahooEnv導入 |
| 1.5.0 | 2025/07/20 | GoogleMapsAPIのAdvancedMarkerに対応 |
| 1.4 | 2021/02/20 | PHP8対応,Yahoo! JavaScriptマップ廃止 |
| 1.3 | 2020/03/22 | OSM Nominatim Search API追加 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 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の変更に対応 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 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() 追加 |
準備:PHP の https対応
Windowsでは、"php.ini" の下記の行を有効化する。
extension=php_openssl.dllLinuxでは --with-openssl=/usr オプションを付けて再ビルドする。→OpenSSLインストール手順
これで準備は完了だ。
準備: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 を利用するのであれば Google Cloud Platform APIキー とマップID が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、IP2Location.ioを利用するのであれば「PHPでIPアドレスやホスト名から住所を求める」を、それぞれ参照されたい。
PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。
準備:pahooInputData 関数群
また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。
準備:地図サービスの選択
住所検索サービスは、Google、Yahoo!JAPAN、HeartRails Geo APIから選択可能で、定数 GEOSERVICE に値を設定すること。
サンプル・プログラムの流れ
解説:大圏航路と等角航路
なお、地球は完全な球体ではないので、厳密には大円と大圏航路には微妙なずれがある。今回は計算を簡便にする目的で、大円が大圏航路であるとしている。
これに対し、極点に対して常に一定の角度で進むコースを等角航路(rhumb line)と呼ぶ。天体観測によって緯度は観測できても、正確な時刻を知るためのクロノメーターが無かった時代は、大圏航路より時間がかかるが、等角航路を使っていた。
$$ \displaystyle tan(\delta) = \frac{sin(\delta_1) sin(\phi_2 - \phi)}{cos(\delta_1) sin(\phi_2 - \phi_1)} + \frac{sin(\delta_2) sin(\phi_1 - \phi)}{cos(\delta_2) sin(\phi_1 - \phi_2)} $$
によって計算できる。
また、地球の半径をRとすると、2地点間の大圏距離は
$$ \displaystyle R cos^{-1}(sin(\phi_1) sin(\delta_2) + cos(\phi_1) cos(\phi_2) cos(abs(\delta_2 - \delta_1)) $$
によって計算できる。
解説:大圏航路の軌跡
pahooGeoCode.php
734: /**
735: * 2地点間の大圏航路軌跡を求める
736: * @param float $long_a, $lati_a A地点の経度,緯度(世界測地系)
737: * @param float $long_b, $lati_b B地点の経度,緯度(世界測地系)
738: * @param array $points 軌跡の座標を格納
739: * [$n]['longitude'] 軌跡の経度(世界測地系)
740: * [$n]['latitude'] 軌跡の緯度(世界測地系)
741: * @return int 座標の数
742: *
743: */
744: function greatCircleSailing($long_a, $lati_a, $long_b, $lati_b, &$points) {
745: $lati_a = deg2rad($lati_a);
746: $long_a = deg2rad($long_a);
747: $lati_b = deg2rad($lati_b);
748: $long_b = deg2rad($long_b);
749:
750: $l1 = ($long_a >= 0) ? $long_a : 2 * pi() + $long_a;
751: $l2 = ($long_b >= 0) ? $long_b : 2 * pi() + $long_b;
752: $dd = $l2 - $l1;
753: $tt = 0.01; // 経度方向の増分
754: if ($dd < 0) {
755: $dd = abs($dd);
756: $tt = -$tt;
757: } else if ($dd > pi()) {
758: list($lati_a, $lati_b) = array($lati_b, $lati_a);
759: list($long_a, $long_b) = array($long_b, $long_a);
760: $dd = 2 * pi() - $dd;
761: }
762: $st = 0.0;
763: $cnt = 0;
764:
765: // 軌跡の計算
766: $latitude = $lati_a;
767: $longitude = $long_a;
768: while ($st < $dd) {
769: if ($latitude >= 0.5 * pi()) $latitude -= pi();
770: if ($longitude >= 1.0 * pi()) $longitude = $longitude - pi();
771: $points[$cnt]['latitude'] = rad2deg($latitude);
772: $points[$cnt]['longitude'] = rad2deg($longitude);
773: $longitude += $tt;
774: if ($longitude >= pi()) $longitude = $longitude - 2 * pi();
775: $latitude = (sin($lati_a) * sin($long_b - $longitude)) / (cos($lati_a) * sin($long_b - $long_a)) + (sin($lati_b) * sin($long_a - $longitude)) / (cos($lati_b) * sin($long_a - $long_b));
776: $latitude = atan($latitude);
777: if (sin($lati_a) / sin($lati_b) < 0) $latitude += pi();
778:
779: $st += abs($tt);
780: $cnt++;
781: }
782: $points[$cnt]['latitude'] = rad2deg($lati_b);
783: $points[$cnt]['longitude'] = rad2deg($long_b);
784: $cnt++;
785:
786: return $cnt;
787: }
なお、「PHPで弾道ミサイルの軌道を計算する」で紹介したように、Googleマップでは、メソッド Polyline のプロパティ geodesic を true にすることで、大圏航法による最短距離を近似描画できる。
解説:大圏航路の距離
pahooGeoCode.php
714: /**
715: * 2地点間の大圏航路距離を求める
716: * @param float $long_a, $lati_a A地点の経度,緯度(世界測地系)
717: * @param float $long_b, $lati_b B地点の経度,緯度(世界測地系)
718: * @return float 大圏航路距離
719: *
720: */
721: function greatCircleDistance($long_a, $lati_a, $long_b, $lati_b) {
722: $lati_a = deg2rad($lati_a);
723: $long_a = deg2rad($long_a);
724: $lati_b = deg2rad($lati_b);
725: $long_b = deg2rad($long_b);
726:
727: // 距離の計算
728: $ll = abs($long_b - $long_a);
729: $distance = 6371.0 * acos(sin($lati_a) * sin($lati_b) + cos($lati_a) * cos($lati_b) * cos($ll));
730:
731: return $distance;
732: }
解説:等角航路の軌跡
pahooGeoCode.php
789: /**
790: * 2地点間の等角航路軌跡を求める
791: * @param float $long_a, $lati_a A地点の経度,緯度(世界測地系)
792: * @param float $long_b, $lati_b B地点の経度,緯度(世界測地系)
793: * @param array $points 軌跡の座標を格納
794: * [$n]['longitude'] 軌跡の経度(世界測地系)
795: * [$n]['latitude'] 軌跡の緯度(世界測地系)
796: * @return float $distance 2地点間の等角航路距離を格納
797: * @return int 座標の数
798: *
799: */
800: function rhumbLine($long_a, $lati_a, $long_b, $lati_b, &$points, &$distance) {
801: $lati_a = deg2rad($lati_a);
802: $long_a = deg2rad($long_a);
803: $lati_b = deg2rad($lati_b);
804: $long_b = deg2rad($long_b);
805: $n = 200;
806:
807: // 経度方向の増分
808: $l1 = ($long_a >= 0) ? $long_a : 2 * pi() + $long_a;
809: $l2 = ($long_b >= 0) ? $long_b : 2 * pi() + $long_b;
810: $d1 = $l2 - $l1;
811: $t1 = 0.01;
812: $n = abs($d1) / $t1;
813: if ($d1 < 0) {
814: $d1 = 2 * pi() + $d1;
815: $t1 = -$t1;
816: } else if ($d1 > pi()) {
817: list($lati_a, $lati_b) = array($lati_b, $lati_a);
818: list($long_a, $long_b) = array($long_b, $long_a);
819: $d1 = 2 * pi() - $d1;
820: $n = abs($d1) / $t1;
821: }
822:
823: // 緯度方向の増分
824: $l1 = $lati_a;
825: $l2 = $lati_b;
826: $d2 = $l2 - $l1;
827: if ($d2 >= pi()) {
828: $d2 -= pi();
829: $t2 = - $d2 / $n;
830: } else {
831: $t2 = $d2 / $n; // 緯度方向の増分
832: }
833:
834: // 軌跡の計算
835: $latitude = $lati_a;
836: $longitude = $long_a;
837: $distance = 0.0;
838: for ($cnt = 0; $cnt < $n; $cnt++) {
839: if ($latitude >= 0.5 * pi()) $latitude -= pi();
840: if ($longitude >= 1.0 * pi()) $longitude = $longitude - 2 * pi();
841: $points[$cnt]['latitude'] = rad2deg($latitude);
842: $points[$cnt]['longitude'] = rad2deg($longitude);
843: $longitude += $t1;
844: $latitude += $t2;
845: if ($cnt >= 1) {
846: $distance += $this->greatCircleDistance($points[$cnt - 1]['longitude'], $points[$cnt - 1]['latitude'], $points[$cnt]['longitude'], $points[$cnt]['latitude']);
847: }
848: }
849: $points[$cnt]['latitude'] = rad2deg($lati_b);
850: $points[$cnt]['longitude'] = rad2deg($long_b);
851: $distance += $this->greatCircleDistance($points[$cnt - 1]['longitude'], $points[$cnt - 1]['latitude'], $points[$cnt]['longitude'], $points[$cnt]['latitude']);
852: $cnt++;
853:
854: return $cnt;
855: }
なお、等角航路は複雑な曲線を描くため、距離を求める適当な方程式がない。そこで、隣り合う座標間の大圏距離を積分し、等角航路の距離を同時に算出する。
解説:初期値
greatCircleSailing.php
66: // マップの表示サイズ(単位:ピクセル)
67: define('MAP_WIDTH', 600);
68: define('MAP_HEIGHT', 400);
69: // マップID
70: define('MAPID', 'map_id');
71: // 初期値
72: define('DEF_LONGITUDE0', 139.766667); // 地図中心(経度)
73: define('DEF_LATITUDE0', 35.681111); // (緯度)
74: define('DEF_FROM', '東京駅'); // from(クエリ)
75: define('DEF_TO', 'ワシントン'); // to (クエリ)
76: define('DEF_CAT_FROM', 'landmark'); // from(カテゴリ)
77: define('DEF_CAT_TO', 'world'); // to (カテゴリ)
78: define('DEF_LONGITUDE1', 139.766667); // from(経度)
79: define('DEF_LATITUDE1', 35.681111); // (緯度)
80: define('DEF_LONGITUDE2', -77.0329165); // to (経度)
81: define('DEF_LATITUDE2', 38.8878665); // (緯度)
82: define('DEF_TYPE', 'roadmap'); // マップタイプ
83: define('DEF_ZOOM', 2); // ズーム
解説:Googleマップ上でマーカーをドラッグする
greatCircleSailing.php
171: /**
172: * マーカー設定、フィット機能:Googleマップ用スクリプト
173: * @param float $latitude, $longitude 経路の中央点座標(緯度・経度)
174: * @param bool $drag TRUE:ドラッグで再描画する/FALSE:しない(デフォルト)
175: * @return string JavaScript
176: */
177: function jsDragMarker_Gmap($latitude, $longitude, $drag=FALSE) {
178: $submit = $drag ? 'document.myform.submit();' : '';
179:
180: $js =<<< EOT
181: // イベント設定
182: document.getElementById('fit').addEventListener('click', fitting, false);
183:
184: // マーカー設定
185: marker_001.setDraggable(true);
186: google.maps.event.addListener(marker_001, 'dragend', function() {
187: let latlng = marker_001.getPosition();
188: document.getElementById('longitude1').value = latlng.lng();
189: document.getElementById('latitude1').value = latlng.lat();
190: document.getElementById('from').value = '';
191: {$submit}
192: });
193:
194: marker_002.setDraggable(true);
195: google.maps.event.addListener(marker_002, 'dragend', function() {
196: let latlng = marker_002.getPosition();
197: document.getElementById('longitude2').value = latlng.lng();
198: document.getElementById('latitude2').value = latlng.lat();
199: document.getElementById('to').value = '';
200: {$submit}
201: });
202:
203: /**
204: * 地図を最適サイズにフィットする
205: * @param なし
206: * @return なし
207: */
208: function fitting() {
209: var lat0, lng0, lat1, lng1;
210: var lat = Array();
211: var lng = Array();
212: lat[0] = document.getElementById('latitude1').value;
213: lng[0] = document.getElementById('longitude1').value;
214: lat[1] = document.getElementById('latitude2').value;
215: lng[1] = document.getElementById('longitude2').value;
216: lat[2] = {$latitude};
217: lng[2] = {$longitude};
218:
219: // 南西端(lat0, lng0), 北東端(lat1, lng1)を求める
220: if (lat[0] <= lat[1]) {
221: lat0 = lat[0];
222: lat1 = lat[1];
223: } else {
224: lat0 = lat[1];
225: lat1 = lat[0];
226: }
227: if (lat[2] >= 0) {
228: if (lat[0] <= lat[2]) {
229: lng0 = lng[0];
230: lng1 = lng[1];
231: } else {
232: lng0 = lng[1];
233: lng1 = lng[0];
234: }
235: } else {
236: if (lat[0] <= lat[2]) {
237: lng0 = lng[1];
238: lng1 = lng[0];
239: } else {
240: lng0 = lng[0];
241: lng1 = lng[1];
242: }
243: }
244:
245: var bounds = new google.maps.LatLngBounds(new google.maps.LatLng(lat0, lng0), new google.maps.LatLng(lat1, lng1));
246: map.fitBounds(bounds); // 地図表示の最適化
247: }
248:
249: EOT;
250: return $js;
251: }
クラス pahooGeoCode では、さまざまな情報を付加しやすいように、GoogleMaps JavaScript API の AdvancedMarker オブジェクトを利用している。しかし、2025年(令和7年)7月現在、AdvancedMarker はドラッグすることができない。そこで、ドラッグ可能で旧来用いていた Marker オブジェクトを利用することにした。
メソッド drawJSmap もしくは drawGMap の引数 $markerLevel で AdvancedMarker か Marker かを選ぶことができるようにした。省略時は AdvancedMarker になるようにしてある。
解説:Leafletマップ上でマーカーをドラッグする
greatCircleSailing.php
287: /**
288: * マーカー設定、フィット機能スクリプト:Leafletマップ用
289: * @param float $latitude, $longitude 経路の中央点座標(緯度・経度)
290: * @param bool $drag TRUE:ドラッグで再描画する/FALSE:しない(デフォルト)
291: * @return string JavaScript
292: */
293: function jsDragMarker_Leaflet($latitude, $longitude, $drag=FALSE) {
294: // Leafletマップ:東経・西経の境目で線分が折り返さないよう調整
295: if ($longitude < 0) $longitude = 360 + $longitude;
296: $submit = $drag ? 'document.myform.submit();' : '';
297:
298: $js =<<< EOT
299: // イベント設定
300: document.getElementById('fit').addEventListener('click', fitting, false);
301:
302: // マーカー設定
303: marker_001.dragging.enable();
304: marker_001.on('dragend', function(event) {
305: var marker = event.target;
306: var position = marker_001.getLatLng();
307: marker.setLatLng(new L.LatLng(position.lat, position.lng),{draggable:true});
308: map.panTo(new L.LatLng(position.lat, position.lng))
309: document.getElementById('longitude1').value = position.lng;
310: document.getElementById('latitude1').value = position.lat;
311: document.getElementById('from').value = '';
312: {$submit}
313: });
314:
315: marker_002.dragging.enable();
316: marker_002.on('dragend', function(event) {
317: var marker = event.target;
318: var position = marker.getLatLng();
319: marker.setLatLng(new L.LatLng(position.lat, position.lng),{draggable:true});
320: map.panTo(new L.LatLng(position.lat, position.lng))
321: document.getElementById('longitude2').value = position.lng;
322: document.getElementById('latitude2').value = position.lat;
323: document.getElementById('to').value = '';
324: {$submit}
325: });
326:
327: /**
328: * 地図を最適サイズにフィットする
329: * @param なし
330: * @return なし
331: */
332: function fitting() {
333: var lat0, lng0, lat1, lng1;
334: var lat = Array();
335: var lng = Array();
336: lat[0] = document.getElementById('latitude1').value;
337: lng[0] = document.getElementById('longitude1').value;
338: lat[1] = document.getElementById('latitude2').value;
339: lng[1] = document.getElementById('longitude2').value;
340: lat[2] = {$latitude};
341: lng[2] = {$longitude};
342:
343: // 南西端(lat0, lng0), 北東端(lat1, lng1)を求める
344: if (lat[0] <= lat[1]) {
345: lat0 = lat[0];
346: lat1 = lat[1];
347: } else {
348: lat0 = lat[1];
349: lat1 = lat[0];
350: }
351: if (lat[2] >= 0) {
352: if (lat[0] <= lat[2]) {
353: lng0 = lng[0];
354: lng1 = lng[1];
355: } else {
356: lng0 = lng[1];
357: lng1 = lng[0];
358: }
359: } else {
360: if (lat[0] <= lat[2]) {
361: lng0 = lng[1];
362: lng1 = lng[0];
363: } else {
364: lng0 = lng[0];
365: lng1 = lng[1];
366: }
367: }
368:
369: // Leafletマップ:東経・西経の境目で線分が折り返さないよう調整
370: // bug:Leafletマップではfitが効かない
371: if (lng0 < 0) lng0 = 360 + lng0;
372: if (lng1 < 0) lng1 = 360 + lng1;
373: var bounds = L.latLngBounds([lat0, lng0], [lat1, lng1])
374: map.fitBounds(bounds); // 地図表示の最適化
375: }
376: EOT;
377: return $js;
378: }
解説:航路描画スクリプト
greatCircleSailing.php
253: /**
254: * 航路描画スクリプト:Googleマップ用スクリプト
255: * @param int $id 識別ID
256: * @param array $items 航路の座標
257: * @param string $color 描画色(RGB)
258: * @param int $weight 線の太さ(省略時=1)
259: * @return string JavaScript
260: */
261: function jsDrawLine_Gmap($id, $items, $color, $weight=1) {
262: $js =<<< EOT
263: var pline{$id} = new google.maps.Polyline({
264: map: map,
265: path:[
266:
267: EOT;
268: foreach ($items as $item) {
269: $js .=<<< EOT
270: new google.maps.LatLng({$item['latitude']}, {$item['longitude']}),
271:
272: EOT;
273: }
274: $js .=<<< EOT
275: ],
276: strokeColor: "{$color}",
277: strokeOpacity: 1,
278: strokeWeight: {$weight},
279: zIndex: 1
280: });
281:
282: EOT;
283: return $js;
284: }
greatCircleSailing.php
380: /**
381: * 航路描画スクリプト:Leafletマップ用
382: * @param int $id 識別ID
383: * @param array $items 航路の座標
384: * @param string $color 描画色(RGB)
385: * @param int $weight 線の太さ(省略時=1)
386: * @return string JavaScript
387: */
388: function jsDrawLine_Leaflet($id, $items, $color, $weight=1) {
389: $cnt = 0;
390: $js =<<< EOT
391: var pline{$id}_{$cnt} = L.polyline([
392:
393: EOT;
394: foreach ($items as $key=>$item) {
395: if ($key > 0) {
396: // Leafletマップ:東経・西経の境目で線分が折り返さないよう調整
397: if ((($items[$key - 1]['longitude'] > 0) && ($items[$key]['longitude'] < 0)) || (($items[$key - 1]['longitude'] < 0) && ($items[$key]['longitude'] > 0))) {
398: $cnt++;
399: $js .=<<< EOT
400: ], {
401: "color": "#{$color}",
402: "opacity": 1.0,
403: "weight": {$weight},
404: }).addTo(map);
405: var pline{$id}_{$cnt} = L.polyline([
406:
407: EOT;
408: }
409: }
410: $long = ($item['longitude'] < 0) ? 360 + $item['longitude'] : $item['longitude'];
411: $js .=<<< EOT
412: [{$item['latitude']}, {$long}],
413:
414: EOT;
415: }
416: $js .=<<< EOT
417: ], {
418: "color": "#{$color}",
419: "opacity": 1.0,
420: "weight": {$weight},
421: }).addTo(map);
422:
423: EOT;
424: return $js;
425: }
なお、Lefletのメソッド polyline を使って線分を繋げていくと、東経と西経を
跨ぐ地点(経度の符合が変わる地点)を境目に、線分が折り返してしまう。そこで、境目で線分を、いったん断絶させるようにしている。航路を拡大してみると、この部分で切れていることが見えてしまうが、ご了承いただきたい。
また、マーカーの位置を調整するため、前述のユーザー関数 jsDragMarker_Leaflet を含め、マイナス表記の西経を360度表記に変換したりしており、フィット機能が正常に働かないため、これを省いている。
解説:距離計算表
greatCircleSailing.php
428: /**
429: * 距離計算表を作成
430: * @param array $items 地点・距離情報
431: * @param object $pgc pahooGeoCodeクラス
432: * @return string 距離計算表(HTML)
433: */
434: function makeDistanceTable($items, $pgc) {
435: $d11 = sprintf('%.1f', round($items['dist1'], 1));
436: $d12 = sprintf('%.1f', round($pgc->km2mi($items['dist1']), 1));
437: $d13 = sprintf('%.1f', round($pgc->km2nm($items['dist1']), 1));
438: $d21 = sprintf('%.1f', round($items['dist2'], 1));
439: $d22 = sprintf('%.1f', round($pgc->km2mi($items['dist2']), 1));
440: $d23 = sprintf('%.1f', round($pgc->km2nm($items['dist2']), 1));
441: $ww = MAP_WIDTH / 4;
442:
443: $html =<<< EOT
444: <table class="plists">
445: <caption>距離計算</caption>
446: <tr>
447: <th style="width:{$ww}px;"> </th>
448: <th style="width:{$ww}px;">キロメートル</th>
449: <th style="width:{$ww}px;">マイル</th>
450: <th style="width:{$ww}px;">海里</th>
451: </tr>
452: <tr>
453: <th>大圏航路</th>
454: <td>{$d11}</td>
455: <td>{$d12}</td>
456: <td>{$d13}</td>
457: </tr>
458: <tr>
459: <th>等角航路</th>
460: <td>{$d21}</td>
461: <td>{$d22}</td>
462: <td>{$d23}</td>
463: </tr>
464: </table>
465:
466: EOT;
467: return $html;
468: }
活用例
参考サイト
- 各種WebAPIの登録方法:ぱふぅ家のホームページ
- PHPでGoogleを利用して住所から緯度・経度を求める
- PHPで2地点間の直線距離を求める
- 地図上で2点間の直線距離を測:みんなの知識 ちょっと便利帳

(2025年9月19日)マーカードラッグ後に再描画するとマーカーの位置が戻ってしまう不具合を解消.
(2025年8月30日).pahooEnv導入
(2025年7月20日)GoogleMaps JavaScript APIのAdvancedMarkerに対応
(2025年6月14日)GoogleMaps JavaScript APIの変更に対応した.