xref: /plugin/openlayersmap/syntax/olmap.php (revision 372f1508f6464a0536996de48a7c74938a8ab723)
1<?php
2/*
3 * Copyright (c) 2008-2012 Mark C. Prins <mprins@users.sf.net>
4*
5* Permission to use, copy, modify, and distribute this software for any
6* purpose with or without fee is hereby granted, provided that the above
7* copyright notice and this permission notice appear in all copies.
8*
9* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*/
17
18/**
19 * Plugin OL Maps: Allow Display of a OpenLayers Map in a wiki page.
20 *
21 * @author Mark Prins
22 */
23
24if (!defined('DOKU_INC'))
25	define('DOKU_INC', realpath(dirname(__FILE__) . '/../../') . '/');
26if (!defined('DOKU_PLUGIN'))
27	define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
28require_once (DOKU_PLUGIN . 'syntax.php');
29
30/**
31 * All DokuWiki plugins to extend the parser/rendering mechanism
32 * need to inherit from this class
33 */
34class syntax_plugin_openlayersmap_olmap extends DokuWiki_Syntax_Plugin {
35
36	/** defaults of the known attributes of the olmap tag. */
37	private $dflt = array (
38			'id'		=> 'olmap',
39			'width'		=> '550px',
40			'height'	=> '450px',
41			'lat'		=> 50.0,
42			'lon'		=> 5.1,
43			'zoom'		=> 12,
44			'toolbar'	=> true,
45			'statusbar'	=> true,
46			'controls'	=> true,
47			'poihoverstyle'	=> false,
48			'baselyr'	=>'OpenStreetMap',
49			'gpxfile'	=> '',
50			'kmlfile'	=> '',
51			'summary'	=>''
52	);
53
54	/**
55	 * Return the type of syntax this plugin defines.
56	 * @Override
57	 */
58	function getType() {
59		return 'substition';
60	}
61
62	/**
63	 * Defines how this syntax is handled regarding paragraphs.
64	 * @Override
65	 */
66	function getPType() {
67		//normal block stack
68		return 'block';
69	}
70
71	/**
72	 * Returns a number used to determine in which order modes are added.
73	 * @Override
74	 */
75	function getSort() {
76		return 901;
77	}
78
79	/**
80	 * This function is inherited from Doku_Parser_Mode.
81	 * Here is the place to register the regular expressions needed
82	 * to match your syntax.
83	 * @Override
84	 */
85	function connectTo($mode) {
86		$this->Lexer->addSpecialPattern('<olmap ?[^>\n]*>.*?</olmap>', $mode, 'plugin_openlayersmap_olmap');
87	}
88
89	/**
90	 * handle each olmap tag. prepare the matched syntax for use in the renderer.
91	 * @Override
92	 */
93	function handle($match, $state, $pos, &$handler) {
94		// break matched cdata into its components
95		list ($str_params, $str_points) = explode('>', substr($match, 7, -9), 2);
96		// get the lat/lon for adding them to the metadata (used by geotag)
97		preg_match('(lat[:|=]\"-?\d*\.\d*\")',$match,$mainLat);
98		preg_match('(lon[:|=]\"-?\d*\.\d*\")',$match,$mainLon);
99		$mainLat=substr($mainLat[0],5,-1);
100		$mainLon=substr($mainLon[0],5,-1);
101
102		$gmap = $this->_extract_params($str_params);
103		$overlay = $this->_extract_points($str_points);
104
105		$imgUrl = "{{";
106		// choose maptype based on tag
107		if (stripos($gmap['baselyr'],'google') !== false){
108			// use google
109			$imgUrl .= $this->_getGoogle($gmap, $overlay);
110		} elseif (stripos($gmap['baselyr'],'ve') !== false){
111			// use bing
112			$imgUrl .= $this->_getBing($gmap, $overlay);
113		} elseif (stripos($gmap['baselyr'],'bing') !== false){
114			// use bing
115			$imgUrl .= $this->_getBing($gmap, $overlay);
116			//} elseif (stripos($gmap['baselyr'],'mapquest') !== false){
117			// use mapquest
118			//	$imgUrl .=$this->_getMapQuest($gmap,$overlay);
119		} else {
120			$imgUrl .=$this->_getStaticOSM($gmap,$overlay);
121		}
122
123		// append dw specific params
124		$imgUrl .="&.png?".$gmap['width']."x".$gmap['height'];
125		$imgUrl .= "&nolink";
126		$imgUrl .= " |".$gmap['summary']."}} ";
127		// remove 'px'
128		// this breaks the gpx in the url. $imgUrl = str_replace("px", "",$imgUrl);
129
130		$imgUrl=p_render("xhtml", p_get_instructions($imgUrl), $info);
131
132		$mapid = $gmap['id'];
133
134		// create a javascript parameter string for the map
135		$param = '';
136		foreach ($gmap as $key => $val) {
137			$param .= is_numeric($val) ? "$key: $val, " : "$key: '" . hsc($val) . "', ";
138		}
139		if (!empty ($param)) {
140			$param = substr($param, 0, -2);
141		}
142		unset ($gmap['id']);
143
144		// create a javascript serialisation of the point data
145		$poi = '';
146		$poitable='';
147		$rowId=0;
148		if (!empty ($overlay)) {
149			foreach ($overlay as $data) {
150				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
151				$rowId++;
152				$poi .= ", {lat: $lat, lon: $lon, txt: '$text', angle: $angle, opacity: $opacity, img: '$img', rowId: $rowId}";
153				$poitable .='
154				<tr>
155				<td class="rowId">'.$rowId.'</td>
156				<td class="icon"><img src="'.DOKU_BASE.'lib/plugins/openlayersmap/icons/'.$img.'" alt="icon" /></td>
157				<td class="lat" title="'.$this->getLang('olmapPOIlatTitle').'">'.$lat.'</td>
158				<td class="lon" title="'.$this->getLang('olmapPOIlonTitle').'">'.$lon.'</td>
159				<td class="txt">'.$text.'</td>
160				</tr>';
161			}
162			$poi = substr($poi, 2);
163		}
164		//$js .= "createMap({" . $param . " },[$poi]);";
165		//$js .= "[{" . $param . " },[$poi]];";
166		$js .= "{mapOpts:{" . $param . " },poi:[$poi]};";
167		// unescape the json
168		$poitable = stripslashes($poitable);
169
170		return array($mapid,$js,$mainLat,$mainLon,$poitable,$gmap['summary'],$imgUrl);
171	}
172
173	/**
174	 * render html tag/output. render the content.
175	 * @Override
176	 */
177	function render($mode, &$renderer, $data) {
178		static $initialised = false; // set to true after script initialisation
179		static $mapnumber = 0; // incremeted for each map tag in the page source
180		list ($mapid, $param, $mainLat, $mainLon, $poitable, $poitabledesc, $staticImgUrl) = $data;
181
182		if ($mode == 'xhtml') {
183			$olscript = '';
184			$olEnable = false;
185			$gscript = '';
186			$gEnable = $this->getConf('enableGoogle');
187			$vscript = '';
188			$vEnable = false;
189			$mqEnable = $this->getConf('enableMapQuest');
190			$osmEnable = $this->getConf('enableOSM');
191			$enableBing = $this->getConf('enableBing');
192
193			$scriptEnable = '';
194
195			if (!$initialised) {
196				$initialised = true;
197				// render necessary script tags
198				if($gEnable){
199					$gscript ='<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.8&amp;sensor=false"></script>';
200				}
201
202				$vscript = $this->getConf('veScriptUrl');
203				$vscript = $vscript ? '<script type="text/javascript" src="' . $vscript . '"></script>' : "";
204
205				$olscript = $this->getConf('olScriptUrl');
206				$olscript = $olscript ? '<script type="text/javascript" src="' . $olscript . '"></script>' : "";
207				$olscript = str_replace('DOKU_BASE/', DOKU_BASE, $olscript);
208
209				$scriptEnable = '<script type="text/javascript"><!--//--><![CDATA[//><!--' . "\n";
210				$scriptEnable .= $olscript ? 'olEnable = true;' : 'olEnable = false;';
211				$scriptEnable .= $vscript ? ' veEnable = true;' : ' veEnable = false;';
212				$scriptEnable .= 'gEnable = '.($gEnable ? 'true' : 'false').';';
213				$scriptEnable .= 'osmEnable = '.($osmEnable ? 'true' : 'false').';';
214				$scriptEnable .= 'mqEnable = '.($mqEnable ? 'true' : 'false').';';
215				$scriptEnable .= 'bEnable = '.($enableBing ? 'true' : 'false').';';
216				$scriptEnable .= 'bApiKey="'.$this->getConf('bingAPIKey').'";';
217				$scriptEnable .= 'OpenLayers.ImgPath = "'.DOKU_BASE.'lib/plugins/openlayersmap/lib/'.$this->getConf('olMapStyle').'/";';
218				$scriptEnable .= "\n" . '//--><!]]></script>';
219			}
220			$renderer->doc .= "
221			$gscript
222			$vscript
223			$olscript
224			$scriptEnable";
225			if ($this->getConf('enableA11y')){
226				$renderer->doc .= '				<div id="'.$mapid.'-static" class="olStaticMap">'.$staticImgUrl.'</div>';
227			}
228			$renderer->doc .= '				<div id="'.$mapid.'-clearer" class="clearer"><p>&nbsp;</p></div>';
229			if ($this->getConf('enableA11y')){
230				// render a (hidden) table of the POI for the print and a11y presentation
231				$renderer->doc .= ' 	<div class="olPOItableSpan" id="'.$mapid.'-table-span"><table class="olPOItable" id="'.$mapid.'-table" summary="'.$poitabledesc.'" title="'.$this->getLang('olmapPOItitle').'">
232				<caption class="olPOITblCaption">'.$this->getLang('olmapPOItitle').'</caption>
233				<thead class="olPOITblHeader">
234				<tr>
235				<th class="rowId" scope="col">id</th>
236				<th class="icon" scope="col">'.$this->getLang('olmapPOIicon').'</th>
237				<th class="lat" scope="col" title="'.$this->getLang('olmapPOIlatTitle').'">'.$this->getLang('olmapPOIlat').'</th>
238				<th class="lon" scope="col" title="'.$this->getLang('olmapPOIlonTitle').'">'.$this->getLang('olmapPOIlon').'</th>
239				<th class="txt" scope="col">'.$this->getLang('olmapPOItxt').'</th>
240				</tr>
241				</thead>
242				<tfoot class="olPOITblFooter"><tr><td colspan="5">'.$poitabledesc.'</td></tr></tfoot>
243				<tbody class="olPOITblBody">'.$poitable.'</tbody>
244				</table></div>';
245
246				//TODO no tfoot when $poitabledesc is empty
247			}
248			// render inline mapscript
249			$renderer->doc .="\n		<script type='text/javascript'><!--//--><![CDATA[//><!--\n";
250			// var $mapid = $param
251			$renderer->doc .="		olMapData[$mapnumber] = $param
252			//--><!]]></script>";
253			$mapnumber++;
254			return true;
255		} elseif ($mode == 'metadata') {
256			// render metadata if available
257			if (!(($this->dflt['lat']==$mainLat)||($thisdflt['lon']==$mainLon))){
258				// unless they are the default
259				$renderer->meta['geo']['lat'] = $mainLat;
260				$renderer->meta['geo']['lon'] = $mainLon;
261			}
262			return true;
263		}
264		return false;
265	}
266
267	/**
268	 * extract parameters for the map from the parameter string
269	 *
270	 * @param   string    $str_params   string of key="value" pairs
271	 * @return  array                   associative array of parameters key=>value
272	 */
273	private function _extract_params($str_params) {
274		$param = array ();
275		preg_match_all('/(\w*)="(.*?)"/us', $str_params, $param, PREG_SET_ORDER);
276		// parse match for instructions, break into key value pairs
277		$gmap = $this->dflt;
278		foreach ($param as $kvpair) {
279			list ($match, $key, $val) = $kvpair;
280			$key = strtolower($key);
281			if (isset ($gmap[$key])){
282				if ($key == 'summary'){
283					// preserve case for summary field
284					$gmap[$key] = $val;
285				}else {
286					$gmap[$key] = strtolower($val);
287				}
288			}
289		}
290		return $gmap;
291	}
292
293	/**
294	 * extract overlay points for the map from the wiki syntax data
295	 *
296	 * @param   string    $str_points   multi-line string of lat,lon,text triplets
297	 * @return  array                   multi-dimensional array of lat,lon,text triplets
298	 */
299	private function _extract_points($str_points) {
300		$point = array ();
301		//preg_match_all('/^([+-]?[0-9].*?),\s*([+-]?[0-9].*?),(.*?),(.*?),(.*?),(.*)$/um', $str_points, $point, PREG_SET_ORDER);
302		/*
303		group 1: ([+-]?[0-9]+(?:\.[0-9]*)?)
304		group 2: ([+-]?[0-9]+(?:\.[0-9]*)?)
305		group 3: (.*?)
306		group 4: (.*?)
307		group 5: (.*?)
308		group 6: (.*)
309		*/
310		preg_match_all('/^([+-]?[0-9]+(?:\.[0-9]*)?),\s*([+-]?[0-9]+(?:\.[0-9]*)?),(.*?),(.*?),(.*?),(.*)$/um', $str_points, $point, PREG_SET_ORDER);
311		// create poi array
312		$overlay = array ();
313		foreach ($point as $pt) {
314			list ($match, $lat, $lon, $angle, $opacity, $img, $text) = $pt;
315			$lat = is_numeric($lat) ? $lat : 0;
316			$lon = is_numeric($lon) ? $lon : 0;
317			$angle = is_numeric($angle) ? $angle : 0;
318			$opacity = is_numeric($opacity) ? $opacity : 0.8;
319			$img = trim($img);
320			// TODO validate using exist & set up default img?
321			$text = addslashes(str_replace("\n", "", p_render("xhtml", p_get_instructions($text), $info)));
322			$overlay[] = array($lat, $lon, $text, $angle, $opacity, $img);
323		}
324		return $overlay;
325	}
326
327	/**
328	 * Create a MapQuest static map API image url.
329	 * @param array $gmap
330	 * @param array $overlay
331	 */
332	private function _getMapQuest($gmap,$overlay) {
333		$sUrl=$this->getConf('iconUrlOverload');
334		if (!$sUrl){
335			$sUrl=DOKU_URL;
336		}
337		switch ($gmap['baselyr']){
338			case 'mapquest hybrid':
339				$maptype='hyb';
340				break;
341			case 'mapquest sat':
342				// $maptype='sat'
343				// because sat coverage is very limited use 'hyb' instead of 'sat' so we don't get a blank map
344				$maptype='hyb';
345				break;
346			case 'mapquest road':
347			default:
348				$maptype='map';
349				break;
350		}
351		$imgUrl = "http://open.mapquestapi.com/staticmap/v3/getmap?declutter=true&";
352		if (count($overlay)< 1){
353			$imgUrl .= "?center=".$gmap['lat'].",".$gmap['lon'];
354			//max level for mapquest is 16
355			if ($gmap['zoom']>16) {
356				$imgUrl .= "&zoom=16";
357			} else			{
358				$imgUrl .= "&zoom=".$gmap['zoom'];
359			}
360		}
361		// use bestfit instead of center/zoom, needs upperleft/lowerright corners
362		//$bbox=$this->_calcBBOX($overlay, $gmap['lat'], $gmap['lon']);
363		//$imgUrl .= "bestfit=".$bbox['minlat'].",".$bbox['maxlon'].",".$bbox['maxlat'].",".$bbox['minlon'];
364
365		// TODO declutter option works well for square maps but not for rectangular, maybe compensate for that or compensate the mbr..
366		$imgUrl .= "&size=".str_replace("px", "",$gmap['width']).",".str_replace("px", "",$gmap['height']);
367
368		// TODO mapquest allows using one image url with a multiplier $NUMBER eg:
369		// $NUMBER = 2
370		// $imgUrl .= DOKU_URL."/".DOKU_PLUGIN."/".getPluginName()."/icons/".$img.",$NUMBER,C,".$lat1.",".$lon1.",0,0,0,0,C,".$lat2.",".$lon2.",0,0,0,0";
371		if (!empty ($overlay)) {
372			$imgUrl .= "&xis=";
373			foreach ($overlay as $data) {
374				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
375				//$imgUrl .= $sUrl."lib/plugins/openlayersmap/icons/".$img.",1,C,".$lat.",".$lon.",0,0,0,0,";
376				$imgUrl .= $sUrl."lib/plugins/openlayersmap/icons/".$img.",1,C,".$lat.",".$lon.",";
377			}
378			$imgUrl = substr($imgUrl,0,-1);
379		}
380		$imgUrl .= "&imageType=png&type=".$maptype;
381		dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::_getMapQuest: MapQuest image url is:');
382		return $imgUrl;
383	}
384	/**
385	 *
386	 * Create a Google maps static image url w/ the poi.
387	 * @param array $gmap
388	 * @param array $overlay
389	 */
390	private function _getGoogle($gmap, $overlay){
391		$sUrl=$this->getConf('iconUrlOverload');
392		if (!$sUrl){
393			$sUrl=DOKU_URL;
394		}
395		switch ($gmap['baselyr']){
396			case 'google hybrid':
397				$maptype='hybrid';
398				break;
399			case 'google sat':
400				$maptype='satellite';
401				break;
402			case 'google relief':
403				$maptype='terrain';
404				break;
405			case 'google road':
406			default:
407				$maptype='roadmap';
408				break;
409		}
410		// TODO maybe use viewport / visible instead of center/zoom,
411		//		see: https://code.google.com/intl/nl/apis/maps/documentation/staticmaps/#ImplicitPositioning
412		//http://maps.google.com/maps/api/staticmap?center=51.565690,5.456756&zoom=16&size=600x400&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/marker.png|label:1|51.565690,5.456756&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/marker-blue.png|51.566197,5.458966|label:2&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/parking.png|51.567177,5.457909|label:3&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/parking.png|51.566283,5.457330|label:4&markers=icon:http://wild-water.nl/dokuwiki/lib/plugins/openlayersmap/icons/parking.png|51.565630,5.457695|label:5&sensor=false&format=png&maptype=roadmap
413		$imgUrl = "http://maps.google.com/maps/api/staticmap?sensor=false";
414		$imgUrl .= "&size=".str_replace("px", "",$gmap['width'])."x".str_replace("px", "",$gmap['height']);
415		$imgUrl .= "&center=".$gmap['lat'].",".$gmap['lon'];
416		// max is 21 (== building scale), but that's overkill..
417		if ($gmap['zoom']>16) {
418			$imgUrl .= "&zoom=16";
419		} else			{
420			$imgUrl .= "&zoom=".$gmap['zoom'];
421		}
422
423		if (!empty ($overlay)) {
424			$rowId=0;
425			foreach ($overlay as $data) {
426				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
427				$imgUrl .= "&markers=icon%3a".$sUrl."lib/plugins/openlayersmap/icons/".$img."%7c".$lat.",".$lon."%7clabel%3a".++$rowId;
428			}
429		}
430		$imgUrl .= "&format=png&maptype=".$maptype;
431		global $conf;
432		$imgUrl .= "&language=".$conf['lang'];
433		dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::_getGoogle: Google image url is:');
434		return $imgUrl;
435	}
436
437	/**
438	 *
439	 * Create a Bing maps static image url w/ the poi.
440	 * @param array $gmap
441	 * @param array $overlay
442	 */
443	private function _getBing($gmap, $overlay){
444		if(!$this->getConf('bingAPIKey')){
445			// in case there is no Bing api key
446			$this->_getMapQuest($gmap, $overlay);
447		}
448		switch ($gmap['baselyr']){
449			case 've hybrid':
450			case 'bing hybrid':
451				$maptype='AerialWithLabels';
452				break;
453			case 've sat':
454			case 'bing sat':
455				$maptype='Aerial';
456				break;
457			case 've normal':
458			case 've road':
459			case 've':
460			case 'bing road':
461			default:
462				$maptype='Road';
463				break;
464		}
465		$bbox=$this->_calcBBOX($overlay, $gmap['lat'], $gmap['lon']);
466		//$imgUrl = "http://dev.virtualearth.net/REST/v1/Imagery/Map/".$maptype."/".$gmap['lat'].",".$gmap['lon']."/".$gmap['zoom'];
467		$imgUrl = "http://dev.virtualearth.net/REST/v1/Imagery/Map/".$maptype."/";
468		$imgUrl .= "?mapArea=".$bbox['minlat'].",".$bbox['minlon'].",".$bbox['maxlat'].",".$bbox['maxlon'];
469		// TODO declutter option works well for square maps but not for rectangular, maybe compensate for that or compensate the mbr..
470		$imgUrl .= "&declutter=1";
471		$imgUrl .= "&ms=".str_replace("px", "",$gmap['width']).",".str_replace("px", "",$gmap['height']);
472		$imgUrl .= "&key=".$this->getConf('bingAPIKey');
473		if (!empty ($overlay)) {
474			$rowId=0;
475			foreach ($overlay as $data) {
476				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
477				// TODO icon style lookup, see: http://msdn.microsoft.com/en-us/library/ff701719.aspx for iconStyle
478				$iconStyle=32;
479				$rowId++;
480				// NOTE: the max number of pushpins is 18!
481				if ($rowId==18) {
482					break;
483				}
484				$imgUrl .= "&pp=$lat,$lon;$iconStyle;$rowId";
485			}
486		}
487		dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::_getBing: bing image url is:');
488		return $imgUrl;
489	}
490
491	/**
492	 *
493	 * Create a static OSM map image url w/ the poi from http://staticmap.openstreetmap.de (staticMapLite)
494	 * use http://staticmap.openstreetmap.de "staticMapLite" or a local version
495	 * @param array $gmap
496	 * @param array $overlay
497	 *
498	 * @todo implementation for http://ojw.dev.openstreetmap.org/StaticMapDev/
499	 */
500	private function _getStaticOSM($gmap, $overlay){
501		//http://staticmap.openstreetmap.de/staticmap.php?center=47.000622235634,10.117187497601&zoom=5&size=500x350
502		// &markers=48.999812532766,8.3593749976708,lightblue1|43.154850037315,17.499999997306,lightblue1|49.487527053077,10.820312497573,ltblu-pushpin|47.951071133739,15.917968747369,ol-marker|47.921629720114,18.027343747285,ol-marker-gold|47.951071133739,19.257812497236,ol-marker-blue|47.180141361692,19.257812497236,ol-marker-green
503		global $conf;
504
505		switch ( $this->getConf('optionStaticMapGenerator')){
506			case 'local':
507				$imgUrl =$conf['baseurl']."/lib/plugins/openlayersmap/staticmap/map.php";
508				$imgUrl .= '?kml='.$gmap['kmlfile'];
509				$imgUrl .= '&gpx='.$gmap['gpxfile'];
510				break;
511			case 'remote':
512			default:
513				$imgUrl = "http://staticmap.openstreetmap.de/staticmap.php";
514		}
515
516		$imgUrl .= "&center=".$gmap['lat'].",".$gmap['lon'];
517		$imgUrl .= "&size=".str_replace("px", "",$gmap['width'])."x".str_replace("px", "",$gmap['height']);
518		if ($gmap['zoom']>16) {
519			// actually this could even be 18, but that seems overkill
520			$imgUrl .= "&zoom=16";
521		} else {
522			$imgUrl .= "&zoom=".$gmap['zoom'];
523		}
524
525		switch ($gmap['baselyr']){
526			case 'mapnik':
527			case 'openstreetmap':
528				$maptype='openstreetmap';
529				break;
530			case 'transport':
531				$maptype='transport';
532				break;
533			case 'landscape':
534				$maptype='landscape';
535				break;
536			case 'cycle map':
537				$maptype='cycle';
538				break;
539			case 'cloudmade':
540				$maptype='cloudmade';
541				break;
542			case 'cloudmade fresh':
543				$maptype='fresh';
544				break;
545			case 'hike and bike map':
546				$maptype='hikeandbike';
547				break;
548			case 'mapquest hybrid':
549			case 'mapquest road':
550			case 'mapquest sat':
551				$maptype='mapquest';
552				break;
553			default:
554				$maptype='';
555				break;
556		}
557		$imgUrl .= "&maptype=".$maptype;
558
559		if (!empty ($overlay)) {
560			$rowId=0;
561			$imgUrl .= "&markers=";
562			foreach ($overlay as $data) {
563				list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
564				$rowId++;
565				if ($this->getConf('optionStaticMapGenerator')=='remote') $iconStyle = "lightblue$rowId";
566				if ($this->getConf('optionStaticMapGenerator')=='local') $iconStyle = substr($img, 0,strlen($img)-4);
567				$imgUrl .= "$lat,$lon,$iconStyle%7c";
568			}
569			$imgUrl = substr($imgUrl,0,-3);
570		}
571
572		dbglog($imgUrl,'syntax_plugin_openlayersmap_olmap::_getStaticOSM: osm image url is:');
573		return $imgUrl;
574	}
575	/**
576	 * Calculate the minimum bbox for a start location + poi.
577	 *
578	 * @param array $overlay  multi-dimensional array of array($lat, $lon, $text, $angle, $opacity, $img)
579	 * @param float $lat latitude for map center
580	 * @param float $lon longitude for map center
581	 * @return multitype:float array describing the mbr and center point
582	 */
583	private function _calcBBOX($overlay, $lat, $lon){
584		$lats[] = $lat;
585		$lons[] = $lon;
586		foreach ($overlay as $data) {
587			list ($lat, $lon, $text, $angle, $opacity, $img) = $data;
588			$lats[] = $lat;
589			$lons[] = $lon;
590		}
591		sort($lats);
592		sort($lons);
593		// TODO: make edge/wrap around cases work
594		$centerlat = $lats[0]+($lats[count($lats)-1]-$lats[0]);
595		$centerlon = $lons[0]+($lons[count($lats)-1]-$lons[0]);
596		return array('minlat'=>$lats[0], 'minlon'=>$lons[0],
597				'maxlat'=>$lats[count($lats)-1], 'maxlon'=>$lons[count($lats)-1],
598				'centerlat'=>$centerlat,'centerlon'=>$centerlon);
599	}
600}