I'm trying to get make a query which gives me a list of stores sorted by how far they are from the current location. I'm working in php and using MySQL for my database.
To calculate the distance between 2 stores, I use the longitudes and latitudes from the 2 stores and derive the distance from it. This is contained in a self-defined function distance($lat1, $lng1, $lat2, $lng2). The result of this function is the distance in km.
I want to use this function to create an extra column in my query result so I can sort all the stores from the one most behind my current location to the one most far from my current location. Both functions are declared in the same file, but I do not get any result. Is it possible to call a function in the SELECT clause by declaring it the way I did?
function getSortedStores($cur_lat, $cur_lng)
{
$query = "SELECT Store.ID, Store.Name, distance($cur_lat, $cur_lng, Address.Latitude, Address.Longitude) AS Distance FROM Store INNER JOIN Address ON Store.ID=Address.StoreID ORDER BY Distance";
$result = mysql_query($query);
return $result;
}
function distance($lat1, $lng1, $lat2, $lng2)
{
$toRadians = M_PI / 180;
$lat1 *= $toRadians;
$lng1 *= $toRadians;
$lat2 *= $toRadians;
$lng2 *= $toRadians;
$r = 6371; // mean radius of Earth in km
$dlat = $lat2 - $lat1;
$dlng = $lng2 - $lng1;
$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$km = $r * $c;
$km = round($km, 1);
return $km;
}
you can't use php function in mysql. for more detail about mysql User-Defined Function
see this
http://dev.mysql.com/doc/refman/5.1/en/adding-functions.html
You can't mix PHP and mySQL in that way, you can either do the calculation in mySQL with their math functions, or select the raw data and do the calculations based on the result set in PHP. But you cannot call a PHP function inside a mySQL query.
Alternatively, and assuming that your stores are not mobile. You can create a simple table table to store the distances between all of your stores. It takes up a little extra storage, but can potentially save you a fair bit of CPU cycles in the end.
TABLE distances
store1_id INT PK
store2_id INT PK
distance FLOAT
SELECT distance
FROM distances
WHERE (store1_id = $store1 AND store2_id = $store2)
OR (store1_id = $store2 AND store1_id = $store2)
LIMIT 1
Related
I'm using MySQLi with mysqlnd driver, and using a function to get long/lat coordinates and calculate the distance between them, however I'm having issues with strange numbers and errors regarding "expected double, string given".
In my database, the long/lat values are stored as "Decimal (18,15)". I then use a MySQLi query to retireve this from the database, and store them in a PHP Variable like so:
$latitudeTo = $postcoderow[latitude];
$float_latitudeTo = floatval($latitudeTo);
$longitudeTo = $postcoderow[longitude];
$float_longitudeTo = floatval($longitudeTo);
The other set of long/lat are the same (just using different names).
However, the postcodes will be only from the UK, and using the following PHP Function
function calculateDistance($float_latitudeFrom, $float_longitudeFrom, $float_latitudeTo, $float_longitudeTo, $earthMeanRadius = 3440) {
$deltaLatitude = deg2rad($float_latitudeTo - $float_latitudeFrom);
$deltaLongitude = deg2rad($float_longitudeTo - $float_longitudeFrom);
$a = sin($deltaLatitude / 2) * sin($deltaLatitude / 2) +
cos(deg2rad($float_latitudeFrom)) * cos(deg2rad(float_latitudeTo)) *
sin($deltaLongitude / 2) * sin($deltaLongitude / 2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
return $earthMeanRadius * $c;
}
//Function call with the coordinates.
$miles = calculateDistance($float_latitudeFrom, $float_longitudeFrom, $float_latitudeTo, $float_longitudeTo, $earthMeanRadius = 3440);
I'm getting values of 3000+ miles returned (I just echo '.$miles.')
How do I store $float_latitudeTo... etc as doubles, as they are decimals from the database, however are converted to a string which is causing errors. I think the PHP Function itself is fine, just how I'm parsing the values.
Thanks for your time!
I have a table in mysql with 4 columns:
Latitude_1
Longitude_1
Latitude_2
Longitude_2
Now I want to calculate the heading for all rows to be used in a kml file.
I found this function:
// Takes two sets of geographic coordinates in decimal degrees and produces bearing (azimuth) from the first set of coordinates to the second set.//
public static function bearing($lat1, $lon1, $lat2, $lon2) {
$lat1 = deg2rad($lat1);
$lon1 = deg2rad($lon1);
$lat2 = deg2rad($lat2);
$lon2 = deg2rad($lon2);
$lonDelta = $lon2 - $lon1;
$y = sin($lonDelta) * cos($lat2);
$x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($lonDelta);
$brng = atan2($y, $x);
$brng = $brng * (180 / pi());
if ( $brng < 0 ) { $brng += 360; }
return $brng;
}
Now I hope that someone shows me a query that echoes all headings (bearings) of the table based on the above mentioned function
To combine an expression expr, take a look to the mysql math functions and find proper equivalents for php ones - https://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html
Simplify your expr if possible
Use your result expression expr in following query SELECT expr FROM your_table
Profit
Please help me to find an algorithm that finds the nearest neighbor by its coordinates (latitude/longitude) I will implemented it using PHP
for example. we have 1 client and 2 nodes
Node 1 = 32.9697, -96.8032 and Node 2=42.9697, -97.80322
each node has their own given coordinates (place on a map).
the client will send a latitude and longitude coordinates into the system and the system will find out if the coordinates that it receives from the client is near to Node 1 or Node 2
Please excuse my grammar. Hoping for your kind response. Thank you in advance
If you have only a limited number of possible targets (as I would guess from your question) you can use the following function (copied from here) and just iterate over all your targets to find the closest one.
function distance($lat1, $lng1, $lat2, $lng2, $miles = false)
{
$pi80 = M_PI / 180;
$lat1 *= $pi80;
$lng1 *= $pi80;
$lat2 *= $pi80;
$lng2 *= $pi80;
$r = 6372.797; // mean radius of Earth in km
$dlat = $lat2 - $lat1;
$dlng = $lng2 - $lng1;
$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$km = $r * $c;
return ($miles ? ($km * 0.621371192) : $km);
}
If you have many possible locations (>=10^4) you should organise those data points in some structure to only have to evaluate a fraction of them. I'd suggest a Quadtree for this although it will not work for the poles as well as the datum-border. I'm sure you'll find better solutions if needed for such a case (which I assume you do not require).
I have a list of ISO 3166 country codes (240) and a list of 8 countries/territories/regions (Australia, Denmark, Netherlands, Qatar, South Africa, UAE, UK & USA). I would like to go through the list of country codes and, for each one, work out which is the closest one from the list of 8. The metric (geographical distance, straight-line distance, driving time, etc.) isn't particularly important as it doesn't need to be perfect, just reasonable.
The list of 8 places is subject to regular change so it's impractical to do the task manually. I've tried using the Google Maps API but have so far been unsuccessful. The ideal solution would be in PHP and would result in an array with the country code as the index and closest country (from the list of 8) as the value. Any help appreciated!
The geonames project has public data that you can use
http://www.geonames.org/
Now you can get the distance between geographical coorindates.
function distance($lat1, $lng1, $lat2, $lng2, $miles = true)
{
$pi80 = M_PI / 180;
$lat1 *= $pi80;
$lng1 *= $pi80;
$lat2 *= $pi80;
$lng2 *= $pi80;
$r = 6372.797; // mean radius of Earth in km
$dlat = $lat2 - $lat1;
$dlng = $lng2 - $lng1;
$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$km = $r * $c;
return ($miles ? ($km * 0.621371192) : $km);
}
For your use case you could use the capital of the countries. For big countries you should possibly add some more countries near the boarders.
That is one solution. You could also store geometric shapes that approximate the country in a database and make exact queries...
However the starting point is the data. What do you actually want? What data do you have?
If efficiency is a problem I would recommend build a graph where every country is stored and linked with its border countries. If you only look at the border countries this greatly reduces computational effort.
I am working on a website which requires distance calculation between two zip-codes. I have a database table which consists of zip-codes and their related latitudes and longitudes. I make use of this to calculate distance between the two places.
But I have a problem that this gives me straight line distance and not driving distance - how can I find that?
I'm using the following code
$lat1 = $this->deg_to_rad($lat1);
$lon1 = $this->deg_to_rad($lon1);
$lat2 = $this->deg_to_rad($lat2);
$lon2 = $this->deg_to_rad($lon2);
$delta_lat = $lat2 - $lat1;
$delta_lon = $lon2 - $lon1;
$temp = pow(sin($delta_lat/2.0),2) + cos($lat1) * cos($lat2) * pow(sin($delta_lon/2.0),2);
$distance = 3956 * 2 * atan2(sqrt($temp),sqrt(1-$temp));
You can somehere silently call a Google Maps GDirection(). It gives you not only a route but real distance also, but this is javascript soulution, and only way to provide this data to php is catch received distance and send to php by AJAX.