Location: PHPKode > projects > Keepright > keepright/web/helpers.inc.php
<?php

// calculate the minimum distance of point P to a line built from A and B
function distance_point_segment($Px, $Py, $Ax, $Ay, $Bx, $By) {
/*
                 P
                *
             /  |
       AP /     |
       /        | d
    /  alfa     |
  *---------------------------------------*
  A                  AB                   B

given:	straight line vom A to B 
	Point P


    ( Px - Ax )
AP= (         )
    ( Py - Ay )


    ( Bx - Ax )
AB= (         )
    ( By - Ay )


equation for straight line: X = A + AB * k
where k is scalar. 
k==0 leads to X==A
k==1 leads to X==B

find the one k where distance from P to X becomes a minimum

PX = | P - A - AB * k|

|PX|² = [Px - Ax - (Bx-Ax)k]² + [Py - Ay - (By-Ay)k]²

d(|PX|²) / dk = 0
leads to
    (Px-Ax)(Bx-Ax) + (Py-Ay)(By-Ay)
k = --------------------------------
          (Bx-Ax)² + (By-Ay)²
*/

	//printf("P(%01.2f, %01.2f) A(%01.2f, %01.2f) B(%01.2f, %01.2f)\n", $Px, $Py, $Ax, $Ay, $Bx, $By);

	$denominator = pow($Bx-$Ax,2) + pow($By-$Ay,2);
	
	// denominator may be zero if A==B. return the distance from P to A in this case
	if ($denominator==0) {
		return sqrt( pow($Px-$Ax,2) + pow($Py-$Ay,2) );
	} else {
		$k = (($Px-$Ax)*($Bx-$Ax) + ($Py-$Ay)*($By-$Ay)) / $denominator;
		//echo "k=$k ";

		// cut off k at 0/1 because only points between A and B are valid
		if ($k<0) $k=0;
		if ($k>1) $k=1;
		$Xx=$Ax + ($Bx-$Ax)*$k;		// X is the one point on the line that is nearest to P
		$Xy=$Ay + ($By-$Ay)*$k;
		return sqrt( pow($Px-$Xx,2) + pow($Py-$Xy,2) );		// distance PX
	}
}	



function tile_for_xy($ix, $yps) {
	$t=0;
	$mask=1;
	$adder=1;
	$x=1*$ix;
	$y=1*$yps;
	//echo "\t$x\t$y";
	for ($i=0; $i<16; $i++) {
		if ($y & $mask) $t += $adder;
		$adder*=2;
	
		if ($x & $mask) $t += $adder;
		$mask*=2;
		$adder*=2;
	}

	return $t;
}
function xy_for_tile($tile) {
	$x=0; 
	$y=0;
	$mask=1;
	$adder=1;
	$t=1*$tile;

	for ($i=0; $i<16; $i++) {
		if ($t & $mask) $y += $adder;
		$mask*=2;
	
		if ($t & $mask) $x += $adder;
		$mask*=2;
		$adder*=2;
	}
	return array('x'=>$x, 'y'=>$y);
}

function lon2x($lon) {
	return round(($lon + 180 ) * 65535 / 360);
}

function lat2y($lat) {
	return round(($lat + 90) * 65535 / 180);
}

function x2lon($x) {
	return ($x*360/65535) - 180;
}

function y2lat($y) {
	return ($y*180/65535)-90;
}


// execute $sql using database link $link
// echo debug messages if $debug is set
function query($sql, $link, $debug=true) {
	if ($debug) {
		echo "\n\n" . rtrim(preg_replace('/(\s)\s+/', '$1', $sql)) . "\n";
		$starttime=microtime(true);
	}
	//$result=mysql_unbuffered_query($sql, $link);
	$result=mysqli_query($link, $sql, MYSQLI_USE_RESULT);
	if (!$result) {
		$message  = 'Invalid query: ' . mysqli_errno($link) . ": " . mysqli_error($link) . "\n";
		$message .= 'Whole query: ' . $sql . "\n";
		$message .= 'Query result: ' . $result . "\n";
		echo($message);
	}
	if ($debug) echo format_time(microtime(true)-$starttime) ."\n";
	return $result;
}



/*
http://wiki.openstreetmap.org/index.php/Mercator
Php Code by Erhan Baris 19:19, 01.09.2007

START

*/

function deg_rad($ang)
{
	return (float)((float)$ang * (float)(M_PI / 180.0));
}

function merc_x($lon)
{
	$r_major = 6378137.000;
	return (float)($r_major * deg_rad($lon));
}

function merc_y($lat)
{
	if ($lat > 89.5) $lat = 89.5;
	if ($lat < -89.5) $lat = -89.5;
	$r_major = 6378137.000;
	$r_minor = 6356752.3142;
	$temp = $r_minor / $r_major;
	$es = 1.0 - ($temp * $temp);
	$eccent = sqrt($es);
	$phi = deg_rad($lat);
	$sinphi = sin($phi);
	$con = $eccent * $sinphi;
	$com = 0.5 * $eccent;
	$con = pow(((1.0-$con)/(1.0+$con)), $com);
	$ts = tan(0.5 * ((M_PI*0.5) - $phi))/$con;
	$y = 0 - $r_major * log($ts);
	return $y;
}

function merc($x,$y) {
    return array('x'=>merc_x($x),'y'=>merc_y($y));
}

/*
http://wiki.openstreetmap.org/index.php/Mercator
Php Code by Erhan Baris 19:19, 01.09.2007

END

*/


function create_mysql_functions($db) {
	query("DROP FUNCTION IF EXISTS deg_rad", $db, false);
	query("DROP FUNCTION IF EXISTS merc_x", $db, false);
	query("DROP FUNCTION IF EXISTS merc_y", $db, false);
	
	query("
		CREATE FUNCTION deg_rad (ang DOUBLE) RETURNS DOUBLE NO SQL
		BEGIN 
			RETURN ang * PI() / 180.0;
		END
	", $db, false);
	
	query("
		CREATE FUNCTION merc_x (lon INT(11)) RETURNS DOUBLE NO SQL
		BEGIN 
			RETURN 6378137.000 * deg_rad(lon);
		END
	", $db, false);
	
	query("
		CREATE FUNCTION merc_y (lat1 INT(11)) RETURNS DOUBLE NO SQL
		BEGIN 
			DECLARE lat DOUBLE;
			DECLARE r_major DOUBLE;
			DECLARE r_minor DOUBLE;
			DECLARE eccent DOUBLE;
			DECLARE phi DOUBLE;
			DECLARE con DOUBLE;
			DECLARE com DOUBLE;
		
			SET lat=lat1;
			IF lat1 > 89.5 THEN 
				SET lat = 89.5; 
			END IF;
			IF lat1 < -89.5 THEN 
				SET lat = -89.5; 
			END IF;
			SET r_major = 6378137.000;
			SET r_minor = 6356752.3142;
			SET eccent = SQRT(1.0 - POW(r_minor / r_major, 2));
			SET phi = deg_rad(lat);
			SET con = eccent * sin(phi);
			SET com = 0.5 * eccent;
			SET con = POW(((1.0-con)/(1.0+con)), com);
			RETURN 0 - r_major * LOG(TAN(0.5 * ((PI()*0.5) - phi))/con);
		END
	", $db, false);
}

function drop_mysql_functions($db) {
	query("DROP FUNCTION IF EXISTS deg_rad;", $db, false);
	query("DROP FUNCTION IF EXISTS merc_x;", $db, false);
	query("DROP FUNCTION IF EXISTS merc_y;", $db, false);
}



// gets a time value in seconds and writes it in s, min, h
// according to its amount
function format_time($t) {
	if ($t<60) {
		return sprintf("%01.2fs", $t);						// seconds
	} elseif ($t<3600) {
		return sprintf("%01.0fm %01.0fs", floor($t/60), $t % 60);		// minutes
	} else 
		return sprintf("%01.0fh %01.0fm", floor($t/3600), ($t % 3600)/60);	// hours
}
?>
Return current item: Keepright