Module: GoogleMapsService::Convert

Defined in:
lib/google_maps_service/convert.rb

Overview

Converts Ruby types to string representations suitable for Maps API server.

Class Method Summary collapse

Class Method Details

.as_list(arg) ⇒ Array

Coerces arg into a list. If arg is already list-like, returns arg. Otherwise, returns a one-element list containing arg.

Parameters:

  • arg (Object)

Returns:

  • (Array)


69
70
71
72
73
74
# File 'lib/google_maps_service/convert.rb', line 69

def as_list(arg)
  if arg.kind_of?(Array)
      return arg
  end
  return [arg]
end

.bounds(arg) ⇒ String

Converts a lat/lon bounds to a comma- and pipe-separated string.

Accepts two representations:

  1. String: pipe-separated pair of comma-separated lat/lon pairs.

  2. Hash with two entries - “southwest” and “northeast”. See latlng

for information on how these can be represented.

For example:

>> sydney_bounds = {
?>   "northeast": {
?>     "lat": -33.4245981,
?>     "lng": 151.3426361
?>   },
?>   "southwest": {
?>     "lat": -34.1692489,
?>     "lng": 150.502229
?>   }
?> }
>> GoogleMapsService::Convert.bounds(sydney_bounds)
=> '-34.169249,150.502229|-33.424598,151.342636'

Parameters:

  • arg (Hash)

    The bounds.

Returns:

  • (String)

Raises:

  • (ArgumentError)


138
139
140
141
142
143
144
145
146
147
148
# File 'lib/google_maps_service/convert.rb', line 138

def bounds(arg)
  if arg.kind_of?(Hash)
    if arg.has_key?("southwest") && arg.has_key?("northeast")
      return "#{latlng(arg["southwest"])}|#{latlng(arg["northeast"])}"
    elsif arg.has_key?(:southwest) && arg.has_key?(:northeast)
      return "#{latlng(arg[:southwest])}|#{latlng(arg[:northeast])}"
    end
  end

  raise ArgumentError, "Expected a bounds (southwest/northeast) Hash, but got #{arg.class}"
end

.components(arg) ⇒ String

Converts a dict of components to the format expected by the Google Maps server.

Examples:

>> GoogleMapsService::Convert.components({"country": "US", "postal_code": "94043"})
=> "country:US|postal_code:94043"

Parameters:

  • arg (Hash)

    The component filter.

Returns:

  • (String)

Raises:

  • (ArgumentError)


103
104
105
106
107
108
109
110
# File 'lib/google_maps_service/convert.rb', line 103

def components(arg)
  if arg.kind_of?(Hash)
    arg = arg.sort.map { |k, v| "#{k}:#{v}" }
    return arg.join("|")
  end

  raise ArgumentError, "Expected a Hash for components, but got #{arg.class}"
end

.decode_polyline(polyline) ⇒ Array

Decodes a Polyline string into a list of lat/lng hash.

See the developer docs for a detailed description of this encoding: developers.google.com/maps/documentation/utilities/polylinealgorithm

Parameters:

  • polyline (String)

    An encoded polyline

Returns:

  • (Array)

    Array of hash with lat/lng keys



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/google_maps_service/convert.rb', line 158

def decode_polyline(polyline)
  points = []
  index = lat = lng = 0

  while index < polyline.length
    result = 1
    shift = 0
    while true
      b = polyline[index].ord - 63 - 1
      index += 1
      result += b << shift
      shift += 5
      break if b < 0x1f
    end
    lat += (result & 1) != 0 ? (~result >> 1) : (result >> 1)

    result = 1
    shift = 0
    while true
      b = polyline[index].ord - 63 - 1
      index += 1
      result += b << shift
      shift += 5
      break if b < 0x1f
    end
    lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1)

    points << {lat: lat * 1e-5, lng: lng * 1e-5}
  end

  points
end

.encode_polyline(points) ⇒ String

Encodes a list of points into a polyline string.

See the developer docs for a detailed description of this encoding: developers.google.com/maps/documentation/utilities/polylinealgorithm

Parameters:

  • points (Array<Hash>, Array<Array>)

    A list of lat/lng pairs.

Returns:

  • (String)


199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/google_maps_service/convert.rb', line 199

def encode_polyline(points)
  last_lat = last_lng = 0
  result = ""

  points.each do |point|
    ll = normalize_latlng(point)
    lat = (ll[0] * 1e5).round.to_i
    lng = (ll[1] * 1e5).round.to_i
    d_lat = lat - last_lat
    d_lng = lng - last_lng

    [d_lat, d_lng].each do |v|
      v = (v < 0) ? ~(v << 1) : (v << 1)
      while v >= 0x20
        result += ((0x20 | (v & 0x1f)) + 63).chr
        v >>= 5
      end
      result += (v + 63).chr
    end

    last_lat = lat
    last_lng = lng
  end

  result
end

.join_list(sep, arg) ⇒ String

If arg is list-like, then joins it with sep.

Parameters:

  • sep (String)

    Separator string.

  • arg (Array, String)

    Value to coerce into a list.

Returns:

  • (String)


59
60
61
# File 'lib/google_maps_service/convert.rb', line 59

def join_list(sep, arg)
  return as_list(arg).join(sep)
end

.latlng(arg) ⇒ String

Converts a lat/lon pair to a comma-separated string.

Examples:

>> GoogleMapsService::Convert.latlng({"lat": -33.8674869, "lng": 151.2069902})
=> "-33.867487,151.206990"

Parameters:

  • arg (Hash, Array)

    The lat/lon hash or array pair.

Returns:

  • (String)

    Comma-separated lat/lng.

Raises:

  • (ArgumentError)

    When argument is not lat/lng hash or array.



18
19
20
# File 'lib/google_maps_service/convert.rb', line 18

def latlng(arg)
  return "%f,%f" % normalize_latlng(arg)
end

.normalize_latlng(arg) ⇒ Array

Take the various lat/lng representations and return a tuple.

Accepts various representations:

  1. Hash with two entries - lat and lng

  2. Array or list - e.g. [-33, 151]

Parameters:

  • arg (Hash, Array)

    The lat/lon hash or array pair.

Returns:

  • (Array)

    Pair of lat and lng array.

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/google_maps_service/convert.rb', line 32

def normalize_latlng(arg)
  if arg.kind_of?(Hash)
      if arg.has_key?(:lat) and arg.has_key?(:lng)
          return arg[:lat], arg[:lng]
      end
      if arg.has_key?(:latitude) and arg.has_key?(:longitude)
          return arg[:latitude], arg[:longitude]
      end
      if arg.has_key?("lat") and arg.has_key?("lng")
          return arg["lat"], arg["lng"]
      end
      if arg.has_key?("latitude") and arg.has_key?("longitude")
          return arg["latitude"], arg["longitude"]
      end
  elsif arg.kind_of?(Array)
    return arg[0], arg[1]
  end

  raise ArgumentError, "Expected a lat/lng Hash or Array, but got #{arg.class}"
end

.time(arg) ⇒ String

Converts the value into a unix time (seconds since unix epoch).

Examples:

>> GoogleMapsService::Convert.time(datetime.now())
=> "1409810596"

Parameters:

  • arg (Time, Date, DateTime, Integer)

    The time.

Returns:

  • (String)

    String representation of epoch time



86
87
88
89
90
91
# File 'lib/google_maps_service/convert.rb', line 86

def time(arg)
  if arg.kind_of?(DateTime)
    arg = arg.to_time
  end
  return arg.to_i.to_s
end