PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/application/helpers/map.php

http://github.com/ushahidi/Ushahidi_Web
PHP | 518 lines | 352 code | 50 blank | 116 comment | 39 complexity | a6b4229392daf33966578e43f6f898a5 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php defined('SYSPATH') OR die('No direct access allowed.');
  2. /**
  3. * Map helper class
  4. *
  5. * Portions of this class credited to: zzolo, phayes, tmcw, brynbellomy, bdragon
  6. *
  7. * @package Map
  8. * @author Ushahidi Team
  9. * @copyright (c) 2008 Ushahidi Team
  10. * @license http://www.ushahidi.com/license.html
  11. */
  12. class map_Core {
  13. /**
  14. * Generate the Javascript for Each Layer
  15. * .. new OpenLayers.Layer.XXXX
  16. * if $all is set to TRUE all maps are rendered
  17. * **caveat is that each mapping api js must be loaded**
  18. *
  19. * @param bool $all
  20. * @return string $js
  21. */
  22. public static function layers_js($all = FALSE)
  23. {
  24. // Javascript
  25. $js = "";
  26. // Get All Layers
  27. $layers = map::base();
  28. // Next get the default base layer
  29. $default_map = Kohana::config('settings.default_map');
  30. if ( ! isset($layers[$default_map]))
  31. { // Map Layer Doesn't Exist - default to google
  32. $default_map = "osm_mapnik";
  33. }
  34. // Get OpenLayers type
  35. $openlayers_type = $layers[$default_map]->openlayers;
  36. // To store options for the bing maps
  37. foreach ($layers as $layer)
  38. {
  39. if ($layer->active)
  40. {
  41. if ($all == TRUE OR $layer->openlayers == $openlayers_type)
  42. {
  43. //++ Bing doesn't have the first argument
  44. if ($layer->openlayers == "Bing")
  45. {
  46. // Options for the Bing layer constructor
  47. $bing_options = "{\n"
  48. . "\t name: \"".$layer->data['name']."\",\n"
  49. . "\t type: \"".$layer->data['type']."\",\n"
  50. . "\t key: \"".$layer->data['key']."\"\n"
  51. . "}";
  52. $js .= "var ".$layer->name." = new OpenLayers.Layer.".$layer->openlayers."($bing_options);\n\n";
  53. }
  54. // Allow layers to specify a custom set of OpenLayers options
  55. // this should allow plugins to add OpenLayers Layer types we haven't considered here
  56. // See http://dev.openlayers.org/docs/files/OpenLayers/Layer-js.html for other layer types
  57. elseif (isset($layer->openlayers_options) AND $layer->openlayers_options != null)
  58. {
  59. $js .= "var ".$layer->name." = new OpenLayers.Layer.{$layer->openlayers}({$layer->openlayers_options});\n\n";
  60. }
  61. // Finally construct JS for the majority of layers
  62. else
  63. {
  64. $js .= "var ".$layer->name." = new OpenLayers.Layer.".$layer->openlayers."(\"".$layer->title."\", ";
  65. if ($layer->openlayers == 'XYZ' || $layer->openlayers == 'WMS' || $layer->openlayers == 'TMS')
  66. {
  67. if (isset($layer->data['url']))
  68. {
  69. $js .= '"'.$layer->data['url'].'", ';
  70. }
  71. }
  72. // Extra parameter used by WMS - key/value pairs representing the GetMap query string
  73. if ($layer->openlayers == 'WMS' AND isset($layer->wms_params))
  74. {
  75. // Add some unnescessary params so that json_encode creates an object not an array.
  76. if (!isset($layer->wms_params['styles'])) $layer->wms_params['styles'] = '';
  77. if (!isset($layer->wms_params['layers'])) $layer->wms_params['layers'] = '';
  78. $js .= json_encode($layer->wms_params);
  79. $js .= ', ';
  80. }
  81. $js .= "{ \n";
  82. $params = $layer->data;
  83. if (isset($params['url'])) unset($params['url']);
  84. if (isset($params['baselayer'])) unset($params['baselayer']);
  85. $params['sphericalMercator'] = true;
  86. // Special handling for layer type - don't quote the value as it should be a js variable
  87. if (isset($params['type']) AND $params['type'] != '')
  88. {
  89. $js .= " type: ".$params['type'].",\n";
  90. unset($params['type']);
  91. }
  92. foreach ($params as $key => $value)
  93. {
  94. if ( ! empty($value))
  95. {
  96. $js .= " ".$key.": ".json_encode($value).",\n";
  97. }
  98. }
  99. $js .= " maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)});\n\n";
  100. }
  101. }
  102. }
  103. }
  104. // Hack on XYZ / Esri Attribution layer here since XYZ doesn't support images in attribution
  105. if (stripos($default_map,'esri_') !== FALSE AND $all == FALSE)
  106. {
  107. // We have two div ids that we use for maps, map and divMap. We need a more permanent
  108. // solution to cover any div name.
  109. // $js .= "if ( $(\"#map\").length > 0 ) { divName = \"map\" }else{ divName= \"divMap\" }"
  110. // . "var esriAttributionDiv = document.createElement('div');"
  111. // . "$(esriAttributionDiv).html('"
  112. // . "<img src=\"http://www.arcgis.com/home/images/map/logo-sm.png\" style=\"float:right;\"/>"
  113. // . "<small style=\"position: absolute; bottom: -10px;\">"
  114. // . "Sources: Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, "
  115. // . "GeoBase, IGN, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), "
  116. // . "and the GIS User Community"
  117. // . "</small>');\n"
  118. // . "$(esriAttributionDiv).css({\n"
  119. // . "\t'position': 'absolute',\n"
  120. // . "\t'z-index': 10000,\n"
  121. // . "\t'margin': '-40px 0 0 85px',\n"
  122. // . "\t'right': $('div#'+divName).offset().right + 10,\n"
  123. // . "\t'width': $('div#'+divName).width() - 90,\n"
  124. // . "});\n"
  125. // . "$(esriAttributionDiv).appendTo($('div#'+divName));";
  126. }
  127. Event::run('ushahidi_filter.map_layers_js', $js);
  128. return $js;
  129. }
  130. /**
  131. * Generate the Map Array.
  132. * These are the maps that show up in the Layer Switcher
  133. * if $all is set to TRUE all maps are rendered
  134. * **caveat is that each mapping api js must be loaded **
  135. *
  136. * @param bool $all
  137. * @return string $js
  138. */
  139. public static function layers_array($all = FALSE)
  140. {
  141. // Javascript
  142. $js = "[";
  143. // Get All Layers
  144. $layers = map::base();
  145. // Next get the default base layer
  146. $default_map = Kohana::config('settings.default_map');
  147. if ( ! isset($layers[$default_map]))
  148. {
  149. // Map Layer Doesn't Exist - default to google
  150. $default_map = "google_normal";
  151. }
  152. // Get openlayers type
  153. $openlayers_type = $layers[$default_map]->openlayers;
  154. $js .= $default_map;
  155. foreach ($layers as $layer)
  156. {
  157. if ($layer->name != $default_map AND $layer->active)
  158. {
  159. if ($all == TRUE OR $layer->openlayers == $openlayers_type)
  160. {
  161. $js .= ",".$layer->name;
  162. }
  163. }
  164. }
  165. $js .= "]";
  166. return $js;
  167. }
  168. /**
  169. * Generate the Map Base Layer Object
  170. * If a layer name is passed, it will return only the object
  171. * for that layer
  172. *
  173. * @author
  174. * @param string $layer_name
  175. * @return string $js
  176. */
  177. public static function base($layer_name = NULL)
  178. {
  179. $layers = array();
  180. // Esri Topo
  181. $layer = new stdClass();
  182. $layer->active = TRUE;
  183. $layer->name = 'esri_topo';
  184. $layer->openlayers = "XYZ";
  185. $layer->title = 'Esri World Topo Map';
  186. $layer->description = 'This world topographic map (aka "the community basemap") includes boundaries, cities, water features, physiographic features, parks, landmarks, transportation, and buildings.';
  187. $layer->api_url = '';
  188. $layer->data = array(
  189. 'baselayer' => TRUE,
  190. 'attribution' => '',
  191. 'url' => Kohana::config('core.site_protocol').'://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/${z}/${y}/${x}',
  192. 'type' => '',
  193. 'transitionEffect' => 'resize',
  194. );
  195. $layers[$layer->name] = $layer;
  196. // Esri Street Map
  197. $layer = new stdClass();
  198. $layer->active = TRUE;
  199. $layer->name = 'esri_street';
  200. $layer->openlayers = "XYZ";
  201. $layer->title = 'Esri Street Map';
  202. $layer->description = 'This map service presents highway-level data for the world and street-level data for North America, Europe, Southern Africa, parts of Asia, and more.';
  203. $layer->api_url = '';
  204. $layer->data = array(
  205. 'baselayer' => TRUE,
  206. 'attribution' => '',
  207. 'url' => Kohana::config('core.site_protocol').'://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/${z}/${y}/${x}',
  208. 'type' => '',
  209. 'transitionEffect' => 'resize',
  210. );
  211. $layers[$layer->name] = $layer;
  212. // Esri Imagery
  213. $layer = new stdClass();
  214. $layer->active = TRUE;
  215. $layer->name = 'esri_imagery';
  216. $layer->openlayers = "XYZ";
  217. $layer->title = 'Esri Imagery Map';
  218. $layer->description = 'This map service presents satellite imagery for the world and high-resolution imagery for the United States, Great Britain, and hundreds of cities around the world.';
  219. $layer->api_url = '';
  220. $layer->data = array(
  221. 'baselayer' => TRUE,
  222. 'attribution' => '',
  223. 'url' => Kohana::config('core.site_protocol').'://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/${z}/${y}/${x}',
  224. 'type' => '',
  225. 'transitionEffect' => 'resize',
  226. );
  227. $layers[$layer->name] = $layer;
  228. // Esri National Geographic
  229. $layer = new stdClass();
  230. $layer->active = TRUE;
  231. $layer->name = 'esri_natgeo';
  232. $layer->openlayers = "XYZ";
  233. $layer->title = 'Esri National Geographic Map';
  234. $layer->description = 'This map is designed to be used as a general reference map for informational and educational purposes as well as a basemap by GIS professionals and other users for creating web maps and web mapping applications.';
  235. $layer->api_url = '';
  236. $layer->data = array(
  237. 'baselayer' => TRUE,
  238. 'attribution' => '',
  239. 'url' => Kohana::config('core.site_protocol').'://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/${z}/${y}/${x}',
  240. 'type' => '',
  241. 'transitionEffect' => 'resize',
  242. );
  243. $layers[$layer->name] = $layer;
  244. // GOOGLE Satellite
  245. $layer = new stdClass();
  246. $layer->active = TRUE;
  247. $layer->name = 'google_satellite';
  248. $layer->openlayers = "Google";
  249. $layer->title = 'Google Maps Satellite';
  250. $layer->description = 'Google Maps Satellite Imagery.';
  251. $layer->api_url = 'https://maps.google.com/maps/api/js?v=3.7&amp;sensor=false&amp;language='.Kohana::config('locale.language.0');
  252. $layer->data = array(
  253. 'baselayer' => TRUE,
  254. 'type' => 'google.maps.MapTypeId.SATELLITE',
  255. 'animationEnabled' => TRUE,
  256. );
  257. $layers[$layer->name] = $layer;
  258. // GOOGLE Hybrid
  259. $layer = new stdClass();
  260. $layer->active = TRUE;
  261. $layer->name = 'google_hybrid';
  262. $layer->openlayers = "Google";
  263. $layer->title = 'Google Maps Hybrid';
  264. $layer->description = 'Google Maps with roads and terrain.';
  265. $layer->api_url = 'https://maps.google.com/maps/api/js?v=3.7&amp;sensor=false&amp;language='.Kohana::config('locale.language.0');
  266. $layer->data = array(
  267. 'baselayer' => TRUE,
  268. 'type' => 'google.maps.MapTypeId.HYBRID',
  269. 'animationEnabled' => TRUE,
  270. );
  271. $layers[$layer->name] = $layer;
  272. // GOOGLE Normal
  273. $layer = new stdClass();
  274. $layer->active = TRUE;
  275. $layer->name = 'google_normal';
  276. $layer->openlayers = "Google";
  277. $layer->title = 'Google Maps Normal';
  278. $layer->description = 'Standard Google Maps Roads';
  279. $layer->api_url = 'https://maps.google.com/maps/api/js?v=3.7&amp;sensor=false&amp;language='.Kohana::config('locale.language.0');
  280. $layer->data = array(
  281. 'baselayer' => TRUE,
  282. 'type' => '',
  283. 'animationEnabled' => TRUE,
  284. );
  285. $layers[$layer->name] = $layer;
  286. // GOOGLE Physical
  287. $layer = new stdClass();
  288. $layer->active = TRUE;
  289. $layer->name = 'google_physical';
  290. $layer->openlayers = "Google";
  291. $layer->title = 'Google Maps Physical';
  292. $layer->description = 'Google Maps Hillshades';
  293. $layer->api_url = 'https://maps.google.com/maps/api/js?v=3.7&amp;sensor=false&amp;language='.Kohana::config('locale.language.0');
  294. $layer->data = array(
  295. 'baselayer' => TRUE,
  296. 'type' => 'google.maps.MapTypeId.TERRAIN',
  297. 'animationEnabled' => TRUE,
  298. );
  299. $layers[$layer->name] = $layer;
  300. // BING Road
  301. $layer = new stdClass();
  302. $layer->active = TRUE;
  303. $layer->name = 'bing_road';
  304. $layer->openlayers = "Bing";
  305. $layer->title = 'Bing-Road';
  306. $layer->description = 'Bing Road Maps';
  307. $layer->api_signup = Kohana::config('core.site_protocol').'://www.bingmapsportal.com/';
  308. $layer->api_url = '';
  309. $layer->data = array(
  310. 'name' => 'Bing-Road',
  311. 'baselayer' => TRUE,
  312. 'key' => Kohana::config('settings.api_live'),
  313. 'type' => 'Road',
  314. );
  315. $layers[$layer->name] = $layer;
  316. // BING Hybrid
  317. $layer = new stdClass();
  318. $layer->active = TRUE;
  319. $layer->name = 'bing_hybrid';
  320. $layer->openlayers = "Bing";
  321. $layer->title = 'Bing-Hybrid';
  322. $layer->description = 'Bing hybrid of streets and satellite tiles.';
  323. $layer->api_signup = Kohana::config('core.site_protocol').'://www.bingmapsportal.com/';
  324. $layer->api_url = '';
  325. $layer->data = array(
  326. 'name' => 'Bing-Hybrid',
  327. 'baselayer' => TRUE,
  328. 'key' => Kohana::config('settings.api_live'),
  329. 'type' => 'AerialWithLabels',
  330. );
  331. $layers[$layer->name] = $layer;
  332. // BING Aerial
  333. $layer = new stdClass();
  334. $layer->active = TRUE;
  335. $layer->name = 'bing_satellite';
  336. $layer->openlayers = "Bing";
  337. $layer->title = 'Bing-Satellite';
  338. $layer->description = 'Bing Satellite Tiles';
  339. $layer->api_signup = Kohana::config('core.site_protocol').'://www.bingmapsportal.com/';
  340. $layer->api_url = '';
  341. $layer->data = array(
  342. 'name' => 'Bing-Satellite',
  343. 'baselayer' => TRUE,
  344. 'key' => Kohana::config('settings.api_live'),
  345. 'type' => 'Aerial',
  346. );
  347. $layers[$layer->name] = $layer;
  348. // OpenStreetMap Mapnik
  349. $layer = new stdClass();
  350. $layer->active = TRUE;
  351. $layer->name = 'osm_mapnik';
  352. $layer->openlayers = "OSM.Mapnik";
  353. $layer->title = 'OSM Mapnik';
  354. $layer->description = 'The main OpenStreetMap map';
  355. $layer->api_url = Kohana::config('core.site_protocol').'://www.openstreetmap.org/openlayers/OpenStreetMap.js';
  356. $layer->data = array(
  357. 'baselayer' => TRUE,
  358. 'attribution' => '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>',
  359. 'url' => 'http://tile.openstreetmap.org/${z}/${x}/${y}.png',
  360. 'type' => '',
  361. 'transitionEffect' => 'resize',
  362. );
  363. $layers[$layer->name] = $layer;
  364. // OpenStreetMap Cycling Map
  365. $layer = new stdClass();
  366. $layer->active = TRUE;
  367. $layer->name = 'osm_cycle';
  368. $layer->openlayers = "OSM.CycleMap";
  369. $layer->title = 'OSM Cycling Map';
  370. $layer->description = 'OpenStreetMap with highlighted bike lanes';
  371. $layer->api_url = Kohana::config('core.site_protocol').'://www.openstreetmap.org/openlayers/OpenStreetMap.js';
  372. $layer->data = array(
  373. 'baselayer' => TRUE,
  374. 'attribution' => '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>',
  375. 'url' => 'http://tile.openstreetmap.org/cycle/${z}/${x}/${y}.png',
  376. 'type' => '',
  377. 'transitionEffect' => 'resize',
  378. );
  379. $layers[$layer->name] = $layer;
  380. // OpenStreetMap Transport
  381. $layer = new stdClass();
  382. $layer->active = TRUE;
  383. $layer->name = 'osm_TransportMap';
  384. $layer->openlayers = "OSM.TransportMap";
  385. $layer->title = 'OSM Transport Map';
  386. $layer->description = 'TransportMap';
  387. $layer->api_url = Kohana::config('core.site_protocol').'://www.openstreetmap.org/openlayers/OpenStreetMap.js';
  388. $layer->data = array(
  389. 'baselayer' => TRUE,
  390. 'attribution' => '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>',
  391. 'url' => 'http://tile.openstreetmap.org/transport/${z}/${x}/${y}.png',
  392. 'type' => '',
  393. 'transitionEffect' => 'resize',
  394. );
  395. $layers[$layer->name] = $layer;
  396. // Add Custom Layers
  397. // Filter::map_base_layers
  398. Event::run('ushahidi_filter.map_base_layers', $layers);
  399. if ($layer_name)
  400. {
  401. if (isset($layers[$layer_name]))
  402. {
  403. return $layers[$layer_name];
  404. }
  405. else
  406. {
  407. return FALSE;
  408. }
  409. }
  410. else
  411. {
  412. return $layers;
  413. }
  414. }
  415. /**
  416. * GeoCode An Address
  417. *
  418. * @author
  419. * @param string $address
  420. * @return array $geocodes - lat/lon
  421. */
  422. public static function geocode($address = NULL)
  423. {
  424. return geocode::geocode($address);
  425. }
  426. /**
  427. * Reverse Geocode a point
  428. *
  429. * @author
  430. * @param double $latitude
  431. * @param double $longitude
  432. * @return string closest approximation of the point as a display name
  433. */
  434. public static function reverse_geocode($latitude,$longitude)
  435. {
  436. return geocode::reverseGeocode($latitude, $longitude);
  437. }
  438. /**
  439. * Calculate distances between two points
  440. *
  441. * @param double point 1 latitude
  442. * @param double point 1 longitude
  443. * @param double point 2 latitude
  444. * @param double point 2 longitude
  445. * @param string unit (m, k, n)
  446. */
  447. public static function distance($lat1, $lon1, $lat2, $lon2, $unit = "k")
  448. {
  449. $theta = $lon1 - $lon2;
  450. $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
  451. $dist = acos($dist);
  452. $dist = rad2deg($dist);
  453. $miles = $dist * 60 * 1.1515;
  454. $unit = strtoupper($unit);
  455. if ($unit == "K")
  456. {
  457. return ($miles * 1.609344);
  458. }
  459. else if ($unit == "N")
  460. {
  461. return ($miles * 0.8684);
  462. }
  463. else
  464. {
  465. return $miles;
  466. }
  467. }
  468. }