I didn't see the original post, so pardon me if I'm off-target.

I wanted to mention that, when working with "small" distances and areas, I generally use the geo formulas once to calculate the distance/degree ratios for latitude and longitude at one point*, and then just convert other nearby lat/lons to relative distances with pythagoras. It's far less computationally intensive, and good enough for many purposes, including finding the closest object, smoothing ways, getting approximate bearings, etc.

For example, at 34 deg lat, latitude is 110922.416 m/deg and longitude is 92384.593 m/deg.

At 33.5 deg lat (55 km south), lat is 110913.401 m/deg (0.008% less) and lon is 92922.354 m/deg (0.6% more).

Using a traditional, computationally expensive formula, the distance between first point A(34.1, 120.0) and second point B1(33.9, 120.2) is 28871.232 m. Using the constants for 34 deg lat above and pythagoras, you get dY=22184.483 m and dX=18476.919 m. Diagonal distance d = (dY^2 + dX^2)^0.5 = 28871.228 m (almost exactly the same).

For a second point B2(34.35, 120.15), the distance A-B2 using the expensive formula is 30984.896 m. Using the 34 degree factors, it is 31000.353 m (error of 0.05%).

For a second point B3(34.6, 121.3), the distance A-B3 using the expensive formula is 131838.294 m. Using the 34 degree factors, it is 132287.371 m (0.34% error, even for such a large distance from the reference point)

If you don't care about the actual distance values, just their relative sizes, you can drop one more multiplication from the calculation by determining the ratio of the lat m/deg to the lon m/deg factors, then scaling the latitude diff by that factor and feeding the result, along with the longitude diff, to pythagoras:

For the factors for 34 degrees above: latitudinal degrees are 1.200659x as long in meters as longitudinal degrees. So, multiply dY (change in lat) by this ratio and then apply pythagoras to get a mythical unit (call it foo) value.

For A-B1, dY=0.2*1.200659, dX=0.2, d=0.312511 foo.

For A-B2, dY=0.25*1.200659, dX=0.15, d=0.335558 foo. This is 1.0737x A-B1. Note that this is the same ratio as the distance values calculated above (31000.353/28871.228).

For A-B3, dY=0.5*1.200659, dX=1.3, d=1.43192 foo. This is 4.5820x A-B1. Note that this is the same ratio as the distance values calculated above (132287.371/28871.228).


And these are all relatively long distances. When you're looking for the nearest bus stop, intersection, etc., these approximations work quite well. At higher latitudes, accuracy starts to decrease, but is still within 1% out to 10s of km at 60 degrees lat.



* I don't recall the basis for these. They seem to come quite close to traditional calcs like http://www.ngs.noaa.gov/cgi-bin/Inv_Fwd/inverse2.prl. It's possible (even likely) that some of the constants in the main formulae are geoid-dependent - I've only worked with this using the GRS80 spheroid (for WGS84). $nMidLat is the latitude of interest.

$cnPi = 3.1415926535897932;
$cnSphA = 6378137.0;                            # Equatorial radius in meters (GRS80/WGS84)
$cnSphB = 6356752.3141;                 # Polar radius in meters (GRS80/WGS84)
$cnSphF = ($cnSphA - $cnSphB) / $cnSphA;        # Flattening factor
$cnSphCDeg = ($cnSphA * $cnPi) / 180.0; # Meters per 1 degree longitudinal arc at 0 latitude

$nMidLatRad = $nMidLat * $cnPi / 180.0;

# Horizontal meters per degree:
$gnHMult = (1.0 + ((sin($nMidLatRad) ** 2.00362) * $cnSphF)) * $cnSphCDeg * cos($nMidLatRad);

# Vertical meters per degree:
$gnVMult = $cnSphCDeg * 0.993307 * (1 + (3.018996 * (sin($nMidLatRad) ** 2.00985) * $cnSphF));



At 2012-05-09 06:48, Ramiro Cosentino wrote:
Re all,

I've found a solution which works for me. It's basically an implementation of the Haversine function for ruby taken from here
http://www.esawdust.com/blog/gps/files/HaversineFormulaInRuby.html

There is another one I haven't tried here:
https://github.com/almartin/Ruby-Haversine

The only drawback is that I got to fetch all the db records which are around 500 and apply haversine distance to each compared against users's current location (which is provided by the phone).

Thanks everyone for the input! It really helped me find the right direction, or at least reasonable.

--
Alan Mintz <alan_mintz+...@earthlink.net>

_______________________________________________
talk mailing list
talk@openstreetmap.org
http://lists.openstreetmap.org/listinfo/talk

Reply via email to