simplify_rb 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +32 -14
- data/Rakefile +2 -2
- data/lib/simplify_rb/douglas_peucker_simplifier.rb +82 -0
- data/lib/simplify_rb/point.rb +39 -0
- data/lib/simplify_rb/radial_distance_simplifier.rb +18 -0
- data/lib/simplify_rb/version.rb +1 -1
- data/lib/simplify_rb.rb +12 -93
- data/spec/simplify_rb/point_spec.rb +70 -0
- data/spec/simplify_rb_spec.rb +16 -0
- metadata +7 -5
- data/lib/simplify_rb/symbolizer.rb +0 -13
- data/spec/symbolizer_spec.rb +0 -24
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 33cd91e84b17826cf512f3b17083e297b65c3268
         | 
| 4 | 
            +
              data.tar.gz: 48d4337b44170364e78f3e206e5b19a90a84d567
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fd402062db3e2892fd4a1ce5aa8223b47f03daf465be61d397b874c19630aaa7085269ade4ed93c1be6cb45f61d1e092075e962587c3f174383cfd27aaa12468
         | 
| 7 | 
            +
              data.tar.gz: 9a4baf26c41e5d912767840a811847d1bd65b3ccac19e16b9b743a2a7ef5ac21d515f944c92631e8fbe55aa280b47c6029aec77d7c50a5f86234f46cc86be72a
         | 
    
        data/README.md
    CHANGED
    
    | @@ -6,20 +6,6 @@ SimplifyRb is a Ruby port of [simplify.js](https://github.com/mourner/simplify-j | |
| 6 6 |  | 
| 7 7 | 
             
            You can use this gem to reduce the number of points in a complex polyline / polygon, making use of an optimized Douglas-Peucker algorithm.
         | 
| 8 8 |  | 
| 9 | 
            -
            ## Installation
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            Add this line to your application's Gemfile:
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                gem 'simplify_rb'
         | 
| 14 | 
            -
             | 
| 15 | 
            -
            And then execute:
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                $ bundle
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            Or install it yourself as:
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                $ gem install simplify_rb
         | 
| 22 | 
            -
             | 
| 23 9 | 
             
            ## Usage
         | 
| 24 10 |  | 
| 25 11 | 
             
            ```ruby
         | 
| @@ -40,3 +26,35 @@ SimplifyRb::Simplifier.new.process(points, tolerance, high_quality) | |
| 40 26 | 
             
            ```tolerance```: (optional, 1 by default): Affects the amount of simplification that occurs (the smaller, the less simplification).
         | 
| 41 27 |  | 
| 42 28 | 
             
            ```high_quality```: (optional, False by default): Flag to exclude the distance pre-processing. Produces higher quality results when true is passed, but runs slower.
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            ### Custom points
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            You can also use custom points, such as a struct or object which responds to `:x` and `:y`, rather than hashes:
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            ```ruby
         | 
| 35 | 
            +
            CustomPointStruct = Struct.new(:x, :y)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            custom_points = [
         | 
| 38 | 
            +
              CustomPointStruct.new(51.5256, -0.0875),
         | 
| 39 | 
            +
              CustomPointStruct.new(51.7823, -0.0912)
         | 
| 40 | 
            +
            ]
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            tolerance = 1
         | 
| 43 | 
            +
            high_quality = true
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            SimplifyRb::Simplifier.new.process(custom_points, tolerance, high_quality)
         | 
| 46 | 
            +
            ```
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            ## Installation
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            Add this line to your application's Gemfile:
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                gem 'simplify_rb'
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            And then execute:
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                $ bundle
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            Or install it yourself as:
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                $ gem install simplify_rb
         | 
    
        data/Rakefile
    CHANGED
    
    
| @@ -0,0 +1,82 @@ | |
| 1 | 
            +
            # Optimized Douglas-Peucker algorithm
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module SimplifyRb
         | 
| 4 | 
            +
              class DouglasPeuckerSimplifier
         | 
| 5 | 
            +
                def process(points, sq_tolerance)
         | 
| 6 | 
            +
                  points.first.keep = true
         | 
| 7 | 
            +
                  points.last.keep  = true
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  simplify_douglas_peucker(points, sq_tolerance)
         | 
| 10 | 
            +
                    .select(&:keep)
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                private
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                MaxSqDist = Struct.new(:max_sq_dist, :index)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def simplify_douglas_peucker(points, sq_tolerance)
         | 
| 18 | 
            +
                  first_i = 0
         | 
| 19 | 
            +
                  last_i  = points.length - 1
         | 
| 20 | 
            +
                  index = nil
         | 
| 21 | 
            +
                  stack = []
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  while last_i
         | 
| 24 | 
            +
                    result = calc_max_sq_dist(first_i, last_i, points)
         | 
| 25 | 
            +
                    index = result.index
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    if result.max_sq_dist > sq_tolerance
         | 
| 28 | 
            +
                      points[index].keep = true
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                      stack.push(first_i, index, index, last_i)
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    first_i, last_i = stack.pop(2)
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  points
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def calc_max_sq_dist(first_i, last_i, points)
         | 
| 40 | 
            +
                  index = nil
         | 
| 41 | 
            +
                  max_sq_dist = 0
         | 
| 42 | 
            +
                  range = (first_i + 1)...last_i
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  range.each do |i|
         | 
| 45 | 
            +
                    sq_dist = get_sq_seg_dist(points[i], points[first_i], points[last_i])
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    if sq_dist > max_sq_dist
         | 
| 48 | 
            +
                      index = i
         | 
| 49 | 
            +
                      max_sq_dist = sq_dist
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  MaxSqDist.new(max_sq_dist, index)
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # Square distance from a point to a segment
         | 
| 57 | 
            +
                def get_sq_seg_dist(point, point_1, point_2)
         | 
| 58 | 
            +
                  x  = point_1.x
         | 
| 59 | 
            +
                  y  = point_1.y
         | 
| 60 | 
            +
                  dx = point_2.x - x
         | 
| 61 | 
            +
                  dy = point_2.y - y
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  if dx != 0 || dy != 0
         | 
| 64 | 
            +
                    t = ((point.x - x) * dx + (point.y - y) * dy) / (dx * dx + dy * dy)
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    if t > 1
         | 
| 67 | 
            +
                      x = point_2.x
         | 
| 68 | 
            +
                      y = point_2.y
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                    elsif t > 0
         | 
| 71 | 
            +
                      x += dx * t
         | 
| 72 | 
            +
                      y += dy * t
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  dx = point.x - x
         | 
| 77 | 
            +
                  dy = point.y - y
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  dx * dx + dy * dy
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
            end
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            module SimplifyRb
         | 
| 2 | 
            +
              class Point
         | 
| 3 | 
            +
                attr_reader :x, :y, :original_entity
         | 
| 4 | 
            +
                attr_accessor :keep
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                def initialize(raw_point)
         | 
| 7 | 
            +
                  @original_entity = raw_point
         | 
| 8 | 
            +
                  @x, @y = parse_x_y(raw_point)
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def get_sq_dist_to(other_point)
         | 
| 12 | 
            +
                  dx = x - other_point.x
         | 
| 13 | 
            +
                  dy = y - other_point.y
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  dx * dx + dy * dy
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                private
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def parse_x_y(raw_point)
         | 
| 21 | 
            +
                  x = nil
         | 
| 22 | 
            +
                  y = nil
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  if raw_point.kind_of? Hash
         | 
| 25 | 
            +
                    x = raw_point[:x] || raw_point['x']
         | 
| 26 | 
            +
                    y = raw_point[:y] || raw_point['y']
         | 
| 27 | 
            +
                  elsif raw_point.respond_to?(:x) && raw_point.respond_to?(:y)
         | 
| 28 | 
            +
                    x = raw_point.x
         | 
| 29 | 
            +
                    y = raw_point.y
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  if x.nil? || y.nil?
         | 
| 33 | 
            +
                    raise ArgumentError.new('Points must have :x and :y values')
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  [x, y]
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            # Basic distance-based simplification
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module SimplifyRb
         | 
| 4 | 
            +
              class RadialDistanceSimplifier
         | 
| 5 | 
            +
                def process(points, sq_tolerance)
         | 
| 6 | 
            +
                  new_points = [points.first]
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  points.each do |point|
         | 
| 9 | 
            +
                    sq_dist = point.get_sq_dist_to(new_points.last)
         | 
| 10 | 
            +
                    new_points << point if sq_dist > sq_tolerance
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  new_points << points.last unless new_points.last == points.last
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  new_points
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
    
        data/lib/simplify_rb/version.rb
    CHANGED
    
    
    
        data/lib/simplify_rb.rb
    CHANGED
    
    | @@ -1,107 +1,26 @@ | |
| 1 1 | 
             
            require 'simplify_rb/version'
         | 
| 2 | 
            -
            require 'simplify_rb/ | 
| 2 | 
            +
            require 'simplify_rb/point'
         | 
| 3 | 
            +
            require 'simplify_rb/radial_distance_simplifier'
         | 
| 4 | 
            +
            require 'simplify_rb/douglas_peucker_simplifier'
         | 
| 3 5 |  | 
| 4 6 | 
             
            module SimplifyRb
         | 
| 5 7 | 
             
              class Simplifier
         | 
| 6 | 
            -
                def process( | 
| 7 | 
            -
                  raise ArgumentError.new('Points must be an array') unless  | 
| 8 | 
            +
                def process(raw_points, tolerance = 1, highest_quality = false)
         | 
| 9 | 
            +
                  raise ArgumentError.new('Points must be an array') unless raw_points.is_a? Array
         | 
| 8 10 |  | 
| 9 | 
            -
                  return  | 
| 10 | 
            -
             | 
| 11 | 
            -
                  symbolizer = Symbolizer.new
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                  points = symbolizer.symbolize_keys(points) unless points.all? { |p| symbolizer.keys_are_symbols?(p.keys) }
         | 
| 11 | 
            +
                  return raw_points if raw_points.length <= 1
         | 
| 14 12 |  | 
| 15 13 | 
             
                  sq_tolerance = tolerance * tolerance
         | 
| 16 14 |  | 
| 17 | 
            -
                   | 
| 18 | 
            -
                  points = simplify_radial_dist(points, sq_tolerance) unless highest_quality
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  # Optimisation step 2
         | 
| 21 | 
            -
                  simplify_douglas_peucker(points, sq_tolerance)
         | 
| 22 | 
            -
                end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                private
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                # Basic distance-based simplification
         | 
| 27 | 
            -
                def simplify_radial_dist(points, sq_tolerance)
         | 
| 28 | 
            -
                  new_points = [points.first]
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                  points.each do |point|
         | 
| 31 | 
            -
                    new_points << point if (get_sq_dist(point, new_points.last) > sq_tolerance)
         | 
| 32 | 
            -
                  end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                  new_points << points.last unless new_points.last == points.last
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                  new_points
         | 
| 37 | 
            -
                end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                # Simplification using optimized Douglas-Peucker algorithm with recursion elimination
         | 
| 40 | 
            -
                def simplify_douglas_peucker(points, sq_tolerance)
         | 
| 41 | 
            -
                  first = 0
         | 
| 42 | 
            -
                  last  = points.length - 1
         | 
| 43 | 
            -
                  index = nil
         | 
| 44 | 
            -
                  stack = []
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                  points.first[:keep] = true
         | 
| 47 | 
            -
                  points.last[:keep]  = true
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                  while last
         | 
| 50 | 
            -
                    max_sq_dist = 0
         | 
| 15 | 
            +
                  points = raw_points.map { |p| Point.new(p) }
         | 
| 51 16 |  | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
                      if sq_dist > max_sq_dist
         | 
| 56 | 
            -
                        index = i
         | 
| 57 | 
            -
                        max_sq_dist = sq_dist
         | 
| 58 | 
            -
                      end
         | 
| 59 | 
            -
                    end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                    if max_sq_dist > sq_tolerance
         | 
| 62 | 
            -
                      points[index][:keep] = true
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                      stack.push(first, index, index, last)
         | 
| 65 | 
            -
                    end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                    first, last = stack.pop(2)
         | 
| 68 | 
            -
                  end # end while
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                  points.select { |p| p[:keep] && p.delete(:keep) }
         | 
| 71 | 
            -
                end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                # Square distance between two points
         | 
| 74 | 
            -
                def get_sq_dist(point_1, point_2)
         | 
| 75 | 
            -
                  dx = point_1[:x] - point_2[:x]
         | 
| 76 | 
            -
                  dy = point_1[:y] - point_2[:y]
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                  dx * dx + dy * dy
         | 
| 79 | 
            -
                end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                # Square distance from a point to a segment
         | 
| 82 | 
            -
                def get_sq_seg_dist(point, point_1, point_2)
         | 
| 83 | 
            -
                  x  = point_1[:x]
         | 
| 84 | 
            -
                  y  = point_1[:y]
         | 
| 85 | 
            -
                  dx = point_2[:x] - x
         | 
| 86 | 
            -
                  dy = point_2[:y] - y
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                  if dx != 0 || dy != 0
         | 
| 89 | 
            -
                    t = ((point[:x] - x) * dx + (point[:y] - y) * dy) / (dx * dx + dy * dy)
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                    if t > 1
         | 
| 92 | 
            -
                      x = point_2[:x]
         | 
| 93 | 
            -
                      y = point_2[:y]
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                    elsif t > 0
         | 
| 96 | 
            -
                      x += dx * t
         | 
| 97 | 
            -
                      y += dy * t
         | 
| 98 | 
            -
                    end
         | 
| 17 | 
            +
                  unless highest_quality
         | 
| 18 | 
            +
                    points = RadialDistanceSimplifier.new.process(points, sq_tolerance)
         | 
| 99 19 | 
             
                  end
         | 
| 100 20 |  | 
| 101 | 
            -
                   | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
                  dx * dx + dy * dy
         | 
| 21 | 
            +
                  DouglasPeuckerSimplifier.new
         | 
| 22 | 
            +
                    .process(points, sq_tolerance)
         | 
| 23 | 
            +
                    .map(&:original_entity)
         | 
| 105 24 | 
             
                end
         | 
| 106 25 | 
             
              end
         | 
| 107 26 | 
             
            end
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'simplify_rb/point'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe SimplifyRb::Point do
         | 
| 5 | 
            +
              describe 'parsing hashes with string keys' do
         | 
| 6 | 
            +
                it 'determines the :x, :y value' do
         | 
| 7 | 
            +
                  raw_point = { "x" => 51.5256, "y" => -0.0875 }
         | 
| 8 | 
            +
                  point = described_class.new(raw_point)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  expect(point.x).to eq(51.5256)
         | 
| 11 | 
            +
                  expect(point.y).to eq(-0.0875)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              describe 'parsing structs' do
         | 
| 16 | 
            +
                it 'determines the :x, :y value' do
         | 
| 17 | 
            +
                  CustomPointStruct = Struct.new(:x, :y)
         | 
| 18 | 
            +
                  raw_point = CustomPointStruct.new(51.5256, -0.0875)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  point = described_class.new(raw_point)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  expect(point.x).to eq(51.5256)
         | 
| 23 | 
            +
                  expect(point.y).to eq(-0.0875)
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              describe 'handling raw points which are objects' do
         | 
| 28 | 
            +
                it 'determines the :x, :y value' do
         | 
| 29 | 
            +
                  class MyCustomPoint
         | 
| 30 | 
            +
                    attr_reader :x, :y
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    def initialize(x, y)
         | 
| 33 | 
            +
                      @x = x
         | 
| 34 | 
            +
                      @y = y
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  raw_point = MyCustomPoint.new(51.5256, -0.0875)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  point = described_class.new(raw_point)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  expect(point.x).to eq(51.5256)
         | 
| 43 | 
            +
                  expect(point.y).to eq(-0.0875)
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              describe 'missing x/y values' do
         | 
| 48 | 
            +
                it 'raises an error if the points are missing keys' do
         | 
| 49 | 
            +
                  invalid_point = { Z: 51.5256, y: -0.0875 }
         | 
| 50 | 
            +
                  expect { described_class.new(invalid_point) }.to raise_error(ArgumentError, 'Points must have :x and :y values')
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  invalid_point = { x: 51.5256, Z: -0.0875 }
         | 
| 53 | 
            +
                  expect { described_class.new(invalid_point) }.to raise_error(ArgumentError, 'Points must have :x and :y values')
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                it 'raises an error if points don\'t respond to x / y' do
         | 
| 57 | 
            +
                  class UnconventialPoint
         | 
| 58 | 
            +
                    attr_reader :a, :b
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    def initialize(a, b)
         | 
| 61 | 
            +
                      @a = a
         | 
| 62 | 
            +
                      @b = b
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  invalid_point = UnconventialPoint.new(51.5256, -0.0875)
         | 
| 67 | 
            +
                  expect { described_class.new(invalid_point) }.to raise_error(ArgumentError, 'Points must have :x and :y values')
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
            end
         | 
    
        data/spec/simplify_rb_spec.rb
    CHANGED
    
    | @@ -20,6 +20,22 @@ describe SimplifyRb::Simplifier do | |
| 20 20 | 
             
                  end
         | 
| 21 21 | 
             
                end
         | 
| 22 22 |  | 
| 23 | 
            +
                describe 'extra properties on the data' do
         | 
| 24 | 
            +
                  it 'preserves the extra properties' do
         | 
| 25 | 
            +
                    richer_data = [
         | 
| 26 | 
            +
                      { x: 51.5256, y: -0.0875, note: 'Foo bar' },
         | 
| 27 | 
            +
                      { x: 51.7823, y: -0.0912, attr: 123 }
         | 
| 28 | 
            +
                    ]
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    result = subject.process(richer_data, 5, true)
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    expect(result.length).to eq 2
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    expect(result.first[:note]).to eq 'Foo bar'
         | 
| 35 | 
            +
                    expect(result.last[:attr]).to eq 123
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 23 39 | 
             
                context 'only one point' do
         | 
| 24 40 | 
             
                  it 'returns a list with one point' do
         | 
| 25 41 | 
             
                    data = [{ x: 1, y: 2 }]
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: simplify_rb
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.3.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - odlp
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016- | 
| 11 | 
            +
            date: 2016-08-28 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -69,15 +69,17 @@ files: | |
| 69 69 | 
             
            - Rakefile
         | 
| 70 70 | 
             
            - example/example.rb
         | 
| 71 71 | 
             
            - lib/simplify_rb.rb
         | 
| 72 | 
            -
            - lib/simplify_rb/ | 
| 72 | 
            +
            - lib/simplify_rb/douglas_peucker_simplifier.rb
         | 
| 73 | 
            +
            - lib/simplify_rb/point.rb
         | 
| 74 | 
            +
            - lib/simplify_rb/radial_distance_simplifier.rb
         | 
| 73 75 | 
             
            - lib/simplify_rb/version.rb
         | 
| 74 76 | 
             
            - simplify_rb.gemspec
         | 
| 75 77 | 
             
            - spec/fixtures/all-points.yml
         | 
| 76 78 | 
             
            - spec/fixtures/result-fast.yml
         | 
| 77 79 | 
             
            - spec/fixtures/result-high-quality.yml
         | 
| 80 | 
            +
            - spec/simplify_rb/point_spec.rb
         | 
| 78 81 | 
             
            - spec/simplify_rb_spec.rb
         | 
| 79 82 | 
             
            - spec/spec_helper.rb
         | 
| 80 | 
            -
            - spec/symbolizer_spec.rb
         | 
| 81 83 | 
             
            homepage: https://github.com/odlp/simplify_rb
         | 
| 82 84 | 
             
            licenses:
         | 
| 83 85 | 
             
            - MIT
         | 
| @@ -106,6 +108,6 @@ test_files: | |
| 106 108 | 
             
            - spec/fixtures/all-points.yml
         | 
| 107 109 | 
             
            - spec/fixtures/result-fast.yml
         | 
| 108 110 | 
             
            - spec/fixtures/result-high-quality.yml
         | 
| 111 | 
            +
            - spec/simplify_rb/point_spec.rb
         | 
| 109 112 | 
             
            - spec/simplify_rb_spec.rb
         | 
| 110 113 | 
             
            - spec/spec_helper.rb
         | 
| 111 | 
            -
            - spec/symbolizer_spec.rb
         | 
| @@ -1,13 +0,0 @@ | |
| 1 | 
            -
            module SimplifyRb
         | 
| 2 | 
            -
              class Symbolizer
         | 
| 3 | 
            -
                def keys_are_symbols?(keys)
         | 
| 4 | 
            -
                  keys.all? { |k| k.is_a? Symbol }
         | 
| 5 | 
            -
                end
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                def symbolize_keys(collection)
         | 
| 8 | 
            -
                  collection.map do |item|
         | 
| 9 | 
            -
                    item.each_with_object({}) { |(k,v), memo| memo[k.to_sym] = v }
         | 
| 10 | 
            -
                  end
         | 
| 11 | 
            -
                end
         | 
| 12 | 
            -
              end
         | 
| 13 | 
            -
            end
         | 
    
        data/spec/symbolizer_spec.rb
    DELETED
    
    | @@ -1,24 +0,0 @@ | |
| 1 | 
            -
            require 'spec_helper'
         | 
| 2 | 
            -
            require 'simplify_rb/symbolizer'
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            describe SimplifyRb::Symbolizer do
         | 
| 5 | 
            -
              describe '#keys_are_symbols?' do
         | 
| 6 | 
            -
                it 'returns false if any key is not a Symbol' do
         | 
| 7 | 
            -
                  expect(subject.keys_are_symbols?([:a, 'b', :c])).to equal(false)
         | 
| 8 | 
            -
                end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                it 'returns return true if all the keys are Symbols' do
         | 
| 11 | 
            -
                  expect(subject.keys_are_symbols?([:a, :b, :c])).to equal(true)
         | 
| 12 | 
            -
                end
         | 
| 13 | 
            -
              end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
              describe '#symbolize_keys' do
         | 
| 16 | 
            -
                it 'converts all of the collection\'s keys to symbols' do
         | 
| 17 | 
            -
                  collection = [{ 'a' => 1, 'b' => 2 }, { 'c' => 3 }]
         | 
| 18 | 
            -
                  symbolized_result = subject.symbolize_keys(collection)
         | 
| 19 | 
            -
                  expected_result = [{ a: 1, b: 2 }, { c: 3 }]
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                  expect(symbolized_result).to eq(expected_result)
         | 
| 22 | 
            -
                end
         | 
| 23 | 
            -
              end
         | 
| 24 | 
            -
            end
         |