Class: GoogleMaps::Services::Convert

Inherits:
Object
  • Object
show all
Defined in:
lib/googlemaps/services/util.rb

Overview

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

Class Method Summary collapse

Class Method Details

.bounds(arg) ⇒ String

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

Examples:

Converts lat/lng bounds to comma- and pipe-separated string

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

Parameters:

  • arg (Hash)

    The bounds. A hash with two entries - “southwest” and “northeast”.

Returns:

  • (String)

    comma- and pipe-separated string.

Raises:

  • (TypeError)


220
221
222
223
# File 'lib/googlemaps/services/util.rb', line 220

def self.bounds(arg)
  raise TypeError, "#{__method__.to_s} expected a Hash of bounds." unless arg.is_a? Hash
  "#{to_latlng(arg[:southwest])}|#{to_latlng(arg[:northeast])}"
end

.components(arg) ⇒ String

Converts a Hash of components to the format expect by the Google Maps API server.

Examples:

Converts a components hash to server-friendly string

c = {"country" => ["US", "BE"], "postal_code" => 7452}
Convert.components(c) # 'country:BE|country:US|postal_code:7452'

Parameters:

  • arg (Hash)

    The component filter.

Returns:

  • (String)

    Server-friendly string representation

Raises:

  • (TypeError)


200
201
202
203
204
205
206
# File 'lib/googlemaps/services/util.rb', line 200

def self.components(arg)
  raise TypeError, "#{__method__.to_s} expected a Hash of components." unless arg.is_a? Hash

  arg.map { |c, val|
    ArrayBox.wrap(val).map {|elem| "#{c}:#{elem}"}.sort_by(&:downcase)
  }.join('|')
end

.decode_polyline(polyline) ⇒ Array

Decodes a Polyline string into an array of lat/lng hashes.

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

Parameters:

  • polyline (String)

    An encoded polyline.

Returns:

  • (Array)

    an array of lat/lng hashes.

Raises:

  • (TypeError)


266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/googlemaps/services/util.rb', line 266

def self.decode_polyline(polyline)
  raise TypeError, "#{__method__.to_s} expected an argument of type String." unless polyline.is_a? String
  points = Array.new
  index, lat, lng = 0, 0, 0

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

    points.push({:lat => lat * 1e-5, :lng => lng * 1e-5})
  end
  points
end

.encode_polyline(points) ⇒ String

Encodes an array of points into a polyline string.

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

Parameters:

  • points (Array)

    Array of lat/lng hashes.

Returns:

  • (String)

    a polyline string.

Raises:

  • (TypeError)


233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/googlemaps/services/util.rb', line 233

def self.encode_polyline(points)
  raise TypeError, "#{__method__.to_s} expected an Array of points." unless points.is_a? Array
  last_lat, last_lng = 0, 0
  result = ''
  points.each { |point|
    lat = (point[:lat] * 1e5).round.to_i
    lng = (point[:lng] * 1e5).round.to_i
    delta_lat = lat - last_lat
    delta_lng = lng - last_lng

    [delta_lat, delta_lng].each { |val|
      val = (val < 0) ? ~(val << 1) : (val << 1)
      while val >= 0x20
        result += ((0x20 | (val & 0x1f)) + 63).chr
        val >>= 5
      end
      result += (val + 63).chr
    }

    last_lat = lat
    last_lng = lng
  }
  result
end

.format_float(arg) ⇒ String

Formats a float value to as short as possible.

Examples:

Formats the lat or lng float

Convert.format_float(45.1289700)

Parameters:

  • arg (Float)

    The lat or lng float.

Returns:

  • (String)

    formatted value of lat or lng float



164
165
166
# File 'lib/googlemaps/services/util.rb', line 164

def self.format_float(arg)
  arg.to_s.chomp('0').chomp('.')
end

.get_mime_type(content_type) ⇒ String

Returns the MIME type from the given header value.

Parameters:

  • content_type (String)

    The Content-Type header value.

Returns:

  • (String)

    the MIME type value.



324
325
326
# File 'lib/googlemaps/services/util.rb', line 324

def self.get_mime_type(content_type)
  content_type.split(';').first
end

.join_array(sep, arg) ⇒ String

If arg is array-like, then joins it with sep

Parameters:

  • sep (String)

    Separator string.

  • arg (Object)

    Object to coerce into an array.

Returns:

  • (String)

    a joined string.



188
189
190
# File 'lib/googlemaps/services/util.rb', line 188

def self.join_array(sep, arg)
  ArrayBox.wrap(arg).join(sep)
end

.piped_location(arg) ⇒ String

Joins an array of locations into a pipe separated string, handling the various formats supported for lat/lng values.

Examples:

Joins the locations array to pipe-separated string

arr = [{ :lat => -33.987486, :lng => 151.217990}, "Brussels"]
Convert.piped_location(arr) # '-33.987486,151.21799|Brussels'

Parameters:

  • arg (Array)

    Array of locations.

Returns:

  • (String)

    pipe-separated string.

Raises:

  • (TypeError)


177
178
179
180
# File 'lib/googlemaps/services/util.rb', line 177

def self.piped_location(arg)
  raise TypeError, "#{__method__.to_s} expected argument to be an Array." unless arg.instance_of? Array
  arg.map { |location| to_latlng(location) }.join('|')
end

.rectangular_dimensions(size) ⇒ String

Returns the rectangular dimensions in the form horizontal_valuexvertical_value.

Examples:

Convert.rectangular_dimensions({:length => 500, :width => 400}) # "500x400"

Parameters:

  • size (Hash)

    The size hash.

Returns:

  • (String)

    a string value in the form “lengthxwidth”.

Raises:

  • (TypeError)


336
337
338
339
# File 'lib/googlemaps/services/util.rb', line 336

def self.rectangular_dimensions(size)
  raise TypeError, "#{__method__.to_s} expected a Hash." unless size.is_a? Hash
  "#{size[:length]}x#{size[:width]}"
end

.shortest_path(locations) ⇒ String

Returns the shortest representation of the given locations.

The Elevation API limits requests to 2000 characters, and accepts multiple locations either as pipe-delimited lat/lng values, or an encoded polyline, so we determine which is shortest and use it.

Parameters:

  • locations (Array)

    The lat/lng array.

Returns:

  • (String)

    shortest path.

Raises:

  • (TypeError)


312
313
314
315
316
317
# File 'lib/googlemaps/services/util.rb', line 312

def self.shortest_path(locations)
  raise TypeError, "#{__method__.to_s} expected an Array of locations." unless locations.is_a? Array
  encoded = "enc:#{encode_polyline(locations)}"
  unencoded = piped_location(locations)
  encoded.length < unencoded.length ? encoded : unencoded
end

.to_latlng(arg) ⇒ String

Converts a lat/lng value to a comma-separated string.

Examples:

Convert lat/lng value to comma-separated string

Convert.to_latlng("45.458878,-39.56487")
Convert.to_latlng("Brussels")
Convert.to_latlng({ :lat => 45.458878, :lng => -39.56487 })

Parameters:

  • arg (String, Hash)

    The lat/lng value.

Returns:

  • (String)

    comma-separated string.



146
147
148
149
150
151
152
153
154
155
# File 'lib/googlemaps/services/util.rb', line 146

def self.to_latlng(arg)
  case arg
  when String
    arg
  when Hash
    "#{self.format_float(arg[:lat])},#{self.format_float(arg[:lng])}"
  else
    raise TypeError, "#{__method__.to_s} expected location to be String or Hash."
  end
end

.unix_time(val) ⇒ String

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

Examples:

converts value to unix time

Convert.unix_time(1472809264)
Convert.unix_time(Time.now)
Convert.unix_time(Date.parse("2016-09-02"))

Parameters:

  • val (Integer, Time, Date)

    value to convert to unix time format.

Returns:

  • (String)

    seconds since unix epoch.



124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/googlemaps/services/util.rb', line 124

def self.unix_time(val)
  case val
  when Integer
    val.to_s
  when Time
    val.to_i.to_s
  when Date
    val.to_time.to_i.to_s
  else
    raise TypeError, "#{__method__.to_s} expected value to be Integer, Time or Date."
  end
end