Module: GoogleMapsService::Polyline

Defined in:
lib/google_maps_service/polyline.rb

Overview

Encoder/decoder for [Google Encoded Polyline](developers.google.com/maps/documentation/utilities/polylinealgorithm).

Class Method Summary collapse

Class Method Details

.decode(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

Examples:

encoded_path = '_p~iF~ps|U_ulLnnqC_mqNvxq`@'
path = GoogleMapsService::Polyline.decode(encoded_path)
#=> [{:lat=>38.5, :lng=>-120.2}, {:lat=>40.7, :lng=>-120.95}, {:lat=>43.252, :lng=>-126.45300000000002}]


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/google_maps_service/polyline.rb', line 21

def decode(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
    loop do
      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(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



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/google_maps_service/polyline.rb', line 62

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

  points.each do |point|
    ll = GoogleMapsService::Convert.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