views:

446

answers:

3

Hi!

I need to parse some user submitted strings containing latitudes and longitudes, under Ruby.

The result should be given in a double

Example:

08º 04' 49'' 09º 13' 12''

Result:

8.080278 9.22

I've looked to both Geokit and GeoRuby but haven't found a solution. Any hint?

+3  A: 
"08° 04' 49'' 09° 13' 12''".gsub(/(\d+)° (\d+)' (\d+)''/) do
  $1.to_f + $2.to_f/60 + $3.to_f/3600
end
#=> "8.08027777777778 9.22"

Edit: or to get the result as an array of floats:

"08° 04' 49'' 09° 13' 12''".scan(/(\d+)° (\d+)' (\d+)''/).map do |d,m,s|
  d.to_f + m.to_f/60 + s.to_f/3600
end
#=> [8.08027777777778, 9.22]
sepp2k
Thanks! I will accept this elegant answer! However, I was expecting some kind of library that was able to parse other formats or variations. A little tweak on the regexp will do! Thank you again!
rubenfonseca
+2  A: 

How about using a regular expression? Eg:

def latlong(dms_pair)
  match = dms_pair.match(/(\d\d)º (\d\d)' (\d\d)'' (\d\d)º (\d\d)' (\d\d)''/)
  latitude = match[1].to_f + match[2].to_f / 60 + match[3].to_f / 3600
  longitude = match[4].to_f + match[5].to_f / 60 + match[6].to_f / 3600
  {:latitude=>latitude, :longitude=>longitude}
end

Here's a more complex version that copes with negative coordinates:

def dms_to_degrees(d, m, s)
  degrees = d
  fractional = m / 60 + s / 3600
  if d > 0
    degrees + fractional
  else
    degrees - fractional
  end
end

def latlong(dms_pair)
  match = dms_pair.match(/(-?\d+)º (\d+)' (\d+)'' (-?\d+)º (\d+)' (\d+)''/)

  latitude = dms_to_degrees(*match[1..3].map {|x| x.to_f})
  longitude = dms_to_degrees(*match[4..6].map {|x| x.to_f})

  {:latitude=>latitude, :longitude=>longitude}
end
Will Harris
good solution too. Thank you!
rubenfonseca
+1  A: 

Based on the form of your question, you are expecting the solution to handle negative coordinates correctly. If you weren't, then you'd be expecting an N or S following latitude and an E or W following longitude.

Please note that the accepted solution will not provide correct results with a negative coordinate. Only the degrees will be negative, and the minutes and seconds will be positive. In those cases where the degrees are negative, the minutes and seconds will move the coordinate closer to 0° rather than further away from 0°.

Will Harris' second solution is the better way to go.

Good luck!

metaclass