class Honua::Map

Attributes

height[R]
width[R]
zoom[R]

Public Class Methods

new(center:, width:, height:, zoom:) click to toggle source
# File lib/honua/map.rb, line 13
def initialize(center:, width:, height:, zoom:)
  @width = width
  @height = height
  @reference, @offset = reference_point(center.zoom_to(zoom))
  @tiles = []
  @zoom = zoom
end

Public Instance Methods

draw() click to toggle source
# File lib/honua/map.rb, line 25
def draw
  fetch_tiles
  render
end
location2point(location) click to toggle source

return an x,y point on the map image for a geographical location

# File lib/honua/map.rb, line 31
def location2point(location)
  x = @offset.x
  y = @offset.y
  coordinate = location.to_coordinate(zoom: @reference.zoom)

  # distance from the know coordinate offset
  x += tile_width * (coordinate.column - @reference.column)
  y += tile_height * (coordinate.row - @reference.row)

  x += @width / 2
  y += @height / 2

  Point.new(x.to_i, y.to_i)
end
point2location(point) click to toggle source
# File lib/honua/map.rb, line 46
def point2location(point)
  # TODO: to be implemented
end

Private Instance Methods

add_attribution?() click to toggle source
# File lib/honua/map.rb, line 132
def add_attribution?
  !attribution_text.nil? && attribution.width < @width && attribution.height < @height
end
attribution() click to toggle source

create attribution image

# File lib/honua/map.rb, line 124
def attribution
  @attribution ||= begin
    mask = Vips::Image.text(attribution_text)
    mask = mask.embed(4, 2, mask.width + 8, mask.height + 4)
    mask.ifthenelse(Helpers.hex2rgb(attribution_fgcolor), Helpers.hex2rgb(attribution_bgcolor), blend: true)
  end
end
fetch_tiles() click to toggle source
# File lib/honua/map.rb, line 65
def fetch_tiles
  coordinate, corner = top_left

  Async do
    (corner.y..@height).step(tile_height).each do |y|
      current_coordinate = coordinate.dup
      (corner.x..@width).step(tile_width).each do |x|
        Async do
          @tiles << Tile.get(current_coordinate, Point.new(x, y))
        end
        current_coordinate = current_coordinate.right
      end
      coordinate = coordinate.down
    end
  end
end
reference_point(coordinate) click to toggle source

returns the initial tile coordinate and its offset relative to the map center

# File lib/honua/map.rb, line 53
def reference_point(coordinate)
  # top left coordinate of tile containing center coordinate
  top_left_coordinate = coordinate.container

  # initial tile position offset, assuming centered tile in grid
  offset_x = ((top_left_coordinate.column - coordinate.column) * Honua.configuration.tile_width).round
  offset_y = ((top_left_coordinate.row - coordinate.row) * Honua.configuration.tile_height).round
  offset = Point.new(offset_x, offset_y)

  [top_left_coordinate, offset]
end
render() click to toggle source

create a canvas and draw tile images based on their offset onto it

# File lib/honua/map.rb, line 107
def render
  canvas = Vips::Image.grey(@width, @height)

  @tiles.each do |tile|
    canvas = canvas.insert(tile.image, tile.offset.x, tile.offset.y) # rubocop:disable Style/RedundantSelfAssignment
  end

  # add attribution image to bottom corner if available & attribution fits into image
  if add_attribution?
    options = { x: canvas.width - attribution.width, y: canvas.height - attribution.height }
    canvas = canvas.composite2(attribution, :over, **options)
  end

  canvas
end
top_left() click to toggle source

get top left coordinate and offset to map

# File lib/honua/map.rb, line 83
def top_left
  x_shift = 0
  y_shift = 0

  corner = Point.new(@offset.x + @width / 2, @offset.y + @height / 2)

  # move left on the map until we have the starting coordinate and offset
  while corner.x.positive?
    corner.x -= tile_width
    x_shift += 1
  end

  # move up on the map until we have the starting coordinate and offset
  while corner.y.positive?
    corner.y -= tile_height
    y_shift += 1
  end

  coordinate = Coordinate.new(@reference.row - y_shift, @reference.column - x_shift, @reference.zoom)

  [coordinate, corner]
end