<?
/*
GPX Drawer Class
Version: 1.0
Author: David Boardman
URL: http://www.netzfunk.org/?usr=d
Licenced under Creative Commons Attribution-NonCommercial-ShareAlike 2.5
If redistributed in any form, please include credits and a link to http://www.netzfunk.org/?usr=d
*/
class gpxDrawer{
var $mapname;
var $path;
var $metadata;
var $wpt;
var $rte;
var $trk;
var $trkpt;
var $pixelfact;
var $mapscale;
var $xml;
var $colors;
var $mapwidth;
var $mapheight;
var $area;
var $distance=0;
var $legenda;
var $context;
function gpxDrawer($mapwidth,$mapheight,$mapname,$path,$xml,$scale,$legenda,$context){ // FUNZIONE MAIN
if (!is_numeric($scale) || $scale==0) $scale = 20000;
$this->pixelfact=2817.947378;
$this->mapscale=$scale;
$this->mapname=$mapname;
$this->mapwidth=$mapwidth;
$this->mapheight=$mapheight;
$this->path=$path;
$this->xml=$xml;
$this->legenda=$legenda;
$this->context=$context;
}
function collectMETA(){ // COLLEZIONA METADATA
$meta=$this->xml['gpx']['metadata'];
$this->metadata['filename']=$meta['name']['value'];
$this->metadata['filedesc']=$meta['desc']['value'];
$this->metadata['fileauth']=$meta['author']['name']['value'];
$this->metadata['filelink']=$meta['author']['link']['text']['value'];
$this->metadata['filehref']=$meta['author']['link']['href'];
$this->metadata['copy_year']=$meta['copyright']['year']['value'];
$this->metadata['link_text']=$meta['link']['text']['value'];
$this->metadata['link_href']=$meta['link']['href'];
$this->metadata['time']=$meta['time']['value'];
$this->metadata['keywords']=$meta['keywords']['value'];
$this->metadata['bounds_minlat']=$meta['bounds']['minlat'];
$this->metadata['bounds_maxlat']=$meta['bounds']['maxlat'];
$this->metadata['bounds_minlon']=$meta['bounds']['minlon'];
$this->metadata['bounds_maxlon']=$meta['bounds']['maxlon'];
return $this->metadata;
}
function collectWPT(){ // COLLEZIONA WPT
$i=0;
foreach($this->xml['gpx']['wpt'] as $wpts){
$this->wpt[$i]['ele']=$wpts['ele']['value'];
$this->wpt[$i]['time']=$wpts['time']['value'];
$this->wpt[$i]['magvar']=$wpts['magvar']['value'];
$this->wpt[$i]['geoidheight']=$wpts['geoidheight']['value'];
$this->wpt[$i]['src']=$wpts['src']['value'];
$this->wpt[$i]['link']=$wpts['link']['value'];
$this->wpt[$i]['name']=$wpts['name']['value'];
$this->wpt[$i]['cmt']=$wpts['cmt']['value'];
$this->wpt[$i]['desc']=$wpts['desc']['value'];
$this->wpt[$i]['sym']=$wpts['sym']['value'];
$this->wpt[$i]['lat']=$wpts['lat'];
$this->wpt[$i]['lon']=$wpts['lon'];
$i++;
}
return $this->wpt;
}
function collectRTE(){ // COLLEZIONA RTE
$data=$this->xml['gpx']['rte'];
$this->rte['name']=$data['name']['value'];
$this->rte['desc']=$data['desc']['value'];
$this->rte['gpxcolor']=$data['extensions']['gpx_style:color']['value'];
return $this->rte;
}
function collectTRK(){ // COLLEZIONA TRK
$trklist=$this->xml['gpx']['trk'];
$this->trk['name']=$trklist['name']['value'];
$this->trk['cmt']=$trklist['name']['value'];
$this->trk['desc']=$trklist['desc']['value'];
$this->trk['number']=$trklist['number']['value'];
$this->trk['gpxcolor']=$trklist['extensions']['gpx_style:color']['value'];
return $this->trk;
}
function collectTRKPT(){ // COLLEZIONA TRKPT
$i=0;
foreach($this->xml['gpx']['trk']['trkseg']['trkpt'] as $trkptlist){
//$this->trkpt[$i]['ele']=$trkptlist['ele']['value'];
//$this->trkpt[$i]['time']=$trkptlist['time']['value'];
//$this->trkpt[$i]['magvar']=$trkptlist['magvar']['value'];
//$this->trkpt[$i]['geoidheight']=$trkptlist['geoidheight']['value'];
//$this->trkpt[$i]['name']=$trkptlist['name']['value'];
//$this->trkpt[$i]['cmt']=$trkptlist['cmt']['value'];
//$this->trkpt[$i]['desc']=$trkptlist['desc']['value'];
//$this->trkpt[$i]['sym']=$trkptlist['sym']['value'];
//$this->trkpt[$i]['fix']=$trkptlist['fix']['value'];
//$this->trkpt[$i]['sat']=$trkptlist['sat']['value'];
//$this->trkpt[$i]['hdop']=$trkptlist['hdop']['value'];
//$this->trkpt[$i]['vdop']=$trkptlist['vdop']['value'];
//$this->trkpt[$i]['pdop']=$trkptlist['pdop']['value'];
//$this->trkpt[$i]['dpgpsid']=$trkptlist['dpgpsid']['value'];
$this->trkpt[$i]['lat']=doubleval($trkptlist['lat']);
$this->trkpt[$i]['lon']=doubleval($trkptlist['lon']);
$i++;
}
return $this->trkpt;
}
function getMapCenter(){ // CALCOLA IL CENTRO DELLA MAPPA
$centerlat=$centerlon=$totlat=$totlon=$j=0;
for ($i=0;$i<count($this->trkpt);$i++){
if ($this->trkpt[$i]['lat'] != 0 && $this->trkpt[$i]['lon'] != 0){
$j++;
$totlat+=$this->trkpt[$i]['lat'];
$totlon+=$this->trkpt[$i]['lon'];
}
}
$centerlat=round( $totlat/$j, 6);
$centerlon=round( $totlon/$j, 6);
return array('lat' => $centerlat, 'lon' => $centerlon );
}
function dist($type,$lon1,$lat1,$lon2,$lat2){
$lon1=$lon1*M_PI/180;
$lon2=$lon2*M_PI/180;
$lat1=$lat1*M_PI/180;
$lat2=$lat2*M_PI/180;
$dlon=$lon2-$lon1;
$dlat=$lat2-$lat1;
$a=(sin($dlat/2) * sin($dlat/2)) + cos($lat1) * cos($lat2) * (sin($dlon/2) * sin($dlon/2));
$c=2*atan2(sqrt($a),sqrt(1-$a));
$dlon=$lon2-$lon1;
$dlat=$lat2-$lat1;
$mi=round(3956*$c,4);
$km=round(6367*$c,4);
if($type=="m") return $mi; // return miglia
else return $km; // return chilometri
}
function calcxy($lat, $lon, $pixelfact, $zero_lat, $zero_long){ // CONVERTI LAT/LON IN X/Y
$dif=0;
$px = $py = 0;
$px = ($this->calcRay($lat) * M_PI / 180.0) * cos (M_PI * $lat / 180.0) * ($lon - $zero_long);
$px = ($this->mapwidth/2) + $px / $pixelfact;
$py = ($this->calcRay($lat) * M_PI / 180.0) * ($lat - $zero_lat);
$dif = $this->calcRay($lat) * (1 - (cos ((M_PI * ($lon - $zero_long)) / 180.0)));
$py = $py + $dif / 1.85;
$py = ($this->mapheight/2) - $py / $pixelfact;
$px += $draw_x_offset;
$py += $draw_y_offset;
$px = round($px);
$py = round($py);
$posxy = array('x' => $px, 'y' => $py );
return $posxy;
}
function calcRay($lat){ //calcRay($raggio,$lat,$lon);
$a = 6378.137;
$e2 = 0.081082 * 0.081082;
/*
the radius of curvature of an ellipsoidal Earth in the plane of the
meridian is given by
R' = a * (1 - e^2) / (1 - e^2 * (sin(lat))^2)^(3/2)
where a is the equatorial radius,
b is the polar radius, and
e is the eccentricity of the ellipsoid = sqrt(1 - b^2/a^2)
a = 6378 km (3963 mi) Equatorial radius (surface to center distance)
b = 6356.752 km (3950 mi) Polar radius (surface to center distance)
e = 0.081082 Eccentricity
*/
$lat = $lat * M_PI / 180.0;
$sc = sin ($lat);
$x = $a * (1.0 - $e2);
$z = 1.0 - $e2 * $sc * $sc;
$y = pow ($z, 1.5);
$r = $x / $y;
$r = $r * 1000.0;
return $r;
}
function drawPath($img,$pos){ // DISEGNO TRACKPOINTS (TRKPT)
for($i=0;$i<count($pos);$i++){
if(($pos[$i]['x'] <= $this->mapwidth)&&($pos[$i]['y'] <= $this->mapheight)){
$x1=$pos[$i]['x'];
$y1=$pos[$i]['y'];
if((($x2!="")&&($y2!=""))||(($x2!=0)&&($y2!=0))) imageline($img,$x1,$y1,$x2,$y2,$this->colors['white']);
else imagefilledrectangle($img,$x1-4,$y1-4,$x1+4,$y1+4,$this->colors['green']); //punto iniziale mappa
$x2=$x1;
$y2=$y1;
if($i==count($pos)-1){
imagefilledrectangle($img,$x1-4,$y1-4,$x1+4,$y1+4,$this->colors['blue']); //punto finale mappa
}
}
}
}
function drawPOI($img,$pos,$link,$title,$r){ // (img mappa,x/y,link poi,titolo poi,raggio) DISEGNO WAYPOINTS (WPT)
for($i=0;$i<count($pos);$i++){
if(($pos[$i]['x'] <= $this->mapwidth)&&($pos[$i]['y'] <= $this->mapheight)){
imagefilledellipse($img,$pos[$i]['x'],$pos[$i]['y'],$r[$i],$r[$i],$this->colors['red']);
$this->area.="<area shape=\"circle\" coords=\"".$pos[$i]['x'].",".$pos[$i]['y'].",".$r[$i]."\" href=\"javascript:showPOI('".$link[$i]."');\" onmouseover=\"doTooltip(event,'".htmlspecialchars(strtoupper($title[$i]))."')\" onmouseout=\"hideTip()\">\n";
}
}
}
function drawMap(){ // DISEGNO MAPPA
if(!is_writable($this->path)){
exit("Check permissions on \"".$this->path."\" directory.");
}
$lat1=$lon1=$lat2=$lon2=0;
$map=@imagecreatetruecolor($this->mapwidth,$this->mapheight) or die("Failed to init GD truecolor stream");
//$src_map=@imagecreatefrompng($this->path.$this->mapname.".png") or die("Failed to init GD stream from mapfile");
//imagecopy($map,$src_map,0,0,0,0,$width,$height);
//imagedestroy($src_map);
$this->colors['red']=imagecolorallocate($map,255,0,0);
$this->colors['white']=imagecolorallocate($map, 255, 255, 255);
$this->colors['blue']=imagecolorallocate($map,10,10,255);
$this->colors['green']=imagecolorallocate($map,10,255,10);
$this->colors['black']=imagecolorallocate($map, 0, 0, 0);
$center=$this->getMapCenter();
$mapscalepixfact=$this->mapscale / $this->pixelfact;
for($i=0;$i<count($this->trkpt);$i++){ // TRACKPOINTS
$p[$i]=$this->calcxy($this->trkpt[$i]['lat'],$this->trkpt[$i]['lon'],$mapscalepixfact,$center['lat'],$center['lon']);
//calcolo della distanza percorsa
$lat1=$this->trkpt[$i]['lat'];
$lon1=$this->trkpt[$i]['lon'];
if((($lat2!="")&&($lon2!=""))||(($lat2!=0)&&($lon2!=0))){
$this->distance+=$this->dist("k",$lon1,$lat1,$lon2,$lat2);
}
$lat2=$lat1;
$lon2=$lon1;
}
for($i=0;$i<count($this->wpt);$i++){ // WAYPOINTS
$w[$i]=$this->calcxy($this->wpt[$i]['lat'],$this->wpt[$i]['lon'],$mapscalepixfact,$center['lat'],$center['lon']);
//$l[$i]=$this->wpt[$i]['link'];
$l[$i]=$this->wpt[$i]['desc'];
$t[$i]=$this->wpt[$i]['cmt'];
$ray=explode("|",$this->wpt[$i]['desc']);
$r[$i]=8;
//$r[$i]=$this->calcRay($ray[0],$ray[1],$ray[2]); // calcola raggio WPTS
}
$this->drawPath($map,$p);
$this->drawPOI($map,$w,$l,$t,$r); //(mappa,x/y,link,titolo,raggio)
//$this->insertLegend($map,$this->legenda);
//$this->showMapToBrowser($map);
$this->saveMapAs($map);
}
function insertLegend($map,$pos){ // inserisce riquadro legenda con elementi principali
if(!is_writable($this->path)){
exit("Check permissions on \"".$this->path."\" directory.");
}
$leg=imagecreatefrompng($this->path."/legenda.png");
$legx=imagesx($leg);
$legy=imagesy($leg);
switch($pos){
case "1": // alto-sinistra
$x=10;
$y=10;
break;
case "2": // alto-destra
$x=$this->mapwidth-$legx;
$y=10;
break;
case "3": //basso-sinistra
$x=10;
$y=$this->mapheight-$legy;
break;
case "4": // basso-destra
$x=$this->mapwidth-$legx;
$y=$this->mapheight-$legy;
break;
default:
return;
break;
}
imagecopyresized($map,$leg,$x,$y,0,0,$legx,$legy,$legx,$legy);
}
function getMapArea(){ // RESTITUISCI AREA CLICCABILE MAPPA
return $this->area;
}
function getPathDistance(){ // RESTITUISCI LA DISTANZA PERCORSA
return $this->distance;
}
function outMetaData(){ // RESTITUISCI METATAGS GPX
$m="<pre>".print_r($this->metadata)."</pre>";
return $m;
}
function showMapToBrowser($map){ // MOSTRA MAPPA NEL BROWSER
header("Content-type:image/png");
return imagepng($map);
}
function saveMapAs($map){ // SALVA LA MAPPA
return imagepng($map,$this->path."/map_".$this->mapname.".png");
}
function deleteMap(){ // CANCELLA MAPPA
@unlink($this->path."/map_".$this->mapname.".png");
}
}
?>