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)


60
61
62
63
64
65
# File 'lib/google_maps_service/convert.rb', line 60

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)


129
130
131
132
133
134
135
136
137
# File 'lib/google_maps_service/convert.rb', line 129

def bounds(arg)
  if arg.kind_of?(Hash)
    southwest = arg[:southwest] || arg["southwest"]
    northeast = arg[:northeast] || arg["northeast"]
    return "#{latlng(southwest)}|#{latlng(northeast)}"
  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)


94
95
96
97
98
99
100
101
# File 'lib/google_maps_service/convert.rb', line 94

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



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/google_maps_service/convert.rb', line 167

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)


208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/google_maps_service/convert.rb', line 208

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)


50
51
52
# File 'lib/google_maps_service/convert.rb', line 50

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
# File 'lib/google_maps_service/convert.rb', line 32

def normalize_latlng(arg)
  if arg.kind_of?(Hash)
    lat = arg[:lat] || arg[:latitude] || arg["lat"] || arg["latitude"]
    lng = arg[:lng] || arg[:longitude] || arg["lng"] || arg["longitude"]
    return lat, lng
  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



77
78
79
80
81
82
# File 'lib/google_maps_service/convert.rb', line 77

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

.waypoints(waypoints) ⇒ String

Converts an array of waypoints (path) to the format expected by the Google Maps server.

Accept two representation of waypoint:

  1. String: Name of place or comma-separated lat/lon pair.

  2. Hash/Array: Lat/lon pair.

Parameters:

  • waypoints (Array, String, Hash)

    Path.

Returns:

  • (String)


150
151
152
153
154
155
156
157
# File 'lib/google_maps_service/convert.rb', line 150

def waypoints(waypoints)
  if waypoints.kind_of?(Array) and waypoints.length == 2 and waypoints[0].kind_of?(Numeric) and waypoints[1].kind_of?(Numeric)
    waypoints = [waypoints]
  end

  waypoints = as_list(waypoints)
  return join_list('|', waypoints.map { |k| k.kind_of?(String) ? k : latlng(k) })
end