xref: /plugin/openlayersmap/StaticMap.php (revision 628e43cc3a6624787a1689fcd4920a44ec800286)
1*628e43ccSMark Prins<?php
2*628e43ccSMark Prins
3*628e43ccSMark Prins/*
4*628e43ccSMark Prins * Copyright (c) 2012 Mark C. Prins <mprins@users.sf.net>
5*628e43ccSMark Prins*
6*628e43ccSMark Prins* Based on staticMapLite 0.03 available at http://staticmaplite.svn.sourceforge.net/viewvc/staticmaplite/
7*628e43ccSMark Prins*
8*628e43ccSMark Prins* Copyright (c) 2009 Gerhard Koch <gerhard.koch AT ymail.com>
9*628e43ccSMark Prins*
10*628e43ccSMark Prins* Licensed under the Apache License, Version 2.0 (the "License");
11*628e43ccSMark Prins* you may not use this file except in compliance with the License.
12*628e43ccSMark Prins* You may obtain a copy of the License at
13*628e43ccSMark Prins*
14*628e43ccSMark Prins*     http://www.apache.org/licenses/LICENSE-2.0
15*628e43ccSMark Prins*
16*628e43ccSMark Prins* Unless required by applicable law or agreed to in writing, software
17*628e43ccSMark Prins* distributed under the License is distributed on an "AS IS" BASIS,
18*628e43ccSMark Prins* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19*628e43ccSMark Prins* See the License for the specific language governing permissions and
20*628e43ccSMark Prins* limitations under the License.
21*628e43ccSMark Prins*/
22*628e43ccSMark Prins
23*628e43ccSMark Prins/**
24*628e43ccSMark Prins * @author Mark C. Prins <mprins@users.sf.net>
25*628e43ccSMark Prins * @author Gerhard Koch <gerhard.koch AT ymail.com>
26*628e43ccSMark Prins *
27*628e43ccSMark Prins * USAGE:
28*628e43ccSMark Prins *
29*628e43ccSMark Prins *  map.php?center=40.714728,-73.998672&zoom=14&size=512x512&maptype=cycle&markers=40.702147,-74.015794,lightblue1|40.711614,-74.012318,lightblue2|40.718217,-73.998284,lightblue3&gpx=&kml=
30*628e43ccSMark Prins*/
31*628e43ccSMark Prinsclass StaticMap {
32*628e43ccSMark Prins	// these should probably not be changed
33*628e43ccSMark Prins	protected $tileSize = 256;
34*628e43ccSMark Prins
35*628e43ccSMark Prins	// the final output
36*628e43ccSMark Prins	var $doc = '';
37*628e43ccSMark Prins
38*628e43ccSMark Prins	protected $tileInfo = array(
39*628e43ccSMark Prins			// OSM sources
40*628e43ccSMark Prins			'openstreetmap'=>array(
41*628e43ccSMark Prins					'txt'=>'(c) OpenStreetMap CC-BY-SA',
42*628e43ccSMark Prins					'logo'=>'osm_logo.png',
43*628e43ccSMark Prins					'url'=>'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png'),
44*628e43ccSMark Prins			// cloudmade
45*628e43ccSMark Prins			'cloudmade' =>array(
46*628e43ccSMark Prins					'txt'=>'CloudMade tiles',
47*628e43ccSMark Prins					'logo'=>'cloudmade_logo.png',
48*628e43ccSMark Prins					'url'=> 'http://tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/2/256/{Z}/{X}/{Y}.png'),
49*628e43ccSMark Prins			'fresh' =>array(
50*628e43ccSMark Prins					'txt'=>'CloudMade tiles',
51*628e43ccSMark Prins					'logo'=>'cloudmade_logo.png',
52*628e43ccSMark Prins					'url'=> 'http://tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{Z}/{X}/{Y}.png'),
53*628e43ccSMark Prins			// OCM sources
54*628e43ccSMark Prins			'cycle'=>array(
55*628e43ccSMark Prins					'txt'=>'OpenCycleMap tiles',
56*628e43ccSMark Prins					'logo'=>'cycle_logo.png',
57*628e43ccSMark Prins					'url'=>'http://tile.opencyclemap.org/cycle/{Z}/{X}/{Y}.png'),
58*628e43ccSMark Prins			'transport'=>array(
59*628e43ccSMark Prins					'txt'=>'OpenCycleMap tiles',
60*628e43ccSMark Prins					'logo'=>'cycle_logo.png',
61*628e43ccSMark Prins					'url'=>'http://tile2.opencyclemap.org/transport/{Z}/{X}/{Y}.png'),
62*628e43ccSMark Prins			'landscape'=>array(
63*628e43ccSMark Prins					'txt'=>'OpenCycleMap tiles',
64*628e43ccSMark Prins					'logo'=>'cycle_logo.png',
65*628e43ccSMark Prins					'url'=>'http://tile3.opencyclemap.org/landscape/{Z}/{X}/{Y}.png'),
66*628e43ccSMark Prins			// H&B sources
67*628e43ccSMark Prins			'hikeandbike'=>array(
68*628e43ccSMark Prins					'txt'=>'Hike & Bike Map',
69*628e43ccSMark Prins					'logo'=>'hnb_logo.png',
70*628e43ccSMark Prins					'url'=>'http://toolserver.org/tiles/hikebike/{Z}/{X}/{Y}.png'),
71*628e43ccSMark Prins			//'piste'=>array(
72*628e43ccSMark Prins			//		'txt'=>'OpenPisteMap tiles',
73*628e43ccSMark Prins			//		'logo'=>'piste_logo.png',
74*628e43ccSMark Prins			//		'url'=>''),
75*628e43ccSMark Prins			//'sea'=>array(
76*628e43ccSMark Prins			//		'txt'=>'OpenSeaMap tiles',
77*628e43ccSMark Prins			//		'logo'=>'sea_logo.png',
78*628e43ccSMark Prins			//		'url'=>''),
79*628e43ccSMark Prins			// MapQuest
80*628e43ccSMark Prins			'mapquest'=>array(
81*628e43ccSMark Prins					'txt'=>'MapQuest tiles',
82*628e43ccSMark Prins					'logo'=>'mq_logo.png',
83*628e43ccSMark Prins					'url'=>'http://otile3.mqcdn.com/tiles/1.0.0/osm/{Z}/{X}/{Y}.png')
84*628e43ccSMark Prins	);
85*628e43ccSMark Prins	protected $tileDefaultSrc = 'openstreetmap';
86*628e43ccSMark Prins
87*628e43ccSMark Prins	// set up markers
88*628e43ccSMark Prins	protected $markerPrototypes = array(
89*628e43ccSMark Prins			// found at http://www.mapito.net/map-marker-icons.html
90*628e43ccSMark Prins			// these are 17x19 px with a pointer at the bottom left
91*628e43ccSMark Prins			'lighblue' => array('regex'=>'/^lightblue([0-9]+)$/',
92*628e43ccSMark Prins					'extension'=>'.png',
93*628e43ccSMark Prins					'shadow'=>false,
94*628e43ccSMark Prins					'offsetImage'=>'0,-19',
95*628e43ccSMark Prins					'offsetShadow'=>false
96*628e43ccSMark Prins			),
97*628e43ccSMark Prins			// openlayers std markers are 21x25px with shadow
98*628e43ccSMark Prins			'ol-marker'=> array('regex'=>'/^marker(|-blue|-gold|-green|-red)+$/',
99*628e43ccSMark Prins					'extension'=>'.png',
100*628e43ccSMark Prins					'shadow'=>'marker_shadow.png',
101*628e43ccSMark Prins					'offsetImage'=>'-10,-25',
102*628e43ccSMark Prins					'offsetShadow'=>'-1,-13'
103*628e43ccSMark Prins			),
104*628e43ccSMark Prins			// these are 16x16 px
105*628e43ccSMark Prins			'ww_icon'=> array('regex'=>'/ww_\S+$/',
106*628e43ccSMark Prins					'extension'=>'.png',
107*628e43ccSMark Prins					'shadow'=>false,
108*628e43ccSMark Prins					'offsetImage'=>'-8,-8',
109*628e43ccSMark Prins					'offsetShadow'=>false
110*628e43ccSMark Prins			),
111*628e43ccSMark Prins			// assume these are 16x16 px
112*628e43ccSMark Prins			'rest' => array('regex'=>'/^(?!lightblue([0-9]+)$)(?!(ww_\S+$))(?!marker(|-blue|-gold|-green|-red)+$)(.*)/',
113*628e43ccSMark Prins					'extension'=>'.png',
114*628e43ccSMark Prins					'shadow'=>'marker_shadow.png',
115*628e43ccSMark Prins					'offsetImage'=>'-8,-8',
116*628e43ccSMark Prins					'offsetShadow'=>'-1,-1'
117*628e43ccSMark Prins			)
118*628e43ccSMark Prins	);
119*628e43ccSMark Prins	protected $centerX, $centerY, $offsetX, $offsetY, $image;
120*628e43ccSMark Prins	protected $zoom, $lat, $lon, $width, $height, $markers, $maptype, $kmlFileName, $gpxFileName;
121*628e43ccSMark Prins	protected $tileCacheBaseDir, $mapCacheBaseDir, $mediaBaseDir;
122*628e43ccSMark Prins	protected $useTileCache = true;
123*628e43ccSMark Prins	protected $mapCacheID = '';
124*628e43ccSMark Prins	protected $mapCacheFile = '';
125*628e43ccSMark Prins	protected $mapCacheExtension = 'png';
126*628e43ccSMark Prins
127*628e43ccSMark Prins	/**
128*628e43ccSMark Prins	 *
129*628e43ccSMark Prins	 * @param number $lat
130*628e43ccSMark Prins	 * @param number $lon
131*628e43ccSMark Prins	 * @param number $zoom
132*628e43ccSMark Prins	 * @param number $width
133*628e43ccSMark Prins	 * @param number $height
134*628e43ccSMark Prins	 * @param string $maptype
135*628e43ccSMark Prins	 * @param mixed $markers
136*628e43ccSMark Prins	 * @param string $gpx
137*628e43ccSMark Prins	 * @param string $kml
138*628e43ccSMark Prins	 * @param string $mediaDir
139*628e43ccSMark Prins	 * @param string $tileCacheBaseDir
140*628e43ccSMark Prins	 */
141*628e43ccSMark Prins	public function __construct($lat,$lon,$zoom,$width,$height,$maptype, $markers,$gpx,$kml,$mediaDir,$tileCacheBaseDir){
142*628e43ccSMark Prins		$this->zoom = $zoom;
143*628e43ccSMark Prins		$this->lat = $lat;
144*628e43ccSMark Prins		$this->lon = $lon;
145*628e43ccSMark Prins		$this->width = $width;
146*628e43ccSMark Prins		$this->height = $height;
147*628e43ccSMark Prins		$this->markers = $markers;
148*628e43ccSMark Prins		$this->mediaBaseDir = $mediaDir;
149*628e43ccSMark Prins		// validate + set maptype
150*628e43ccSMark Prins		$this->maptype = $this->tileDefaultSrc;
151*628e43ccSMark Prins		if(array_key_exists($maptype,$this->tileInfo)) {
152*628e43ccSMark Prins			$this->maptype = $maptype;
153*628e43ccSMark Prins		}
154*628e43ccSMark Prins
155*628e43ccSMark Prins		$this->tileCacheBaseDir= $tileCacheBaseDir.'/olmaptiles';
156*628e43ccSMark Prins		$this->useTileCache = $this->tileCacheBaseDir !=='';
157*628e43ccSMark Prins		$this->mapCacheBaseDir = $mediaDir.'/olmapmaps';
158*628e43ccSMark Prins
159*628e43ccSMark Prins		$this->kmlFileName = $this->mediaBaseDir.str_replace(":","/",$kml);
160*628e43ccSMark Prins		$this->gpxFileName = $this->mediaBaseDir.str_replace(":","/",$gpx);
161*628e43ccSMark Prins	}
162*628e43ccSMark Prins
163*628e43ccSMark Prins	/**
164*628e43ccSMark Prins	 *
165*628e43ccSMark Prins	 * @param number $long
166*628e43ccSMark Prins	 * @param number $zoom
167*628e43ccSMark Prins	 */
168*628e43ccSMark Prins	public function lonToTile($long, $zoom){
169*628e43ccSMark Prins		return (($long + 180) / 360) * pow(2, $zoom);
170*628e43ccSMark Prins	}
171*628e43ccSMark Prins	/**
172*628e43ccSMark Prins	 *
173*628e43ccSMark Prins	 * @param number $lat
174*628e43ccSMark Prins	 * @param number $zoom
175*628e43ccSMark Prins	 * @return number
176*628e43ccSMark Prins	 */
177*628e43ccSMark Prins	public function latToTile($lat, $zoom){
178*628e43ccSMark Prins		return (1 - log(tan($lat * pi()/180) + 1 / cos($lat* pi()/180)) / pi()) /2 * pow(2, $zoom);
179*628e43ccSMark Prins	}
180*628e43ccSMark Prins	/**
181*628e43ccSMark Prins	 *
182*628e43ccSMark Prins	 */
183*628e43ccSMark Prins	public function initCoords(){
184*628e43ccSMark Prins		$this->centerX = $this->lonToTile($this->lon, $this->zoom);
185*628e43ccSMark Prins		$this->centerY = $this->latToTile($this->lat, $this->zoom);
186*628e43ccSMark Prins		$this->offsetX = floor((floor($this->centerX)-$this->centerX)*$this->tileSize);
187*628e43ccSMark Prins		$this->offsetY = floor((floor($this->centerY)-$this->centerY)*$this->tileSize);
188*628e43ccSMark Prins	}
189*628e43ccSMark Prins
190*628e43ccSMark Prins	/**
191*628e43ccSMark Prins	 * make basemap image.
192*628e43ccSMark Prins	 */
193*628e43ccSMark Prins	public function createBaseMap(){
194*628e43ccSMark Prins		$this->image = imagecreatetruecolor($this->width, $this->height);
195*628e43ccSMark Prins		$startX = floor($this->centerX-($this->width/$this->tileSize)/2);
196*628e43ccSMark Prins		$startY = floor($this->centerY-($this->height/$this->tileSize)/2);
197*628e43ccSMark Prins		$endX = ceil($this->centerX+($this->width/$this->tileSize)/2);
198*628e43ccSMark Prins		$endY = ceil($this->centerY+($this->height/$this->tileSize)/2);
199*628e43ccSMark Prins		$this->offsetX = -floor(($this->centerX-floor($this->centerX))*$this->tileSize);
200*628e43ccSMark Prins		$this->offsetY = -floor(($this->centerY-floor($this->centerY))*$this->tileSize);
201*628e43ccSMark Prins		$this->offsetX += floor($this->width/2);
202*628e43ccSMark Prins		$this->offsetY += floor($this->height/2);
203*628e43ccSMark Prins		$this->offsetX += floor($startX-floor($this->centerX))*$this->tileSize;
204*628e43ccSMark Prins		$this->offsetY += floor($startY-floor($this->centerY))*$this->tileSize;
205*628e43ccSMark Prins
206*628e43ccSMark Prins		for($x=$startX; $x<=$endX; $x++){
207*628e43ccSMark Prins			for($y=$startY; $y<=$endY; $y++){
208*628e43ccSMark Prins				$url = str_replace(array('{Z}','{X}','{Y}'),array($this->zoom, $x, $y), $this->tileInfo[$this->maptype]['url']);
209*628e43ccSMark Prins				$tileData = $this->fetchTile($url);
210*628e43ccSMark Prins				if($tileData){
211*628e43ccSMark Prins					$tileImage = imagecreatefromstring($tileData);
212*628e43ccSMark Prins				} else {
213*628e43ccSMark Prins					$tileImage = imagecreate($this->tileSize,$this->tileSize);
214*628e43ccSMark Prins					$color = imagecolorallocate($tileImage, 255, 255, 255);
215*628e43ccSMark Prins					@imagestring($tileImage,1,127,127,'err',$color);
216*628e43ccSMark Prins				}
217*628e43ccSMark Prins				$destX = ($x-$startX)*$this->tileSize+$this->offsetX;
218*628e43ccSMark Prins				$destY = ($y-$startY)*$this->tileSize+$this->offsetY;
219*628e43ccSMark Prins				imagecopy($this->image, $tileImage, $destX, $destY, 0, 0, $this->tileSize, $this->tileSize);
220*628e43ccSMark Prins			}
221*628e43ccSMark Prins		}
222*628e43ccSMark Prins	}
223*628e43ccSMark Prins
224*628e43ccSMark Prins	/**
225*628e43ccSMark Prins	 * Place markers on the map and number them in the same order as they are listed in the html.
226*628e43ccSMark Prins	 */
227*628e43ccSMark Prins	public function placeMarkers(){
228*628e43ccSMark Prins		$count=0;
229*628e43ccSMark Prins		$color=imagecolorallocate ($this->image,0,0,0 );
230*628e43ccSMark Prins		$bgcolor=imagecolorallocate ($this->image,200,200,200 );
231*628e43ccSMark Prins		$markerBaseDir = dirname(__FILE__).'/icons';
232*628e43ccSMark Prins		// loop thru marker array
233*628e43ccSMark Prins		foreach($this->markers as $marker){
234*628e43ccSMark Prins			// set some local variables
235*628e43ccSMark Prins			$markerLat = $marker['lat'];
236*628e43ccSMark Prins			$markerLon = $marker['lon'];
237*628e43ccSMark Prins			$markerType = $marker['type'];
238*628e43ccSMark Prins			// clear variables from previous loops
239*628e43ccSMark Prins			$markerFilename = '';
240*628e43ccSMark Prins			$markerShadow = '';
241*628e43ccSMark Prins			$matches = false;
242*628e43ccSMark Prins			// check for marker type, get settings from markerPrototypes
243*628e43ccSMark Prins			if($markerType){
244*628e43ccSMark Prins				foreach($this->markerPrototypes as $markerPrototype){
245*628e43ccSMark Prins					if(preg_match($markerPrototype['regex'],$markerType,$matches)){
246*628e43ccSMark Prins						$markerFilename = $matches[0].$markerPrototype['extension'];
247*628e43ccSMark Prins						if($markerPrototype['offsetImage']){
248*628e43ccSMark Prins							list($markerImageOffsetX, $markerImageOffsetY)  = split(",",$markerPrototype['offsetImage']);
249*628e43ccSMark Prins						}
250*628e43ccSMark Prins						$markerShadow = $markerPrototype['shadow'];
251*628e43ccSMark Prins						if($markerShadow){
252*628e43ccSMark Prins							list($markerShadowOffsetX, $markerShadowOffsetY)  = split(",",$markerPrototype['offsetShadow']);
253*628e43ccSMark Prins						}
254*628e43ccSMark Prins					}
255*628e43ccSMark Prins				}
256*628e43ccSMark Prins			}
257*628e43ccSMark Prins			// create img resource
258*628e43ccSMark Prins			if(file_exists($markerBaseDir.'/'.$markerFilename)){
259*628e43ccSMark Prins				$markerImg = imagecreatefrompng($markerBaseDir.'/'.$markerFilename);
260*628e43ccSMark Prins			} else {
261*628e43ccSMark Prins				$markerImg = imagecreatefrompng($markerBaseDir.'/marker.png');
262*628e43ccSMark Prins			}
263*628e43ccSMark Prins			// check for shadow + create shadow recource
264*628e43ccSMark Prins			if($markerShadow && file_exists($markerBaseDir.'/'.$markerShadow)){
265*628e43ccSMark Prins				$markerShadowImg = imagecreatefrompng($markerBaseDir.'/'.$markerShadow);
266*628e43ccSMark Prins			}
267*628e43ccSMark Prins			// calc position
268*628e43ccSMark Prins			$destX = floor(($this->width/2)-$this->tileSize*($this->centerX-$this->lonToTile($markerLon, $this->zoom)));
269*628e43ccSMark Prins			$destY = floor(($this->height/2)-$this->tileSize*($this->centerY-$this->latToTile($markerLat, $this->zoom)));
270*628e43ccSMark Prins			// copy shadow on basemap
271*628e43ccSMark Prins			if($markerShadow && $markerShadowImg){
272*628e43ccSMark Prins				imagecopy($this->image, $markerShadowImg, $destX+intval($markerShadowOffsetX), $destY+intval($markerShadowOffsetY),
273*628e43ccSMark Prins						0, 0, imagesx($markerShadowImg), imagesy($markerShadowImg));
274*628e43ccSMark Prins			}
275*628e43ccSMark Prins			// copy marker on basemap above shadow
276*628e43ccSMark Prins			imagecopy($this->image, $markerImg, $destX+intval($markerImageOffsetX), $destY+intval($markerImageOffsetY),
277*628e43ccSMark Prins					0, 0, imagesx($markerImg), imagesy($markerImg));
278*628e43ccSMark Prins			// add label
279*628e43ccSMark Prins			imagestring ($this->image , 3 , $destX-imagesx($markerImg)+1 , $destY+intval($markerImageOffsetY)+1 , ++$count , $bgcolor );
280*628e43ccSMark Prins			imagestring ($this->image , 3 , $destX-imagesx($markerImg) , $destY+intval($markerImageOffsetY) , $count , $color );
281*628e43ccSMark Prins		};
282*628e43ccSMark Prins	}
283*628e43ccSMark Prins	/**
284*628e43ccSMark Prins	 *
285*628e43ccSMark Prins	 * @param string $url
286*628e43ccSMark Prins	 * @return string
287*628e43ccSMark Prins	 */
288*628e43ccSMark Prins	public function tileUrlToFilename($url){
289*628e43ccSMark Prins		return $this->tileCacheBaseDir."/".str_replace(array('http://'),'',$url);
290*628e43ccSMark Prins	}
291*628e43ccSMark Prins	/**
292*628e43ccSMark Prins	 *
293*628e43ccSMark Prins	 * @param string $url
294*628e43ccSMark Prins	 */
295*628e43ccSMark Prins	public function checkTileCache($url){
296*628e43ccSMark Prins		$filename = $this->tileUrlToFilename($url);
297*628e43ccSMark Prins		if(file_exists($filename)){
298*628e43ccSMark Prins			return file_get_contents($filename);
299*628e43ccSMark Prins		}
300*628e43ccSMark Prins	}
301*628e43ccSMark Prins
302*628e43ccSMark Prins	public function checkMapCache(){
303*628e43ccSMark Prins		$this->mapCacheID = md5($this->serializeParams());
304*628e43ccSMark Prins		$filename = $this->mapCacheIDToFilename();
305*628e43ccSMark Prins		if(file_exists($filename)) return true;
306*628e43ccSMark Prins	}
307*628e43ccSMark Prins
308*628e43ccSMark Prins	public function serializeParams(){
309*628e43ccSMark Prins		return join("&",array($this->zoom,$this->lat,$this->lon,$this->width,$this->height, serialize($this->markers),$this->maptype));
310*628e43ccSMark Prins	}
311*628e43ccSMark Prins
312*628e43ccSMark Prins	public function mapCacheIDToFilename(){
313*628e43ccSMark Prins		if(!$this->mapCacheFile){
314*628e43ccSMark Prins			$this->mapCacheFile = $this->mapCacheBaseDir."/".$this->maptype."/".$this->zoom."/cache_".substr($this->mapCacheID,0,2)."/".substr($this->mapCacheID,2,2)."/".substr($this->mapCacheID,4);
315*628e43ccSMark Prins		}
316*628e43ccSMark Prins		return $this->mapCacheFile.".".$this->mapCacheExtension;
317*628e43ccSMark Prins	}
318*628e43ccSMark Prins
319*628e43ccSMark Prins	public function mkdir_recursive($pathname, $mode){
320*628e43ccSMark Prins		is_dir(dirname($pathname)) || $this->mkdir_recursive(dirname($pathname), $mode);
321*628e43ccSMark Prins		return is_dir($pathname) || @mkdir($pathname, $mode);
322*628e43ccSMark Prins	}
323*628e43ccSMark Prins
324*628e43ccSMark Prins	public function writeTileToCache($url, $data){
325*628e43ccSMark Prins		$filename = $this->tileUrlToFilename($url);
326*628e43ccSMark Prins		$this->mkdir_recursive(dirname($filename),0777);
327*628e43ccSMark Prins		file_put_contents($filename, $data);
328*628e43ccSMark Prins	}
329*628e43ccSMark Prins
330*628e43ccSMark Prins	public function fetchTile($url){
331*628e43ccSMark Prins		if($this->useTileCache && ($cached = $this->checkTileCache($url))) return $cached;
332*628e43ccSMark Prins		$ch = curl_init();
333*628e43ccSMark Prins		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
334*628e43ccSMark Prins		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; DokuWikiSpatial HTTP Client; '.PHP_OS.')');
335*628e43ccSMark Prins		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
336*628e43ccSMark Prins		curl_setopt($ch, CURLOPT_URL, $url);
337*628e43ccSMark Prins		$tile = curl_exec($ch);
338*628e43ccSMark Prins		curl_close($ch);
339*628e43ccSMark Prins		if($tile && $this->useTileCache){
340*628e43ccSMark Prins			$this->writeTileToCache($url,$tile);
341*628e43ccSMark Prins		}
342*628e43ccSMark Prins		return $tile;
343*628e43ccSMark Prins	}
344*628e43ccSMark Prins
345*628e43ccSMark Prins	/**
346*628e43ccSMark Prins	 * Draw gpx trace on the map.
347*628e43ccSMark Prins	 */
348*628e43ccSMark Prins	public function drawGPX(){
349*628e43ccSMark Prins		//TODO implementation
350*628e43ccSMark Prins		//determine bbox gpx
351*628e43ccSMark Prins	}
352*628e43ccSMark Prins
353*628e43ccSMark Prins	/**
354*628e43ccSMark Prins	 * Draw kml trace on the map.
355*628e43ccSMark Prins	 */
356*628e43ccSMark Prins	public function drawKML(){
357*628e43ccSMark Prins		//TODO implementation
358*628e43ccSMark Prins	}
359*628e43ccSMark Prins
360*628e43ccSMark Prins	/**
361*628e43ccSMark Prins	 * add copyright and origin notice and icons to the map.
362*628e43ccSMark Prins	 */
363*628e43ccSMark Prins	public function drawCopyright(){
364*628e43ccSMark Prins		$logoBaseDir = dirname(__FILE__).'/'.'logo/';
365*628e43ccSMark Prins		$logoImg = imagecreatefrompng($logoBaseDir.$this->tileInfo['openstreetmap']['logo']);
366*628e43ccSMark Prins		$textcolor = imagecolorallocate($this->image, 0, 0, 0);
367*628e43ccSMark Prins		$bgcolor = imagecolorallocate($this->image, 200, 200, 200);
368*628e43ccSMark Prins
369*628e43ccSMark Prins		imagecopy($this->image,
370*628e43ccSMark Prins				$logoImg,
371*628e43ccSMark Prins				0,
372*628e43ccSMark Prins				imagesy($this->image)-imagesy($logoImg),
373*628e43ccSMark Prins				0,
374*628e43ccSMark Prins				0,
375*628e43ccSMark Prins				imagesx($logoImg),
376*628e43ccSMark Prins				imagesy($logoImg)
377*628e43ccSMark Prins		);
378*628e43ccSMark Prins		imagestring ($this->image , 1 , imagesx($logoImg)+2 , imagesy($this->image)-imagesy($logoImg)+1 , $this->tileInfo['openstreetmap']['txt'],$bgcolor );
379*628e43ccSMark Prins		imagestring ($this->image , 1 , imagesx($logoImg)+1 , imagesy($this->image)-imagesy($logoImg) , $this->tileInfo['openstreetmap']['txt'] ,$textcolor );
380*628e43ccSMark Prins
381*628e43ccSMark Prins		// additional tile source info, ie. who created/hosted the tiles
382*628e43ccSMark Prins		if ($this->maptype!='openstreetmap') {
383*628e43ccSMark Prins			$iconImg = imagecreatefrompng($logoBaseDir.$this->tileInfo[$this->maptype]['logo']);
384*628e43ccSMark Prins			imagecopy($this->image,
385*628e43ccSMark Prins					$iconImg,
386*628e43ccSMark Prins					imagesx($logoImg)+1,
387*628e43ccSMark Prins					imagesy($this->image)-imagesy($iconImg),
388*628e43ccSMark Prins					0,
389*628e43ccSMark Prins					0,
390*628e43ccSMark Prins					imagesx($iconImg),
391*628e43ccSMark Prins					imagesy($iconImg)
392*628e43ccSMark Prins			);
393*628e43ccSMark Prins			imagestring ($this->image , 1 , imagesx($logoImg)+imagesx($iconImg)+4 , imagesy($this->image)-ceil(imagesy($logoImg)/2)+1 , $this->tileInfo[$this->maptype]['txt'],$bgcolor );
394*628e43ccSMark Prins			imagestring ($this->image , 1 , imagesx($logoImg)+imagesx($iconImg)+3 , imagesy($this->image)-ceil(imagesy($logoImg)/2) , $this->tileInfo[$this->maptype]['txt'] ,$textcolor );
395*628e43ccSMark Prins		}
396*628e43ccSMark Prins	}
397*628e43ccSMark Prins	/**
398*628e43ccSMark Prins	 * make the map.
399*628e43ccSMark Prins	 */
400*628e43ccSMark Prins	public function makeMap(){
401*628e43ccSMark Prins		$this->initCoords();
402*628e43ccSMark Prins		$this->createBaseMap();
403*628e43ccSMark Prins		if(count($this->markers))$this->placeMarkers();
404*628e43ccSMark Prins		if(file_exists($this->kmlFileName)) $this->drawKML();
405*628e43ccSMark Prins		if(file_exists($this->gpxFileName)) $this->drawGPX();
406*628e43ccSMark Prins		$this->drawCopyright();
407*628e43ccSMark Prins	}
408*628e43ccSMark Prins	/**
409*628e43ccSMark Prins	 * get the map, this may return a reference to a cached copy.
410*628e43ccSMark Prins	 * @return string url relative to media dir
411*628e43ccSMark Prins	 */
412*628e43ccSMark Prins	public function getMap(){
413*628e43ccSMark Prins		// use map cache, so check cache for map
414*628e43ccSMark Prins		if(!$this->checkMapCache()){
415*628e43ccSMark Prins			// map is not in cache, needs to be build
416*628e43ccSMark Prins			$this->makeMap();
417*628e43ccSMark Prins			$this->mkdir_recursive(dirname($this->mapCacheIDToFilename()),0777);
418*628e43ccSMark Prins			imagepng($this->image,$this->mapCacheIDToFilename(),9);
419*628e43ccSMark Prins		}
420*628e43ccSMark Prins		$this->doc =$this->mapCacheIDToFilename();
421*628e43ccSMark Prins		// make url relative to media dir
422*628e43ccSMark Prins		return str_replace($this->mediaBaseDir, '', $this->doc);
423*628e43ccSMark Prins	}
424*628e43ccSMark Prins}
425