Calculate distance between points + sort them (WORKS!)

Hi all,

I have been working on a piece of code I’d like to share with you. Its not a question, the code really works!

Features:

  • Calculate distance between 2 points

  • Sort points (longitude, latitude) by your ‘GPS position’

I used two sources aswell, because I am not so good at math you know ;p

Have fun with it!

-- source print\_r function: https://gist.github.com/nrk/31175 -- source distance between 2 points: http://awesome.naquadah.org/wiki/Kooky\_geo function print\_r ( t ) local print\_r\_cache={} local function sub\_print\_r(t,indent) if (print\_r\_cache[tostring(t)]) then print(indent.."\*"..tostring(t)) else print\_r\_cache[tostring(t)]=true if (type(t)=="table") then for pos,val in pairs(t) do if (type(val)=="table") then print(indent.."["..pos.."] =\> "..tostring(t).." {") sub\_print\_r(val,indent..string.rep(" ",string.len(pos)+8)) print(indent..string.rep(" ",string.len(pos)+6).."}") else print(indent.."["..pos.."] =\> "..tostring(val)) end end else print(indent..tostring(t)) end end end sub\_print\_r(t," ") end -- Locals local cos = math.cos local sin = math.sin local pi = math.pi local sqrt = math.sqrt local min = math.min local asin = math.asin local abs = math.abs -- Calculate distance function distance(from, to) local distance = 0 local radius = 6367000 local radian = pi / 180 local deltaLatitude = sin(radian \* (from.latitude - to.latitude) /2) local deltaLongitude = sin(radian \* (from.longitude - to.longitude) / 2) local circleDistance = 2 \* asin(min(1, sqrt(deltaLatitude \* deltaLatitude + cos(radian \* from.latitude) \* cos(radian \* to.latitude) \* deltaLongitude \* deltaLongitude))) distance = abs(radius \* circleDistance) return distance end -- Markers local markers = { &nbsp;&nbsp;&nbsp; { title='Nova Scotia', latitude = -62.937013, longitude = 45.367584}, -- will become position 3 { title='Brooklyn', latitude = -73.949204, longitude = 40.644178}, -- will become position 1 { title='South Philadelphia West', latitude = -75.181275, longitude = 39.918163} -- will become position 2 } -- Center; could be your current GPS location centerPoint = {latitude = -73.995895, longitude = 40.718119} -- new york -- Set distances in markers for i, Prop in ipairs(markers) do Prop['distance'] = distance(centerPoint, markers[i]) end -- Sort by distance function compare(a,b) return a['distance'] \< b['distance'] end table.sort(markers, compare) -- Print sorted markers print\_r(markers)

Output:

 [1] =\> table: 002ABBC0 { [longitude] =\> 40.644178 [latitude] =\> -73.949204 [title] =\> Brooklyn [distance] =\> 5662.823745369 } [2] =\> table: 002ABBC0 { [longitude] =\> 39.918163 [latitude] =\> -75.181275 [title] =\> South Philadelphia West [distance] =\> 133824.02894993 } [3] =\> table: 002ABBC0 { [longitude] =\> 45.367584 [latitude] =\> -62.937013 [title] =\> Nova Scotia [distance] =\> 1242546.4018208 }

thank you, this code really work very well,

but i want to know, this distance is in which unit(meter, km,feet,)…?

and how can i change in other unit?

please reply me if you have any answer

You should really post to the Code Exchange: http://code.coronalabs.com/

Thank you! No problem.

The results are in meters :slight_smile:

I have been thinking about this, but isn’t it a little overhead to create a new repository (Github) just for this piece of code? :slight_smile:

It has been shared:

http://code.coronalabs.com/code/calculate-distances-between-markers-and-sort-them-longitude-latitude-your-gps-position

Thanks for the code Sneeuw, I’m using it right now in one of my apps.

Best regards,

Tomas

Great! :slight_smile:

Don’t mind to drop the app name/url after you released it. Don’t worry; I won’t take credits :wink:

Will do!

Just as an FYI on the code exchange…   We recognize that setting up a GitHub account and sharing code through there has some overhead.  This is one reason we support GIST as well.  GIST uses GitHub technology but allows you to quickly share shorter code snippets that are not full projects.  If you have a single function or several that might be in one file, GIST is a much faster way to share that code out.

You still have to setup an account, but when it comes to sharing the code, it’s a single form.  Check out:  https://gist.github.com/

Rob

sir can you show me a code similar to this but will only output the nearest marker from your current GPS location(not constant)? I am developing an android app that has a mapview with markers around it, and will be capable of calculating the distance between your current GPS location from the nearest marker… thank you and more power!

I think this can simply done by changing this line:


centerPoint = {latitude = -73.995895, longitude = 40.718119} – new york


Change the variable to your current GPS location. See more details at http://docs.coronalabs.com/api/event/location/longitude.html

If you want to update your GPS more often, see more details at http://forums.coronalabs.com/topic/36981-gps-location-update-frequency/

I hope this will help you :slight_smile:

I’m still confused but thanks a lot for the reply. This might help me solve this problem. And how about displaying only the nearest marker without sorting and displaying all markers?

Sorry, if I’d be making codes for anyone, I wouldn’t even have time left for my own projects.

You have to go thru all markers in order to sort them by distance. If you only want the nearest, just only show the first item in the array. 

I hope this helps.

Thanks a lot sir. I’ve sorted things out. :slight_smile:

:slight_smile: Great! Thanks for your feedback.

**These lines of code will display the output of the distance of your current location from the nearest marker in the corona simulator but the problem is, whenever I run this code in my Android App it doesn’t display anything… Can someone give me an idea about how to display my output in Android?**

function print_r ( t )
local print_r_cache={}
local function sub_print_r(t,indent)
if (print_r_cache[tostring(t)]) then
print(indent…"*"…tostring(t))
else
print_r_cache[tostring(t)]=true
–if (type(t)==“table”) then
for pos,val in pairs(t) do
if (type(val)==“table”) then
print(indent…"["…pos…"] => “…tostring(t)…” {")
sub_print_r(val,indent…string.rep(" “,string.len(pos)+8))
print(indent…string.rep(” “,string.len(pos)+6)…”}")
else
print(indent…"["…pos…"] => “…tostring(val))
end
end
–else
–print(indent…tostring(t))
–end
end
end
sub_print_r(t,” ")
end

– Locals
local cos = math.cos
local sin = math.sin
local pi = math.pi
local sqrt = math.sqrt
local min = math.min
local asin = math.asin
local abs = math.abs

– Calculate distance
function distance(from, to)
local distance = 0
local radius = 6367000
local radian = pi / 180
local deltaLatitude = sin(radian * (from.latitude - to.latitude) /2)
local deltaLongitude = sin(radian * (from.longitude - to.longitude) / 2)

local circleDistance = 2 * asin(min(1, sqrt(deltaLatitude * deltaLatitude +
cos(radian * from.latitude) * cos(radian * to.latitude) * deltaLongitude * deltaLongitude)))
distance = abs(radius * circleDistance)
return distance
end

– Markers
local markers = {
{ title=‘sasa1’, latitude = 7.07220007, longitude = 125.6208795}, – will become position 3
{ title=‘sasa2’, latitude = 7.0723912, longitude = 125.61704414}, – will become position 1
{ title=‘sasa3’, latitude = 7.07362466, longitude = 125.61977253} – will become position 2
}
–currentLatitude = curentLocation.latitude
–currentLongitude = currentLocation.longitude
– Center; could be your current GPS location
centerPoint = {latitude = 7.07525189, longitude = 125.61961413} – new york
–centerPoint = {currentLocation}
–local centerPoint = {myMap:getUserLocation()}

– Set distances in markers
for i, Prop in ipairs(markers) do
Prop[‘distance’] = distance(centerPoint, markers[i])
end

– Sort by distance
function compare(a, b)
return a[‘distance’] < b[‘distance’]

end
table.sort(markers, compare)

local newText =
"Nearest is: " print_r(markers[1])
native.showAlert( “You Are Here”, nearestText, { “OK” } )

end

the smiley there is for “b”. I’m trying to edit it but I ended up messing around my post. I apologize for my mistake.

^^

print_r can ONLY be used in the Corona SDK Simulator Console. 

Try something like:

local newText = "Nearest is: " … markers[1].title
native.showAlert( “You Are Here”, newText, { “OK” } )
end