Source for file utils.php

Documentation is available at utils.php

  1. <?php
  2. /**
  3. * @package org.routamc.positioning
  4. * @author The Midgard Project, http://www.midgard-project.org
  5. * @version $Id: utils.php 3757 2006-07-27 14:32:42Z bergie $
  6. * @copyright The Midgard Project, http://www.midgard-project.org
  7. * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
  8. */
  9.  
  10. /**
  11. * Position handling utils, use static methods
  12. *
  13. * @package org.routamc.positioning
  14. */
  15. class org_routamc_positioning_utils extends midcom_baseclasses_components_purecode
  16. {
  17. /**
  18. * Get distance between to positions in kilometers
  19. *
  20. * Code from http://www.corecoding.com/getfile.php?file=25
  21. */
  22. function get_distance($from, $to, $unit = 'K', $round = true)
  23. {
  24. $theta = $from['longitude'] - $to['longitude'];
  25. $dist = sin(deg2rad($from['latitude'])) * sin(deg2rad($to['latitude'])) + cos(deg2rad($from['latitude'])) * cos(deg2rad($to['latitude'])) * cos(deg2rad($theta));
  26. $dist = acos($dist);
  27. $dist = rad2deg($dist);
  28. $dist = $dist * 60 * 1.1515;
  29. if ($unit == "K")
  30. {
  31. $dist *= 1.609344;
  32. }
  33. else if ($unit == "N")
  34. {
  35. $dist *= 0.8684;
  36. }
  37. if ($round)
  38. {
  39. $dist = round($dist, 1);
  40. }
  41. return $dist;
  42. }
  43. /**
  44. * Get bearing from position to another
  45. *
  46. * Code from http://www.corecoding.com/getfile.php?file=25
  47. */
  48. function get_bearing($from, $to)
  49. {
  50. if (round($from['longitude'], 1) == round($to['longitude'], 1))
  51. {
  52. if ($from['latitude'] < $to['latitude'])
  53. {
  54. $bearing = 0;
  55. }
  56. else
  57. {
  58. $bearing = 180;
  59. }
  60. }
  61. else
  62. {
  63. $dist = org_routamc_positioning_utils::get_distance($from, $to, 'N');
  64. $arad = acos((sin(deg2rad($to['latitude'])) - sin(deg2rad($from['latitude'])) * cos(deg2rad($dist / 60))) / (sin(deg2rad($dist / 60)) * cos(deg2rad($from['latitude']))));
  65. $bearing = $arad * 180 / pi();
  66. if (sin(deg2rad($to['longitude'] - $from['longitude'])) < 0)
  67. {
  68. $bearing = 360 - $bearing;
  69. }
  70. }
  71. $dirs = array("N","E","S","W");
  72. $rounded = round($bearing / 22.5) % 16;
  73. if (($rounded % 4) == 0)
  74. {
  75. $dir = $dirs[$rounded / 4];
  76. }
  77. else
  78. {
  79. $dir = $dirs[2 * floor(((floor($rounded / 4) + 1) % 4) / 2)];
  80. $dir .= $dirs[1 + 2 * floor($rounded / 8)];
  81. }
  82. return $dir;
  83. }
  84. /**
  85. * Converts DMS ( Degrees / minutes / seconds ) to decimal format longitude / latitude
  86. *
  87. * Code from http://www.web-max.ca/PHP/misc_6.php
  88. */
  89. function coordinate_to_decimal($deg, $min, $sec)
  90. {
  91. return $deg+((($min*60)+($sec))/3600);
  92. }
  93.  
  94. /**
  95. * Converts decimal longitude / latitude to DMS ( Degrees / minutes / seconds )
  96. *
  97. * Code from http://www.web-max.ca/PHP/misc_6.php
  98. */
  99. function decimal_to_coordinate($dec)
  100. {
  101. // This is the piece of code which may appear to
  102. // be inefficient, but to avoid issues with floating
  103. // point math we extract the integer part and the float
  104. // part by using a string function.
  105. $vars = explode(".",$dec);
  106. $deg = $vars[0];
  107. $tempma = "0.{$vars[1]}";
  108. $tempma = $tempma * 3600;
  109. $min = floor($tempma / 60);
  110. $sec = $tempma - ($min*60);
  111. $coordinate = array
  112. (
  113. 'deg' => $deg,
  114. 'min' => $min,
  115. 'sec' => $sec
  116. );
  117. return $coordinate;
  118. }
  119.  
  120. /**
  121. * Pretty-print a coordinate value (latitude or longitude)
  122. *
  123. * Code from http://en.wikipedia.org/wiki/Geographic_coordinate_conversion
  124. *
  125. * @return string
  126. */
  127. function pretty_print_coordinate($coordinate)
  128. {
  129. return sprintf("%0.0f° %2.3f",
  130. floor(abs($coordinate)),
  131. 60*(abs($coordinate)-floor(abs($coordinate)))
  132. );
  133. }
  134.  
  135. /**
  136. * Pretty-print a full coordinate (longitude and latitude)
  137. *
  138. * Code from http://en.wikipedia.org/wiki/Geographic_coordinate_conversion
  139. *
  140. * @return string
  141. */
  142. function pretty_print_coordinates($latitude, $longitude)
  143. {
  144. return sprintf("%s %s, %s %s",
  145. ($latitude>0)?"N":"S", org_routamc_positioning_utils::pretty_print_coordinate($latitude),
  146. ($longitude>0)?"E":"W", org_routamc_positioning_utils::pretty_print_coordinate($longitude)
  147. );
  148. }
  149. /**
  150. * Figure out which class to use for positioning
  151. * @param string $class MidCOM class name
  152. * @param string $classname
  153. */
  154. function get_positioning_class($class)
  155. {
  156. // See what kind of object we're querying for
  157. switch ($class)
  158. {
  159. case 'org_routamc_positioning_log_dba':
  160. case 'org_routamc_positioning_city_dba':
  161. case 'org_routamc_positioning_aerodrom_dba':
  162. // Real position entry, query it directly
  163. $classname = $class;
  164. break;
  165. default:
  166. // Non-positioning MidCOM DBA object, query it through location cache
  167. $classname = 'org_routamc_positioning_location_dba';
  168. break;
  169. }
  170. return $classname;
  171. }
  172. /**
  173. * Get closest items
  174. *
  175. * @param string $class MidCOM DBA class to query
  176. * @param Array $position Center position
  177. * @param integer $limit How many results to return
  178. * @return Array Array of MidCOM DBA objects sorted by proximity
  179. */
  180. function get_closest($class, $center, $limit, $modifier = 0.05)
  181. {
  182. $classname = org_routamc_positioning_utils::get_positioning_class($class);
  183. if ($classname != $class)
  184. {
  185. $direct = false;
  186. }
  187. else
  188. {
  189. $direct = true;
  190. }
  191. $qb = $_MIDCOM->dbfactory->new_query_builder($classname);
  192. if (!$direct)
  193. {
  194. // We're querying a regular DBA object through a location object
  195. $qb->add_constraint('parentclass', '=', $class);
  196. }
  197. static $rounds = 0;
  198. $rounds++;
  199. $from['latitude'] = $center['latitude'] + $modifier;
  200. if ($from['latitude'] > 90)
  201. {
  202. $from['latitude'] = 90;
  203. }
  204. $from['longitude'] = $center['longitude'] - $modifier;
  205. if ($from['longitude'] < -180)
  206. {
  207. $from['longitude'] = -180;
  208. }
  209. $to['latitude'] = $center['latitude'] - $modifier;
  210. if ($to['latitude'] < -90)
  211. {
  212. $to['latitude'] = -90;
  213. }
  214. $to['longitude'] = $center['longitude'] + $modifier;
  215. if ($to['longitude'] > 180)
  216. {
  217. $to['longitude'] = 180;
  218. }
  219. $qb->begin_group('AND');
  220. $qb->add_constraint('latitude', '<', $from['latitude']);
  221. $qb->add_constraint('latitude', '>', (float) $to['latitude']);
  222. $qb->end_group();
  223. $qb->begin_group('AND');
  224. $qb->add_constraint('longitude', '>', (float) $from['longitude']);
  225. $qb->add_constraint('longitude', '<', (float) $to['longitude']);
  226. $qb->end_group();
  227. $result_count = $qb->count();
  228. //echo "<br />Round {$rounds}, lat1 {$from['latitude']} lon1 {$from['longitude']}, lat2 {$to['latitude']} lon2 {$to['longitude']}: {$result_count} results\n";
  229. if ($result_count < $limit)
  230. {
  231. if ( $from['latitude'] == 90
  232. && $from['longitude'] == -180
  233. && $to['latitude'] == -90
  234. && $to['longitude'] == 180)
  235. {
  236. // We've queried the entire globe so we return whatever we got
  237. $results = $qb->execute();
  238. $closest = Array();
  239. foreach ($results as $result)
  240. {
  241. $result_coordinates = Array(
  242. 'latitude' => $result->latitude,
  243. 'longitude' => $result->longitude,
  244. );
  245. $distance = sprintf("%05d", round(org_routamc_positioning_utils::get_distance($center, $result_coordinates)));
  246. if (!$direct)
  247. {
  248. // Instantiate the real object as the result
  249. $result = new $class($result->parent);
  250. $result->latitude = $result_coordinates['latitude'];
  251. $result->longitude = $result_coordinates['longitude'];
  252. }
  253. $closest[$distance . $result->guid] = $result;
  254. }
  255. ksort($closest);
  256. reset($closest);
  257. return $closest;
  258. }
  259. $modifier = $modifier * 1.05;
  260. return org_routamc_positioning_utils::get_closest($class, $center, $limit, $modifier);
  261. }
  262. $results = $qb->execute();
  263. $closest = Array();
  264. foreach ($results as $result)
  265. {
  266. $result_coordinates = Array(
  267. 'latitude' => $result->latitude,
  268. 'longitude' => $result->longitude,
  269. );
  270. $distance = sprintf("%05d", round(org_routamc_positioning_utils::get_distance($center, $result_coordinates)));
  271. if (!$direct)
  272. {
  273. // Instantiate the real object as the result
  274. $result = new $class($result->parent);
  275. $result->latitude = $result_coordinates['latitude'];
  276. $result->longitude = $result_coordinates['longitude'];
  277. }
  278. $closest[$distance . $result->guid] = $result;
  279. }
  280. ksort($closest);
  281. reset($closest);
  282. while(count($closest) > $limit)
  283. {
  284. array_pop($closest);
  285. }
  286. return $closest;
  287. }
  288. }

Documentation generated on Tue, 15 Aug 2006 13:01:37 +0300 by phpDocumentor 1.3.0RC3