xref: /plugin/openlayersmap/StaticMap.php (revision da6f229f6a0134a382d8502bff367a6523d94bc4)
1628e43ccSMark Prins<?php
2628e43ccSMark Prins
3628e43ccSMark Prins/*
4628e43ccSMark Prins * Copyright (c) 2012 Mark C. Prins <mprins@users.sf.net>
5628e43ccSMark Prins*
6628e43ccSMark Prins* Based on staticMapLite 0.03 available at http://staticmaplite.svn.sourceforge.net/viewvc/staticmaplite/
7628e43ccSMark Prins*
8628e43ccSMark Prins* Copyright (c) 2009 Gerhard Koch <gerhard.koch AT ymail.com>
9628e43ccSMark Prins*
10628e43ccSMark Prins* Licensed under the Apache License, Version 2.0 (the "License");
11628e43ccSMark Prins* you may not use this file except in compliance with the License.
12628e43ccSMark Prins* You may obtain a copy of the License at
13628e43ccSMark Prins*
14628e43ccSMark Prins*     http://www.apache.org/licenses/LICENSE-2.0
15628e43ccSMark Prins*
16628e43ccSMark Prins* Unless required by applicable law or agreed to in writing, software
17628e43ccSMark Prins* distributed under the License is distributed on an "AS IS" BASIS,
18628e43ccSMark Prins* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19628e43ccSMark Prins* See the License for the specific language governing permissions and
20628e43ccSMark Prins* limitations under the License.
21628e43ccSMark Prins*/
226c6bb022SMark Prinsinclude_once('geoPHP/geoPHP.inc');
23628e43ccSMark Prins/**
24628e43ccSMark Prins * @author Mark C. Prins <mprins@users.sf.net>
25628e43ccSMark Prins * @author Gerhard Koch <gerhard.koch AT ymail.com>
26628e43ccSMark Prins *
27628e43ccSMark Prins */
28628e43ccSMark Prinsclass StaticMap {
29628e43ccSMark Prins	// these should probably not be changed
30628e43ccSMark Prins	protected $tileSize = 256;
31628e43ccSMark Prins
32628e43ccSMark Prins	// the final output
33628e43ccSMark Prins	var $doc = '';
34628e43ccSMark Prins
35628e43ccSMark Prins	protected $tileInfo = array(
36628e43ccSMark Prins			// OSM sources
37628e43ccSMark Prins			'openstreetmap'=>array(
38628e43ccSMark Prins					'txt'=>'(c) OpenStreetMap CC-BY-SA',
39628e43ccSMark Prins					'logo'=>'osm_logo.png',
40628e43ccSMark Prins					'url'=>'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png'),
41628e43ccSMark Prins			// cloudmade
42628e43ccSMark Prins			'cloudmade' =>array(
43628e43ccSMark Prins					'txt'=>'CloudMade tiles',
44628e43ccSMark Prins					'logo'=>'cloudmade_logo.png',
45628e43ccSMark Prins					'url'=> 'http://tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/2/256/{Z}/{X}/{Y}.png'),
46628e43ccSMark Prins			'fresh' =>array(
47628e43ccSMark Prins					'txt'=>'CloudMade tiles',
48628e43ccSMark Prins					'logo'=>'cloudmade_logo.png',
49628e43ccSMark Prins					'url'=> 'http://tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{Z}/{X}/{Y}.png'),
50628e43ccSMark Prins			// OCM sources
51628e43ccSMark Prins			'cycle'=>array(
52628e43ccSMark Prins					'txt'=>'OpenCycleMap tiles',
53628e43ccSMark Prins					'logo'=>'cycle_logo.png',
54628e43ccSMark Prins					'url'=>'http://tile.opencyclemap.org/cycle/{Z}/{X}/{Y}.png'),
55628e43ccSMark Prins			'transport'=>array(
56628e43ccSMark Prins					'txt'=>'OpenCycleMap tiles',
57628e43ccSMark Prins					'logo'=>'cycle_logo.png',
58628e43ccSMark Prins					'url'=>'http://tile2.opencyclemap.org/transport/{Z}/{X}/{Y}.png'),
59628e43ccSMark Prins			'landscape'=>array(
60628e43ccSMark Prins					'txt'=>'OpenCycleMap tiles',
61628e43ccSMark Prins					'logo'=>'cycle_logo.png',
62628e43ccSMark Prins					'url'=>'http://tile3.opencyclemap.org/landscape/{Z}/{X}/{Y}.png'),
63628e43ccSMark Prins			// H&B sources
64628e43ccSMark Prins			'hikeandbike'=>array(
65628e43ccSMark Prins					'txt'=>'Hike & Bike Map',
66628e43ccSMark Prins					'logo'=>'hnb_logo.png',
67628e43ccSMark Prins					'url'=>'http://toolserver.org/tiles/hikebike/{Z}/{X}/{Y}.png'),
68628e43ccSMark Prins			//'piste'=>array(
69628e43ccSMark Prins			//		'txt'=>'OpenPisteMap tiles',
70628e43ccSMark Prins			//		'logo'=>'piste_logo.png',
71628e43ccSMark Prins			//		'url'=>''),
72628e43ccSMark Prins			//'sea'=>array(
73628e43ccSMark Prins			//		'txt'=>'OpenSeaMap tiles',
74628e43ccSMark Prins			//		'logo'=>'sea_logo.png',
75628e43ccSMark Prins			//		'url'=>''),
76628e43ccSMark Prins			// MapQuest
77628e43ccSMark Prins			'mapquest'=>array(
78628e43ccSMark Prins					'txt'=>'MapQuest tiles',
79628e43ccSMark Prins					'logo'=>'mq_logo.png',
80628e43ccSMark Prins					'url'=>'http://otile3.mqcdn.com/tiles/1.0.0/osm/{Z}/{X}/{Y}.png')
81628e43ccSMark Prins	);
82628e43ccSMark Prins	protected $tileDefaultSrc = 'openstreetmap';
83628e43ccSMark Prins
84628e43ccSMark Prins	// set up markers
85628e43ccSMark Prins	protected $markerPrototypes = array(
86628e43ccSMark Prins			// found at http://www.mapito.net/map-marker-icons.html
87628e43ccSMark Prins			// these are 17x19 px with a pointer at the bottom left
88628e43ccSMark Prins			'lighblue' => array('regex'=>'/^lightblue([0-9]+)$/',
89628e43ccSMark Prins					'extension'=>'.png',
90628e43ccSMark Prins					'shadow'=>false,
91628e43ccSMark Prins					'offsetImage'=>'0,-19',
92628e43ccSMark Prins					'offsetShadow'=>false
93628e43ccSMark Prins			),
94628e43ccSMark Prins			// openlayers std markers are 21x25px with shadow
95628e43ccSMark Prins			'ol-marker'=> array('regex'=>'/^marker(|-blue|-gold|-green|-red)+$/',
96628e43ccSMark Prins					'extension'=>'.png',
97628e43ccSMark Prins					'shadow'=>'marker_shadow.png',
98628e43ccSMark Prins					'offsetImage'=>'-10,-25',
99628e43ccSMark Prins					'offsetShadow'=>'-1,-13'
100628e43ccSMark Prins			),
101628e43ccSMark Prins			// these are 16x16 px
102628e43ccSMark Prins			'ww_icon'=> array('regex'=>'/ww_\S+$/',
103628e43ccSMark Prins					'extension'=>'.png',
104628e43ccSMark Prins					'shadow'=>false,
105628e43ccSMark Prins					'offsetImage'=>'-8,-8',
106628e43ccSMark Prins					'offsetShadow'=>false
107628e43ccSMark Prins			),
108628e43ccSMark Prins			// assume these are 16x16 px
109628e43ccSMark Prins			'rest' => array('regex'=>'/^(?!lightblue([0-9]+)$)(?!(ww_\S+$))(?!marker(|-blue|-gold|-green|-red)+$)(.*)/',
110628e43ccSMark Prins					'extension'=>'.png',
111628e43ccSMark Prins					'shadow'=>'marker_shadow.png',
112628e43ccSMark Prins					'offsetImage'=>'-8,-8',
113628e43ccSMark Prins					'offsetShadow'=>'-1,-1'
114628e43ccSMark Prins			)
115628e43ccSMark Prins	);
116628e43ccSMark Prins	protected $centerX, $centerY, $offsetX, $offsetY, $image;
117628e43ccSMark Prins	protected $zoom, $lat, $lon, $width, $height, $markers, $maptype, $kmlFileName, $gpxFileName;
118628e43ccSMark Prins	protected $tileCacheBaseDir, $mapCacheBaseDir, $mediaBaseDir;
119628e43ccSMark Prins	protected $useTileCache = true;
120628e43ccSMark Prins	protected $mapCacheID = '';
121628e43ccSMark Prins	protected $mapCacheFile = '';
122628e43ccSMark Prins	protected $mapCacheExtension = 'png';
123628e43ccSMark Prins
124628e43ccSMark Prins	/**
125628e43ccSMark Prins	 *
126628e43ccSMark Prins	 * @param number $lat
127628e43ccSMark Prins	 * @param number $lon
128628e43ccSMark Prins	 * @param number $zoom
129628e43ccSMark Prins	 * @param number $width
130628e43ccSMark Prins	 * @param number $height
131628e43ccSMark Prins	 * @param string $maptype
132628e43ccSMark Prins	 * @param mixed $markers
133628e43ccSMark Prins	 * @param string $gpx
134628e43ccSMark Prins	 * @param string $kml
135628e43ccSMark Prins	 * @param string $mediaDir
136628e43ccSMark Prins	 * @param string $tileCacheBaseDir
137628e43ccSMark Prins	 */
138628e43ccSMark Prins	public function __construct($lat,$lon,$zoom,$width,$height,$maptype, $markers,$gpx,$kml,$mediaDir,$tileCacheBaseDir){
139628e43ccSMark Prins		$this->zoom = $zoom;
140628e43ccSMark Prins		$this->lat = $lat;
141628e43ccSMark Prins		$this->lon = $lon;
142628e43ccSMark Prins		$this->width = $width;
143628e43ccSMark Prins		$this->height = $height;
144628e43ccSMark Prins		$this->markers = $markers;
145628e43ccSMark Prins		$this->mediaBaseDir = $mediaDir;
146628e43ccSMark Prins		// validate + set maptype
147628e43ccSMark Prins		$this->maptype = $this->tileDefaultSrc;
148628e43ccSMark Prins		if(array_key_exists($maptype,$this->tileInfo)) {
149628e43ccSMark Prins			$this->maptype = $maptype;
150628e43ccSMark Prins		}
151628e43ccSMark Prins
152628e43ccSMark Prins		$this->tileCacheBaseDir= $tileCacheBaseDir.'/olmaptiles';
153628e43ccSMark Prins		$this->useTileCache = $this->tileCacheBaseDir !=='';
154628e43ccSMark Prins		$this->mapCacheBaseDir = $mediaDir.'/olmapmaps';
155628e43ccSMark Prins
156*da6f229fSMark Prins		$this->kmlFileName = $kml;
157*da6f229fSMark Prins		$this->gpxFileName = $gpx;
158628e43ccSMark Prins	}
159628e43ccSMark Prins
160628e43ccSMark Prins	/**
161628e43ccSMark Prins	 *
162628e43ccSMark Prins	 * @param number $long
163628e43ccSMark Prins	 * @param number $zoom
164628e43ccSMark Prins	 */
165628e43ccSMark Prins	public function lonToTile($long, $zoom){
166628e43ccSMark Prins		return (($long + 180) / 360) * pow(2, $zoom);
167628e43ccSMark Prins	}
168628e43ccSMark Prins	/**
169628e43ccSMark Prins	 *
170628e43ccSMark Prins	 * @param number $lat
171628e43ccSMark Prins	 * @param number $zoom
172628e43ccSMark Prins	 * @return number
173628e43ccSMark Prins	 */
174628e43ccSMark Prins	public function latToTile($lat, $zoom){
175628e43ccSMark Prins		return (1 - log(tan($lat * pi()/180) + 1 / cos($lat* pi()/180)) / pi()) /2 * pow(2, $zoom);
176628e43ccSMark Prins	}
177628e43ccSMark Prins	/**
178628e43ccSMark Prins	 *
179628e43ccSMark Prins	 */
180628e43ccSMark Prins	public function initCoords(){
181628e43ccSMark Prins		$this->centerX = $this->lonToTile($this->lon, $this->zoom);
182628e43ccSMark Prins		$this->centerY = $this->latToTile($this->lat, $this->zoom);
183628e43ccSMark Prins		$this->offsetX = floor((floor($this->centerX)-$this->centerX)*$this->tileSize);
184628e43ccSMark Prins		$this->offsetY = floor((floor($this->centerY)-$this->centerY)*$this->tileSize);
185628e43ccSMark Prins	}
186628e43ccSMark Prins
187628e43ccSMark Prins	/**
188628e43ccSMark Prins	 * make basemap image.
189628e43ccSMark Prins	 */
190628e43ccSMark Prins	public function createBaseMap(){
191628e43ccSMark Prins		$this->image = imagecreatetruecolor($this->width, $this->height);
192628e43ccSMark Prins		$startX = floor($this->centerX-($this->width/$this->tileSize)/2);
193628e43ccSMark Prins		$startY = floor($this->centerY-($this->height/$this->tileSize)/2);
194628e43ccSMark Prins		$endX = ceil($this->centerX+($this->width/$this->tileSize)/2);
195628e43ccSMark Prins		$endY = ceil($this->centerY+($this->height/$this->tileSize)/2);
196628e43ccSMark Prins		$this->offsetX = -floor(($this->centerX-floor($this->centerX))*$this->tileSize);
197628e43ccSMark Prins		$this->offsetY = -floor(($this->centerY-floor($this->centerY))*$this->tileSize);
198628e43ccSMark Prins		$this->offsetX += floor($this->width/2);
199628e43ccSMark Prins		$this->offsetY += floor($this->height/2);
200628e43ccSMark Prins		$this->offsetX += floor($startX-floor($this->centerX))*$this->tileSize;
201628e43ccSMark Prins		$this->offsetY += floor($startY-floor($this->centerY))*$this->tileSize;
202628e43ccSMark Prins
203628e43ccSMark Prins		for($x=$startX; $x<=$endX; $x++){
204628e43ccSMark Prins			for($y=$startY; $y<=$endY; $y++){
205628e43ccSMark Prins				$url = str_replace(array('{Z}','{X}','{Y}'),array($this->zoom, $x, $y), $this->tileInfo[$this->maptype]['url']);
206628e43ccSMark Prins				$tileData = $this->fetchTile($url);
207628e43ccSMark Prins				if($tileData){
208628e43ccSMark Prins					$tileImage = imagecreatefromstring($tileData);
209628e43ccSMark Prins				} else {
210628e43ccSMark Prins					$tileImage = imagecreate($this->tileSize,$this->tileSize);
211628e43ccSMark Prins					$color = imagecolorallocate($tileImage, 255, 255, 255);
212628e43ccSMark Prins					@imagestring($tileImage,1,127,127,'err',$color);
213628e43ccSMark Prins				}
214628e43ccSMark Prins				$destX = ($x-$startX)*$this->tileSize+$this->offsetX;
215628e43ccSMark Prins				$destY = ($y-$startY)*$this->tileSize+$this->offsetY;
216628e43ccSMark Prins				imagecopy($this->image, $tileImage, $destX, $destY, 0, 0, $this->tileSize, $this->tileSize);
217628e43ccSMark Prins			}
218628e43ccSMark Prins		}
219628e43ccSMark Prins	}
220628e43ccSMark Prins
221628e43ccSMark Prins	/**
222628e43ccSMark Prins	 * Place markers on the map and number them in the same order as they are listed in the html.
223628e43ccSMark Prins	 */
224628e43ccSMark Prins	public function placeMarkers(){
225628e43ccSMark Prins		$count=0;
226628e43ccSMark Prins		$color=imagecolorallocate ($this->image,0,0,0 );
227628e43ccSMark Prins		$bgcolor=imagecolorallocate ($this->image,200,200,200 );
228628e43ccSMark Prins		$markerBaseDir = dirname(__FILE__).'/icons';
229628e43ccSMark Prins		// loop thru marker array
230628e43ccSMark Prins		foreach($this->markers as $marker){
231628e43ccSMark Prins			// set some local variables
232628e43ccSMark Prins			$markerLat = $marker['lat'];
233628e43ccSMark Prins			$markerLon = $marker['lon'];
234628e43ccSMark Prins			$markerType = $marker['type'];
235628e43ccSMark Prins			// clear variables from previous loops
236628e43ccSMark Prins			$markerFilename = '';
237628e43ccSMark Prins			$markerShadow = '';
238628e43ccSMark Prins			$matches = false;
239628e43ccSMark Prins			// check for marker type, get settings from markerPrototypes
240628e43ccSMark Prins			if($markerType){
241628e43ccSMark Prins				foreach($this->markerPrototypes as $markerPrototype){
242628e43ccSMark Prins					if(preg_match($markerPrototype['regex'],$markerType,$matches)){
243628e43ccSMark Prins						$markerFilename = $matches[0].$markerPrototype['extension'];
244628e43ccSMark Prins						if($markerPrototype['offsetImage']){
245628e43ccSMark Prins							list($markerImageOffsetX, $markerImageOffsetY)  = split(",",$markerPrototype['offsetImage']);
246628e43ccSMark Prins						}
247628e43ccSMark Prins						$markerShadow = $markerPrototype['shadow'];
248628e43ccSMark Prins						if($markerShadow){
249628e43ccSMark Prins							list($markerShadowOffsetX, $markerShadowOffsetY)  = split(",",$markerPrototype['offsetShadow']);
250628e43ccSMark Prins						}
251628e43ccSMark Prins					}
252628e43ccSMark Prins				}
253628e43ccSMark Prins			}
254628e43ccSMark Prins			// create img resource
255628e43ccSMark Prins			if(file_exists($markerBaseDir.'/'.$markerFilename)){
256628e43ccSMark Prins				$markerImg = imagecreatefrompng($markerBaseDir.'/'.$markerFilename);
257628e43ccSMark Prins			} else {
258628e43ccSMark Prins				$markerImg = imagecreatefrompng($markerBaseDir.'/marker.png');
259628e43ccSMark Prins			}
260628e43ccSMark Prins			// check for shadow + create shadow recource
261628e43ccSMark Prins			if($markerShadow && file_exists($markerBaseDir.'/'.$markerShadow)){
262628e43ccSMark Prins				$markerShadowImg = imagecreatefrompng($markerBaseDir.'/'.$markerShadow);
263628e43ccSMark Prins			}
264628e43ccSMark Prins			// calc position
265628e43ccSMark Prins			$destX = floor(($this->width/2)-$this->tileSize*($this->centerX-$this->lonToTile($markerLon, $this->zoom)));
266628e43ccSMark Prins			$destY = floor(($this->height/2)-$this->tileSize*($this->centerY-$this->latToTile($markerLat, $this->zoom)));
267628e43ccSMark Prins			// copy shadow on basemap
268628e43ccSMark Prins			if($markerShadow && $markerShadowImg){
269628e43ccSMark Prins				imagecopy($this->image, $markerShadowImg, $destX+intval($markerShadowOffsetX), $destY+intval($markerShadowOffsetY),
270628e43ccSMark Prins						0, 0, imagesx($markerShadowImg), imagesy($markerShadowImg));
271628e43ccSMark Prins			}
272628e43ccSMark Prins			// copy marker on basemap above shadow
273628e43ccSMark Prins			imagecopy($this->image, $markerImg, $destX+intval($markerImageOffsetX), $destY+intval($markerImageOffsetY),
274628e43ccSMark Prins					0, 0, imagesx($markerImg), imagesy($markerImg));
275628e43ccSMark Prins			// add label
276628e43ccSMark Prins			imagestring ($this->image , 3 , $destX-imagesx($markerImg)+1 , $destY+intval($markerImageOffsetY)+1 , ++$count , $bgcolor );
277628e43ccSMark Prins			imagestring ($this->image , 3 , $destX-imagesx($markerImg) , $destY+intval($markerImageOffsetY) , $count , $color );
278628e43ccSMark Prins		};
279628e43ccSMark Prins	}
280628e43ccSMark Prins	/**
281628e43ccSMark Prins	 *
282628e43ccSMark Prins	 * @param string $url
283628e43ccSMark Prins	 * @return string
284628e43ccSMark Prins	 */
285628e43ccSMark Prins	public function tileUrlToFilename($url){
286628e43ccSMark Prins		return $this->tileCacheBaseDir."/".str_replace(array('http://'),'',$url);
287628e43ccSMark Prins	}
288628e43ccSMark Prins	/**
289628e43ccSMark Prins	 *
290628e43ccSMark Prins	 * @param string $url
291628e43ccSMark Prins	 */
292628e43ccSMark Prins	public function checkTileCache($url){
293628e43ccSMark Prins		$filename = $this->tileUrlToFilename($url);
294628e43ccSMark Prins		if(file_exists($filename)){
295628e43ccSMark Prins			return file_get_contents($filename);
296628e43ccSMark Prins		}
297628e43ccSMark Prins	}
298628e43ccSMark Prins
299628e43ccSMark Prins	public function checkMapCache(){
300628e43ccSMark Prins		$this->mapCacheID = md5($this->serializeParams());
301628e43ccSMark Prins		$filename = $this->mapCacheIDToFilename();
302628e43ccSMark Prins		if(file_exists($filename)) return true;
303628e43ccSMark Prins	}
304628e43ccSMark Prins
305628e43ccSMark Prins	public function serializeParams(){
306628e43ccSMark Prins		return join("&",array($this->zoom,$this->lat,$this->lon,$this->width,$this->height, serialize($this->markers),$this->maptype));
307628e43ccSMark Prins	}
308628e43ccSMark Prins
309628e43ccSMark Prins	public function mapCacheIDToFilename(){
310628e43ccSMark Prins		if(!$this->mapCacheFile){
311628e43ccSMark Prins			$this->mapCacheFile = $this->mapCacheBaseDir."/".$this->maptype."/".$this->zoom."/cache_".substr($this->mapCacheID,0,2)."/".substr($this->mapCacheID,2,2)."/".substr($this->mapCacheID,4);
312628e43ccSMark Prins		}
313628e43ccSMark Prins		return $this->mapCacheFile.".".$this->mapCacheExtension;
314628e43ccSMark Prins	}
315628e43ccSMark Prins
316628e43ccSMark Prins	public function mkdir_recursive($pathname, $mode){
317628e43ccSMark Prins		is_dir(dirname($pathname)) || $this->mkdir_recursive(dirname($pathname), $mode);
318628e43ccSMark Prins		return is_dir($pathname) || @mkdir($pathname, $mode);
319628e43ccSMark Prins	}
320628e43ccSMark Prins
321628e43ccSMark Prins	public function writeTileToCache($url, $data){
322628e43ccSMark Prins		$filename = $this->tileUrlToFilename($url);
323628e43ccSMark Prins		$this->mkdir_recursive(dirname($filename),0777);
324628e43ccSMark Prins		file_put_contents($filename, $data);
325628e43ccSMark Prins	}
326628e43ccSMark Prins
327628e43ccSMark Prins	public function fetchTile($url){
328628e43ccSMark Prins		if($this->useTileCache && ($cached = $this->checkTileCache($url))) return $cached;
329628e43ccSMark Prins		$ch = curl_init();
330628e43ccSMark Prins		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
331628e43ccSMark Prins		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; DokuWikiSpatial HTTP Client; '.PHP_OS.')');
332628e43ccSMark Prins		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
333628e43ccSMark Prins		curl_setopt($ch, CURLOPT_URL, $url);
334628e43ccSMark Prins		$tile = curl_exec($ch);
335628e43ccSMark Prins		curl_close($ch);
336628e43ccSMark Prins		if($tile && $this->useTileCache){
337628e43ccSMark Prins			$this->writeTileToCache($url,$tile);
338628e43ccSMark Prins		}
339628e43ccSMark Prins		return $tile;
340628e43ccSMark Prins	}
341628e43ccSMark Prins
342628e43ccSMark Prins	/**
343628e43ccSMark Prins	 * Draw gpx trace on the map.
344628e43ccSMark Prins	 */
345628e43ccSMark Prins	public function drawGPX(){
3466c6bb022SMark Prins		$gpxgeom = geoPHP::load(file_get_contents($this->gpxFileName),'gpx');
3476c6bb022SMark Prins		$col = imagecolorallocate($this->image, 0, 0, 255);
3486c6bb022SMark Prins
3496c6bb022SMark Prins		for ($i = 1; $i < $gpxgeom->numGeometries()+1; $i++) {
3506c6bb022SMark Prins			$geom = $gpxgeom->geometryN($i);
3516c6bb022SMark Prins			// can be Point or LineString
3526c6bb022SMark Prins			switch ($geom->geometryType()) {
3536c6bb022SMark Prins				case 'LineString':
354*da6f229fSMark Prins					$this->drawLineString($geom, $col);
3556c6bb022SMark Prins					break;
3566c6bb022SMark Prins				case 'Point':
357*da6f229fSMark Prins					$this->drawPoint($geom, $col);
3586c6bb022SMark Prins					break;
3596c6bb022SMark Prins				default:
3606c6bb022SMark Prins					//do nothing
3616c6bb022SMark Prins					break;
3626c6bb022SMark Prins			}
3636c6bb022SMark Prins		}
364628e43ccSMark Prins	}
365628e43ccSMark Prins
366628e43ccSMark Prins	/**
367628e43ccSMark Prins	 * Draw kml trace on the map.
368628e43ccSMark Prins	 */
369628e43ccSMark Prins	public function drawKML(){
370628e43ccSMark Prins		//TODO implementation
3716c6bb022SMark Prins		$kmlgeom = geoPHP::load(file_get_contents($this->kmlFileName),'kml');
3726c6bb022SMark Prins		// TODO get colour from kml node
373*da6f229fSMark Prins		$col = imagecolorallocate($this->image, 255, 0, 0);
3746c6bb022SMark Prins
375*da6f229fSMark Prins		for ($i = 1; $i < $kmlgeom->numGeometries()+1; $i++) {
376*da6f229fSMark Prins			$geom = $kmlgeom->geometryN($i);
3776c6bb022SMark Prins			switch ($geom->geometryType()) {
3786c6bb022SMark Prins				case 'LineString':
379*da6f229fSMark Prins					$this->drawLineString($geom, $col);
3806c6bb022SMark Prins					break;
3816c6bb022SMark Prins				case 'Point':
382*da6f229fSMark Prins					$this->drawPoint($geom, $col);
3836c6bb022SMark Prins					break;
3846c6bb022SMark Prins				case 'Polygon':
3856c6bb022SMark Prins					break;
3866c6bb022SMark Prins				default:
3876c6bb022SMark Prins					//do nothing
3886c6bb022SMark Prins					break;
3896c6bb022SMark Prins			}
3906c6bb022SMark Prins		}
391628e43ccSMark Prins	}
392628e43ccSMark Prins
393*da6f229fSMark Prins	private function drawLineString($line, $colour){
394*da6f229fSMark Prins		for ($p = 1; $p < $line->numGeometries(); $p++) {
395*da6f229fSMark Prins			// get first pair of points
396*da6f229fSMark Prins			$p1 = $line->geometryN($p);
397*da6f229fSMark Prins			$p2 = $line->geometryN($p+1);
398*da6f229fSMark Prins			// translate to paper space
399*da6f229fSMark Prins			$x1 = floor(($this->width/2)-$this->tileSize*($this->centerX-$this->lonToTile($p1->x(), $this->zoom)));
400*da6f229fSMark Prins			$y1 = floor(($this->height/2)-$this->tileSize*($this->centerY-$this->latToTile($p1->y(), $this->zoom)));
401*da6f229fSMark Prins			$x2 = floor(($this->width/2)-$this->tileSize*($this->centerX-$this->lonToTile($p2->x(), $this->zoom)));
402*da6f229fSMark Prins			$y2 = floor(($this->height/2)-$this->tileSize*($this->centerY-$this->latToTile($p2->y(), $this->zoom)));
403*da6f229fSMark Prins			// draw to image
404*da6f229fSMark Prins			imageline ( $this->image ,  $x1 ,  $y1 ,  $x2 ,  $y2 , $colour );
405*da6f229fSMark Prins		}
406*da6f229fSMark Prins	}
407*da6f229fSMark Prins
408*da6f229fSMark Prins	private function drawPoint($point, $colour){
409*da6f229fSMark Prins		// translate to paper space
410*da6f229fSMark Prins		$cx = floor(($this->width/2)-$this->tileSize*($this->centerX-$this->lonToTile($point->x(), $this->zoom)));
411*da6f229fSMark Prins		$cy = floor(($this->height/2)-$this->tileSize*($this->centerY-$this->latToTile($point->y(), $this->zoom)));
412*da6f229fSMark Prins		// draw to image
413*da6f229fSMark Prins		imageellipse  ( $this->image ,  $cx ,  $cy , 14 /*width*/ , 14 /*height*/ , $colour );
414*da6f229fSMark Prins	}
415*da6f229fSMark Prins
416628e43ccSMark Prins	/**
417628e43ccSMark Prins	 * add copyright and origin notice and icons to the map.
418628e43ccSMark Prins	 */
419628e43ccSMark Prins	public function drawCopyright(){
420628e43ccSMark Prins		$logoBaseDir = dirname(__FILE__).'/'.'logo/';
421628e43ccSMark Prins		$logoImg = imagecreatefrompng($logoBaseDir.$this->tileInfo['openstreetmap']['logo']);
422628e43ccSMark Prins		$textcolor = imagecolorallocate($this->image, 0, 0, 0);
423628e43ccSMark Prins		$bgcolor = imagecolorallocate($this->image, 200, 200, 200);
424628e43ccSMark Prins
425628e43ccSMark Prins		imagecopy($this->image,
426628e43ccSMark Prins				$logoImg,
427628e43ccSMark Prins				0,
428628e43ccSMark Prins				imagesy($this->image)-imagesy($logoImg),
429628e43ccSMark Prins				0,
430628e43ccSMark Prins				0,
431628e43ccSMark Prins				imagesx($logoImg),
432628e43ccSMark Prins				imagesy($logoImg)
433628e43ccSMark Prins		);
434628e43ccSMark Prins		imagestring ($this->image , 1 , imagesx($logoImg)+2 , imagesy($this->image)-imagesy($logoImg)+1 , $this->tileInfo['openstreetmap']['txt'],$bgcolor );
435628e43ccSMark Prins		imagestring ($this->image , 1 , imagesx($logoImg)+1 , imagesy($this->image)-imagesy($logoImg) , $this->tileInfo['openstreetmap']['txt'] ,$textcolor );
436628e43ccSMark Prins
437628e43ccSMark Prins		// additional tile source info, ie. who created/hosted the tiles
438628e43ccSMark Prins		if ($this->maptype!='openstreetmap') {
439628e43ccSMark Prins			$iconImg = imagecreatefrompng($logoBaseDir.$this->tileInfo[$this->maptype]['logo']);
440628e43ccSMark Prins			imagecopy($this->image,
441628e43ccSMark Prins					$iconImg,
442628e43ccSMark Prins					imagesx($logoImg)+1,
443628e43ccSMark Prins					imagesy($this->image)-imagesy($iconImg),
444628e43ccSMark Prins					0,
445628e43ccSMark Prins					0,
446628e43ccSMark Prins					imagesx($iconImg),
447628e43ccSMark Prins					imagesy($iconImg)
448628e43ccSMark Prins			);
449628e43ccSMark Prins			imagestring ($this->image , 1 , imagesx($logoImg)+imagesx($iconImg)+4 , imagesy($this->image)-ceil(imagesy($logoImg)/2)+1 , $this->tileInfo[$this->maptype]['txt'],$bgcolor );
450628e43ccSMark Prins			imagestring ($this->image , 1 , imagesx($logoImg)+imagesx($iconImg)+3 , imagesy($this->image)-ceil(imagesy($logoImg)/2) , $this->tileInfo[$this->maptype]['txt'] ,$textcolor );
451628e43ccSMark Prins		}
452628e43ccSMark Prins	}
453628e43ccSMark Prins	/**
454628e43ccSMark Prins	 * make the map.
455628e43ccSMark Prins	 */
456628e43ccSMark Prins	public function makeMap(){
457628e43ccSMark Prins		$this->initCoords();
458628e43ccSMark Prins		$this->createBaseMap();
459628e43ccSMark Prins		if(count($this->markers))$this->placeMarkers();
460628e43ccSMark Prins		if(file_exists($this->kmlFileName)) $this->drawKML();
461628e43ccSMark Prins		if(file_exists($this->gpxFileName)) $this->drawGPX();
462628e43ccSMark Prins		$this->drawCopyright();
463628e43ccSMark Prins	}
464628e43ccSMark Prins	/**
465628e43ccSMark Prins	 * get the map, this may return a reference to a cached copy.
466628e43ccSMark Prins	 * @return string url relative to media dir
467628e43ccSMark Prins	 */
468628e43ccSMark Prins	public function getMap(){
469628e43ccSMark Prins		// use map cache, so check cache for map
470628e43ccSMark Prins		if(!$this->checkMapCache()){
471628e43ccSMark Prins			// map is not in cache, needs to be build
472628e43ccSMark Prins			$this->makeMap();
473628e43ccSMark Prins			$this->mkdir_recursive(dirname($this->mapCacheIDToFilename()),0777);
474628e43ccSMark Prins			imagepng($this->image,$this->mapCacheIDToFilename(),9);
475628e43ccSMark Prins		}
476628e43ccSMark Prins		$this->doc =$this->mapCacheIDToFilename();
477628e43ccSMark Prins		// make url relative to media dir
478628e43ccSMark Prins		return str_replace($this->mediaBaseDir, '', $this->doc);
479628e43ccSMark Prins	}
480628e43ccSMark Prins}
481