Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 7f19866b5b
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 74 lines (58 sloc) 1.744 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
class MapDataExtractor::PathsExtractor
  def initialize(image, nodes)
    @image = image
    @view = image.view(0, 0, image.columns, image.rows)
    @nodes = nodes
  end


  def paths
    # Find path's starting points from each node.
    start_points = Hash.new { |k, v| k[v] = [] }
    @nodes.each do |node|
      node[:points].each do |point|
        x, y = point
        pixel = @view[y][x]

        start_points[node] << point if pixel.opacity == 0
      end
    end

    # Follow the path for each starting point found.
    paths = []
    start_points.each do |node, start_points|
      start_points.each do |starting_point|
        color = @image.pixel_color(*starting_point)
        steps = [ starting_point ]

        begin
          point = point_with_colour_around(color, steps[-1], steps[-2])
          steps << point if point
        end while point

        arrival_node = node_for_point(steps[-1], @nodes)
        paths << { from: node, to: arrival_node, points: steps }
      end
    end

    paths
  end


  private


  # Return the first point with the given color around given coordinates.
  def point_with_colour_around(color, origin_point, point_to_ignore = nil)
    x, y = origin_point

    [
      [ x - 1, y - 1 ],
      [ x, y - 1 ],
      [ x + 1, y - 1 ],
      [ x - 1, y ],
      [ x + 1, y ],
      [ x - 1, y + 1 ],
      [ x, y + 1 ],
      [ x + 1, y + 1 ]
    ].each do |point|
      return point if point != point_to_ignore && @image.pixel_color(*point) == color
    end

    nil
  end


  def node_for_point(searched_point, nodes)
    nodes.find do |node|
      node[:points].any? do |point|
        point[0] == searched_point[0] && point[1] == searched_point[1]
      end
    end
  end
end
Something went wrong with that request. Please try again.