Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactor entire step process.

  • Loading branch information...
commit 6e5a9995b8fad1cfe77e1a964cb5c8349442de67 1 parent ebf4e26
@joshuaclayton authored
Showing with 142 additions and 122 deletions.
  1. +110 −4 lib/polylines/base.rb
  2. +19 −63 lib/polylines/decoder.rb
  3. +13 −55 lib/polylines/encoder.rb
View
114 lib/polylines/base.rb
@@ -1,11 +1,117 @@
module Polylines
class Base
- def self.step_5(number)
- ~number
+ attr_reader :current_value, :negative
+
+ def initialize(current_value)
+ @current_value = current_value
+ end
+
+ def step_2
+ @negative = current_value < 0 if encoding?
+
+ encode! { (current_value * 1e5).round }
+ decode! { current_value.to_f/1e5 }
+ end
+
+ def step_3
+ return unless negative
+ encode! { ~(current_value * -1) + 1 }
+ decode! { ~(current_value - 1) * -1 }
+ end
+
+ def step_4
+ encode! { current_value << 1 }
+ decode! { current_value >> 1 }
+ end
+
+ def step_5
+ return unless negative
+ encode! { ~current_value }
+ decode! { ~current_value }
+ end
+
+ def step_6
+ encode! do
+ [].tap do |numbers|
+ while current_value > 0 do
+ numbers.unshift(current_value & 0x1f)
+ @current_value >>= 5
+ end
+ end
+ end
+
+ decode! do
+ current_value.map {|chunk| "%05b" % chunk }.join.tap do |val|
+ @negative = val[-1, 1] == "1"
+ end.to_i(2)
+ end
+ end
+
+ def step_7
+ encode! { current_value.reverse }
+ decode! { current_value.reverse }
+ end
+
+ def step_8
+ encode! { current_value[0..-2].map {|item| item | 0x20 } << current_value.last }
+ decode! { current_value[0..-2].map {|item| item ^ 0x20 } << current_value.last }
end
- def self.step_7(five_bit_chunks)
- five_bit_chunks.reverse
+ def step_10
+ encode! { current_value.map {|value| value + 63 } }
+ decode! { current_value.map {|value| value - 63 } }
+ end
+
+ def step_11
+ encode! { current_value.map(&:chr).join }
+ decode! { current_value.split(//).map {|char| char[0] } }
+ end
+
+ def encode!
+ if encoding?
+ @current_value = yield
+ end
+ end
+
+ def decode!
+ if decoding?
+ @current_value = yield
+ end
+ end
+
+ def encoding?
+ self.is_a?(Polylines::Encoder)
+ end
+
+ def decoding?
+ self.is_a?(Polylines::Decoder)
+ end
+
+ def self.transform_to_array_of_lat_lng_and_deltas(value)
+ if self == Polylines::Encoder
+ delta_latitude, delta_longitude = 0, 0
+
+ return value.inject([]) do |polyline, (latitude, longitude)|
+ polyline << latitude - delta_latitude
+ polyline << longitude - delta_longitude
+ delta_latitude, delta_longitude = latitude, longitude
+ polyline
+ end
+ end
+
+ if self == Polylines::Decoder
+ set = []
+ return value.split(//).inject([]) do |charset, char|
+ set << char
+
+ if ((char[0] - 63) & 0x20) == 0
+ charset << set.join
+ set = []
+ end
+
+ charset
+ end.map {|charset| decode(charset) }
+ end
end
end
end
View
82 lib/polylines/decoder.rb
@@ -1,76 +1,32 @@
module Polylines
class Decoder < Base
def self.decode_polyline(polyline)
- set = []
+ points_with_deltas = transform_to_array_of_lat_lng_and_deltas(polyline)
- points_with_deltas = polyline.split(//).inject([]) do |charset, char|
- set << char
+ [].tap do |points|
+ points << [points_with_deltas.shift, points_with_deltas.shift]
- if ((char[0] - 63) & 0x20) == 0
- charset << set.join
- set = []
+ while points_with_deltas.any?
+ points << [
+ points.last[0] + points_with_deltas.shift,
+ points.last[1] + points_with_deltas.shift
+ ]
end
-
- charset
- end.map {|charset| decode(charset) }
-
- points = [[points_with_deltas.shift, points_with_deltas.shift]]
-
- while points_with_deltas.any?
- new_latitude = points.last[0] + points_with_deltas.shift
- new_longitude = points.last[1] + points_with_deltas.shift
- points << [new_latitude, new_longitude]
end
-
- points
end
def self.decode(string)
- decimal_values = step_11(string)
- decimal_values = step_10(decimal_values)
- xord_values = step_8(decimal_values)
- five_bit_chunks = step_7(xord_values)
- binary_string = step_6(five_bit_chunks)
-
- negative = binary_string[-1, 1] == "1"
-
- number = binary_string.to_i(2)
- number = step_5(number) if negative
- number = step_4(number)
- number = step_3(number) if negative
- step_2(number)
- end
-
- def self.step_2(number)
- number.to_f/1e5
- end
-
- def self.step_3(number)
- number -= 1
- number = ~number
- number *= -1
- end
-
- def self.step_4(number)
- number >> 1
- end
-
- def self.step_6(five_bit_chunks)
- five_bit_chunks.map do |chunk|
- "%05b" % chunk
- end.join
- end
-
- def self.step_8(decimal_values)
- decimal_values[0..-2].map {|value| 0x20 ^ value } << decimal_values.last
- end
-
- def self.step_10(values)
- values.map {|value| value - 63 }
- end
-
- def self.step_11(string)
- string.split(//).map {|char| char[0] }
+ self.new(string).tap do |decoding|
+ decoding.step_11
+ decoding.step_10
+ decoding.step_8
+ decoding.step_7
+ decoding.step_6
+ decoding.step_5
+ decoding.step_4
+ decoding.step_3
+ decoding.step_2
+ end.current_value
end
end
end
View
68 lib/polylines/encoder.rb
@@ -1,64 +1,22 @@
module Polylines
class Encoder < Base
def self.encode_points(points)
- delta_latitude, delta_longitude = 0, 0
-
- points.inject([]) do |polyline, (latitude, longitude)|
- polyline << encode(latitude - delta_latitude)
- polyline << encode(longitude - delta_longitude)
- delta_latitude, delta_longitude = latitude, longitude
- polyline
- end.join
+ points_with_deltas = transform_to_array_of_lat_lng_and_deltas(points)
+ points_with_deltas.map {|point| encode(point) }.join
end
def self.encode(number)
- negative = number < 0
- number = step_2(number)
- number = step_3(number) if negative
- number = step_4(number)
- number = step_5(number) if negative
-
- five_bit_chunks = step_6(number)
- five_bit_chunks = step_7(five_bit_chunks)
- ord_values = step_8(five_bit_chunks)
- decimal_values = step_10(ord_values)
-
- step_11(decimal_values)
- end
-
- def self.step_2(number)
- (number * 1e5).round
- end
-
- def self.step_3(number)
- number *= -1
- number = ~number
- number += 1
- end
-
- def self.step_4(number)
- number << 1
- end
-
- def self.step_6(number)
- [].tap do |numbers|
- while number > 0 do
- numbers.unshift(number & 0x1f)
- number = number >> 5
- end
- end
- end
-
- def self.step_8(five_bit_chunks)
- five_bit_chunks[0..-2].map {|chunk| 0x20 | chunk } << five_bit_chunks.last
- end
-
- def self.step_10(values)
- values.map {|value| value + 63 }
- end
-
- def self.step_11(values)
- values.map(&:chr).join
+ self.new(number).tap do |encoding|
+ encoding.step_2
+ encoding.step_3
+ encoding.step_4
+ encoding.step_5
+ encoding.step_6
+ encoding.step_7
+ encoding.step_8
+ encoding.step_10
+ encoding.step_11
+ end.current_value
end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.