I am looking for a bounding box (sort of) but not with points in the corners. I want points due north, due south, due east, and due west. When you have points in the corners, your query result will be skewed because of the Pythagorean theorem. If you have a square with a side length of x, the diagonal will be of length x * square root of 2. That (half) will not match the distance I want to go north, south, east and west of the starting point.
I looked at the bearings in the script. They are 0, 90, 180, and 270. Given those bearings, I do not see that this would produce coordinates on the diagonal despite what the author says. The bearings appear to be due north, south, east, and west. I could be wrong.
Since latitude increments from north to south and longitude from east to west, I want points due north and south so I can query everything between the north and south points and do the same with longitude to find matches in my database.
The script linked to by crmalibu is highly accurate for the North coordinate (using the new latitude and the original longitude), but all the other points, especially the south and west, are off. They are short. I’m not looking for points on the diagonal. But if I were, it would not matter because the distances are off.
Here is my entire test script with the unaltered original script followed by an example I tested.
<?php
$google_map_url = 'http://maps.google.com/maps?f=q&q={lat},{lon}(Test)&z=15&iwloc=A';
// McKnight & 17th.
$lat0 = 45.02091417565888;
$lon0 = -93.00496459007263;
//Beam & McKnight from http://mapki.com/getLonLat.php
//$lat0 = 45.02814095036411;
//$lon0 = -93.00500750541687;
// Beam & McKnight from script calculation.
//$lat0 = 45.028142832457;
//$lon0 = -93.004964590073;
list($lat1,$lat2,$lon1,$lon2) = getBoundingBox($lat0, $lon0, .5);
$url0 = str_replace('{lat}', $lat0, $google_map_url);
$url0 = str_replace('{lon}', $lon0, $url0);
$url1 = str_replace('{lat}', $lat1, $google_map_url);
$url1 = str_replace('{lon}', $lon0, $url1);
$url2 = str_replace('{lat}', $lat2, $google_map_url);
$url2 = str_replace('{lon}', $lon0, $url2);
$url3 = str_replace('{lat}', $lat0, $google_map_url);
$url3 = str_replace('{lon}', $lon1, $url3);
$url4 = str_replace('{lat}', $lat0, $google_map_url);
$url4 = str_replace('{lon}', $lon2, $url4);
echo '<a href="' . $url0 . '">url0 Original Coords</a>' . '<br/>';
echo '<a href="' . $url1 . '">url1 New lat1 (South) Original lon</a>' . '<br/>';
echo '<a href="' . $url2 . '">url2 New lat2 (North) Original lon</a>' . '<br/>';
echo '<a href="' . $url3 . '">url3 New lon1 (West) Original lat</a>' . '<br/>';
echo '<a href="' . $url4 . '">url4 New lon2 (East) Original lat</a>' . '<br/>';
// Original script.
function getBoundingBox($lat_degrees,$lon_degrees,$distance_in_miles) {
$radius = 3963.1; // of earth in miles
// bearings
$due_north = 0;
$due_south = 180;
$due_east = 90;
$due_west = 270;
// convert latitude and longitude into radians
$lat_r = deg2rad($lat_degrees);
$lon_r = deg2rad($lon_degrees);
// find the northmost, southmost, eastmost and westmost corners $distance_in_miles away
// original formula from
// http://www.movable-type.co.uk/scripts/latlong.html
$northmost = asin(sin($lat_r) * cos($distance_in_miles/$radius) + cos($lat_r) * sin ($distance_in_miles/$radius) * cos($due_north));
$southmost = asin(sin($lat_r) * cos($distance_in_miles/$radius) + cos($lat_r) * sin ($distance_in_miles/$radius) * cos($due_south));
$eastmost = $lon_r + atan2(sin($due_east)*sin($distance_in_miles/$radius)*cos($lat_r),cos($distance_in_miles/$radius)-sin($lat_r)*sin($lat_r));
$westmost = $lon_r + atan2(sin($due_west)*sin($distance_in_miles/$radius)*cos($lat_r),cos($distance_in_miles/$radius)-sin($lat_r)*sin($lat_r));
$northmost = rad2deg($northmost);
$southmost = rad2deg($southmost);
$eastmost = rad2deg($eastmost);
$westmost = rad2deg($westmost);
// sort the lat and long so that we can use them for a between query
if ($northmost > $southmost) {
$lat1 = $southmost;
$lat2 = $northmost;
} else {
$lat1 = $northmost;
$lat2 = $southmost;
}
if ($eastmost > $westmost) {
$lon1 = $westmost;
$lon2 = $eastmost;
} else {
$lon1 = $eastmost;
$lon2 = $westmost;
}
return array($lat1,$lat2,$lon1,$lon2);
}
?>
Our starting point is McKnight & 17th, 45.02091417565888, -93.00496459007263. I know with certainty that the distance from McKnight & 17th north to Beam & McKnight is 1/2 mile. I’ve measured it in two different vehicles in the past. I got the coordinates from http://mapki.com/getLonLat.php. I would love to know how to develop a tool like that.
Running the script outputs the following Google Maps links:
Original starting location:
http://maps.google.com/maps?f=q&q=45.020914175659,-93.004964590073(Test)&z=15&iwloc=A
Point due south using original longitude and lat1 from the script:
http://maps.google.com/maps?f=q&q=45.016587820348,-93.004964590073(Test)&z=15&iwloc=A
Point due north using original longitude and lat2 from the script:
http://maps.google.com/maps?f=q&q=45.028142832457,-93.004964590073(Test)&z=15&iwloc=A
Point due west using original latitude and lon1:
http://maps.google.com/maps?f=q&q=45.020914175659,-93.006764941236(Test)&z=15&iwloc=A
Point due east using original latitude and lon2:
http://maps.google.com/maps?f=q&q=45.020914175659,-92.995822045458(Test)&z=15&iwloc=A
As I mentioned previously, the distance from our starting point at McKnight & 17th due north to McKnight & Beam is exactly 1/2 mile. The output from the script for the due north point is almost exactly accurate:
http://maps.google.com/maps?f=q&q=45.028142832457,-93.004964590073(Test)&z=15&iwloc=A
Starting at the intersection of McKnight & 17th and going 1/2 mile north, we get a point at the intersection of McKnight & Beam as we should.
As a test, let’s move our starting point to Beam and McKnight and look at the south point produced by the PHP script. Starting coordinates are 45.02814095036411, -93.00500750541687.
New original location at Beam & McKnight:
http://maps.google.com/maps?f=q&q=45.028140950364,-93.005007505417(Test)&z=15&iwloc=A
The south point:
http://maps.google.com/maps?f=q&q=45.023814594979,-93.005007505417(Test)&z=15&iwloc=A
We have established the distance from McKnight & 17th north to Beam & McKnight is 1/2 mile (.5). But if you look at the new south point, it is well short of the intersection of McKnight & 17th.
Thus, the script has to be inaccurate.
I have tested this on other distances of 1 mile and 5 miles and have found similar inaccuracies not just with the north-south points, but with the east-west points as well.
Even if these points were supposed to be plotted on the diagonal (which I do not want), the north-south distances would have to be the same. But they are not. I tested those, too.
If anyone has any idea if the original script can be salvaged or if you see any bugs in my code, please let me know.
Or if there are any math and PHP gurus out there that can take the Haversine formula and modify it to return point coordinates instead of a distance, let me know.
I am sure something like this could be beneficial to others. Of course, I did a search here at Sitepoint before I posted this thread. I didn’t find any answers and have not found any despite hours of searching on the internet.
Thank you.