1 <?php
if (!defined('PmWiki')) exit();
4 This script adds support for gps coordinates conversion and displaying at maps
5 - add (:geo [args] coords :) tag functionality
7 Copyright 2006-2011 Anomen (ludek_h@seznam.cz)
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published
10 by the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
14 * GPX export (see sourceblock for howto)
18 $RecipeInfo['Geobox']['Version'] = '2012-09-07';
21 Markup('geo','fulltext','/\(:geo\s+((?:[dmsDMS,.]+:\s+)?(?:[a-z]+=\S+\s+)*)?(.*?)\s*:\)/e',
22 "geobox_maps(strtolower('$1'),'$2')");
24 SDV($GeoBoxDefaultFormat,'dm');
26 SDVA($GeoBoxLinks, array(
27 'maps.google.com'=>'http://maps.google.com/?q=$N%20$E',
28 'mapy.cz'=>'http://www.mapy.cz/?query=$N$LAT%20$E$LON',
29 'geocaching.com/maps'=>'http://www.geocaching.com/map/default.aspx?lat=$N&lng=$E',
30 'geocaching.com/near'=>'http://www.geocaching.com/seek/nearest.aspx?lat=$N&lng=$E&f=1'
33 function geobox_asint($m, $index)
36 if (isset($m[$index])) {
37 $res = strtr($m[$index], ',', '.');
45 if (strtolower($Charset) == 'utf-8') {
48 $pat[2] = '\'\'|\"|“|″|”|’’|';
50 $pat[0] = chr(0xB0) . '|\*';
56 function geobox_parse_coords($coords)
62 $re_num = "\d+(?:[.,]\d*)?";
83 $regex_pre = "(N|S|)\s*(${re_coord})\s*;?\s*(E|W|)\s*(${re_coord})";
84 $regex_post = "()(${re_coord})\s*(N|S)\s*\;?s*(${re_coord})\s*(E|W)";
86 if (preg_match("/^\s*${regex_pre}\s*\$/xi", $coords, $m)) {
87 $res['result'] = 'PRE';
88 $res['pattern'] = $regex_pre;
90 else if (preg_match("/^\s*${regex_post}\s*\$/xi", $coords, $m)) {
91 $res['result'] = 'POST';
92 $res['pattern'] = $regex_post;
93 $m[1]=$m[6];$m[6]=$m[11]; // move directions
99 $res[0] = abs(geobox_asint($m, 3)) +
geobox_asint($m, 4)/60 +
geobox_asint($m, 5)/(60*60);
100 $res[1] = abs(geobox_asint($m, 8)) +
geobox_asint($m, 9)/60 +
geobox_asint($m, 10)/(60*60);
102 if (geobox_asint($m, 3) < 0) { $res[0] = -$res[0]; }
103 if (geobox_asint($m, 8) < 0) { $res[1] = -$res[1]; }
105 if (strtoupper($m[1]) == 'S') { $res[0] = -$res[0]; }
106 if (strtoupper($m[6]) == 'W') { $res[1] = -$res[1]; }
112 function geobox_floor0($foo)
114 if($foo > 0) { return floor($foo); }
115 else { return ceil($foo); }
118 function geobox_sign($foo)
120 return ($foo < 0) ?
"-" : "";
123 function geobox_atan2($y, $x)
126 return ($x >= 0) ?
0 : pi();
128 return 2 * atan((sqrt($x*$x+
$y*$y)-$x)/$y);
133 function geobox_convert_coords($c)
135 $c['LAT'] = ($c[0] > 0) ?
"N" : "S";
136 $c['LON'] = ($c[1] > 0) ?
"E" : "W";
138 $c['NSig'] = geobox_sign($c[0]);
139 $c['ESig'] = geobox_sign($c[1]);
141 $c['N'] = sprintf("%'08.5f",$c[0]);
142 $c['E'] = sprintf("%'08.5f",$c[1]);
143 $c['W'] = sprintf("%'08.5f",-$c[1]);
144 $c['S'] = sprintf("%'08.5f",-$c[0]);
145 $c['Nd'] = sprintf("%'08.5f",abs($c[0]));
146 $c['Ed'] = sprintf("%'08.5f",abs($c[1]));
148 // convert to [Ndi]°[Nmi]'[Ns]" and [Ndi]°[Nm]'
149 $c['Ndi'] = sprintf("%'02.0f",floor($c['Nd']));
150 $c['Ni'] = $c['NSig'] . $c['Ndi'];
151 $c['Nm'] = sprintf("%'06.3f",($c['Nd']-$c['Ndi'])*60);
152 $c['Nmi'] = sprintf("%'02.0f",floor($c['Nm']));
154 $c['Ns'] = sprintf("%'06.3f",($s-floor($s))*60);
155 $c['Nsi'] = sprintf("%'02.0f",floor($c['Ns']));
157 $c['Edi'] = sprintf("%'03.0f",floor($c['Ed']));
158 $c['Ei'] = $c['ESig'] . $c['Edi'];
159 $c['Em'] = sprintf("%'06.3f",($c['Ed']-$c['Edi'])*60);
160 $c['Emi'] = sprintf("%'02.0f",floor($c['Em']));
162 $c['Es'] = sprintf("%'06.3f",($s-floor($s))*60);
163 $c['Esi'] = sprintf("%'02.0f",floor($c['Es']));
169 * Parses parameters and returns them in array.
171 * If parameter is specified by uniquely distinguishable substring of known
172 * parameter (e.g.: dist=10),
173 * full parameter value is also returned (e.g.: distance=10).
175 function geobox_parse_params($param)
177 $known_params = array('format', 'azimuth', 'distance');
179 $params = array('param' => $param);
181 $pairs = preg_split("/\s+/", $param, -1, PREG_SPLIT_NO_EMPTY
);
182 foreach ($pairs as $p) {
183 $tokens=explode('=', $p);
184 if (strpos($tokens[0],":") !== false) {
185 $params['format'] = $tokens[0];
187 $params[$tokens[0]] = $tokens[1];
188 foreach ($known_params as $k) {
189 if (strpos($k, $tokens[0]) === 0) {
190 $params[$k] = $tokens[1];
199 function geobox_build_link($link, $c)
201 return preg_replace('/\\$([A-Za-z]+)/e', '$c[\'$1\']', $link);
204 function geobox_maps($param, $coords_param)
206 global $GeoBoxDefaultFormat, $GeoBoxLinks;
208 $c = geobox_parse_coords($coords_param);
210 if (empty($c['result'])) {
211 return "[Invalid \"$coords_param\"]";
214 $params = geobox_parse_params($param);
215 $cformat = $params['format'];
217 if (!empty($params['azimuth']) ||
!empty($params['distance'])) {
218 if (is_numeric($params['azimuth']) && is_numeric($params['distance'])) {
219 $c = geobox_projection($c[0], $c[1], $params['azimuth'], $params['distance']);
221 return "[Invalid azimuth \"${params['azimuth']}\" or distance \"${params['distance']}\"]";
224 $c = geobox_convert_coords($c);
226 if (empty($cformat)) {
227 $cformat = $GeoBoxDefaultFormat;
229 if (strpos($cformat, "s") !== false) {
230 $COORDS=geobox_build_link('$NSig$Ndi°$Nmi\'$Ns" $ESig$Edi°$Emi\'$Es"', $c);// DMS
232 else if (strpos($cformat, "m") !== false) {
233 $COORDS=geobox_build_link('$NSig$Ndi°$Nm\' $ESig$Edi°$Em\'', $c);// DM
236 $COORDS=geobox_build_link('$NSig$Nd° $ESig$Ed°', $c);//
241 if (is_array($GeoBoxLinks) && !empty($GeoBoxLinks)) {
243 foreach ($GeoBoxLinks as $t=>$l) {
244 $l = geobox_build_link($l, $c);
245 $result .= " [[$l | $t]]";
253 * Calculates coordinates of point given by starting coordinates, azimuth and distance (meters).
254 * All angles are in degrees.
256 function geobox_projection($latitude_deg, $longtitude_deg, $azimuth_deg, $distance) {
258 //source: geocaching_tool2.xls
262 $azimuth = $azimuth_deg*$ro;
263 $latitude = $latitude_deg*$ro;
265 $fi2 = sin($latitude)*cos($DR)+
cos($latitude)*sin($DR)*cos($azimuth);
270 $x = (cos($DR)-sin($latitude)*sin($lat))/(cos($latitude)*cos($lat));
272 $y = sin($DR)*sin($azimuth)/cos($lat);
274 $la2 = geobox_atan2($y, $x);
276 $lon = $longtitude_deg +
$la2/$ro;
280 $ret[0] = $lat / $ro;