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).
Related
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
How can I calculate every Lat/Long coordinates between two Lat/Long coordinates in PHP?
Lets say I have coordinates A:
(39.126331, -84.113288)
and coordinates B:
(39.526331, -84.213288)
How would I calculate every possible coordinates between those two Lat/Long coordinates (in a direct line) up to five decimal places (e.g. 39.12633, -84.11328) and get list of coordinates between the two?
In addition, I have another set of coordinates (Coordinates C) that are slightly off and not on the track of coordinates between A and B.
How could I calculate the distance between coordinates C and the closest coordinates between A and B?
You can compute a voronoi diagram from all the lat lon pairs and then look for adjacent cell. Also note that lat lon are angles and not world coordinate or cartesian coordinates. You can download my PHP class voronoi diagram # phpclasses.org.
Here is what solved this for me,
function point_to_line_segment_distance($startX,$startY, $endX,$endY, $pointX,$pointY)
{
$r_numerator = ($pointX - $startX) * ($endX - $startX) + ($pointY - $startY) * ($endY - $startY);
$r_denominator = ($endX - $startX) * ($endX - $startX) + ($endY - $startY) * ($endY - $startY);
$r = $r_numerator / $r_denominator;
$px = $startX + $r * ($endX - $startX);
$py = $startY + $r * ($endY - $startY);
$closest_point_on_segment_X = $px;
$closest_point_on_segment_Y = $py;
$distance = user_bomb_distance_calc($closest_point_on_segment_X, $closest_point_on_segment_Y, $pointX, $pointY);
return array($distance, $closest_point_on_segment_X, $closest_point_on_segment_Y);
}
function user_bomb_distance_calc($uLat , $uLong , $bLat , $bLong)
{
$earthRadius = 6371; #km
$dLat = deg2rad((double)$bLat - (double) $uLat);
$dlong = deg2rad((double)$bLong - (double) $uLong);
$a = sin($dLat / 2 ) * sin($dLat / 2 ) + cos(deg2rad((double)$uLat)) * cos(deg2rad((double)$bLat)) * sin($dlong / 2) * sin($dlong / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$distance = $earthRadius * $c;
$meter = 1000; //convert to meter 1KM = 1000M
return intval( $distance * $meter ) ;
}
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'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
I am making a small section of an app (phone and website) that can find the nearest stores (stored in my database). I am using PHP so was going to make use of the web service idea and have AJAX requests posted to a PHP Page. I have found the following info from snipplr.com:
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);
}
Which is all good, but I have a database of about 300 locations. I just need bit of help getting started with this.
My idea was to do a query to a DB and get all of the long/lats in an array and loop through the array, each time using this above function. Then sort the requests by distance and done!
But I just wondered if theres a better way? I am relatively new to PHP development, so need to get an idea about best practices etc...
Thanks for the help!
i'd actually advice you to check out the solution of google. this works pretty well:
https://developers.google.com/maps/articles/phpsqlsearch?hl=en