class GeosparqlToGeojson::Converter::PolygonConverter

Class to convert polygon data and process polygon holes.

@since 0.2.0

Public Class Methods

new(geosparql_values_by_type, values) click to toggle source

Creates a new instance of GeosparqlToGeojson::Converter::PolygonConverter

@param [Hash] geosparql_values_by_type that contains the formatted GeoSPARQL data. @param [Array<String>] values the raw polygon data.

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 19
def initialize(geosparql_values_by_type, values)
  @geosparql_values_by_type = geosparql_values_by_type
  @values     = values.flatten
  @polygons   = []
  @holes      = []
  @formatted_polygon_array = []
end

Public Instance Methods

convert() click to toggle source

Converts polygon data into the correct format and adds it to @geosparql_values_by_type.

@return [Hash] the converted andf formatted polygon data.

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 30
def convert
  format_data

  if @holes.any?
    match_holes_to_polygons
    format_polygons_with_holes
  end

  format_polygons_without_holes
  add_formatted_polygons_to_data_hash
end

Private Instance Methods

add_formatted_polygons_to_data_hash() click to toggle source

Adds the populated @formatted_polygon_array to @geosparql_values_by_type

@return [Hash] @geosparql_values_by_type the 'Polygon' type with it's values.

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 199
def add_formatted_polygons_to_data_hash
  @geosparql_values_by_type[:Polygon] = @formatted_polygon_array
end
format_data() click to toggle source

Splits polygon value strings by GeoSparql syntax, strips whitespace and converts values to floats.

@return [void]

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 47
def format_data
  @values.map! do |values_string|
    values_string.split(/\),?\s*\(/).map! do |values|
      values = values.split(',').map(&:strip)
      values.map! { |value| value.split(/\s/).map(&:to_f) }
    end
  end

  split_into_polygons_and_holes
end
format_polygons_with_holes() click to toggle source

Adds an array of a polygon and the holes that match the polygon to @formatted_polygon_array.

@return [void]

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 167
def format_polygons_with_holes
  @matches.each do |key, values|
    polygon_with_holes = [@polygons[key]]

    values.each do |value|
      polygon_with_holes << @holes[value]
    end

    @formatted_polygon_array << polygon_with_holes
  end
end
format_polygons_without_holes() click to toggle source

Adds polygons that don't have holes to @formatted_polygon_array.

@return [void]

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 182
def format_polygons_without_holes
  remove_polygons_with_holes if @matches

  @polygons.each { |polygon| @formatted_polygon_array << [polygon] }
end
hole?(values) click to toggle source

Checks whether a polygon is a hole. Uses the shoelace formula.

@param [Array] values the polygon values. @return [Boolean]

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 79
def hole?(values)
  results = []
  count   = values.size
  values.each_with_index do |_value, index|
    current    = values[index]
    next_value = values[index + 1]

    if index < count - 1
      results << (next_value[0] - current[0]) * (next_value[1] + current[1])
    end
  end
  results.compact!
  return true if results.sum.negative?
  false
end
match_holes_to_polygons() click to toggle source

Generates a hash containing the indexes of polygons and the holes within them.

@return [void]

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 98
def match_holes_to_polygons
  @matches = {}
  @polygons.each_with_index do |polygon, polygon_index|
    set_min_and_max_axis(polygon)

    @holes.each_with_index do |hole, hole_index|
      set_min_and_max_axis(hole)

      # @note This method of building a border box around the polygon and checking
      #   to see whether the min and max values of the hole fit within it
      #   will work since we already know it is a hole. Otherwise we would need a more accurate solution.
      if @x_min[1] > @x_min[0] && @x_max[1] < @x_max[0] && @y_min[1] > @y_min[0] && @y_max[1] < @y_max[0]
        @matches[polygon_index] ||= []
        @matches[polygon_index].push(hole_index)
      end

      set_min_and_max_to_first_value
    end

    reset_min_and_max_instance_variables
  end
end
remove_polygons_with_holes() click to toggle source

Deletes polygons that contain holes from @polygons.

@return [void]

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 191
def remove_polygons_with_holes
  # Need to reverse the keys so that the @polygon index doesn't change before we call #delete_at.
  @matches.keys.reverse.each { |key| @polygons.delete_at(key) }
end
reset_min_and_max_instance_variables() click to toggle source

Sets minimum and maximum X and Y axis variables to nil.

@return [void]

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 157
def reset_min_and_max_instance_variables
  @x_min = nil
  @y_min = nil
  @x_max = nil
  @y_max = nil
end
set_min_and_max_axis(values) click to toggle source

Sets the minumum and maximum values of a polygon's X and Y axis.

@param [Array<Float>] values the x and y values for each point on the polygon. @return [void]

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 125
def set_min_and_max_axis(values)
  x_axis = []
  y_axis = []
  @x_min ||= []
  @x_max ||= []
  @y_min ||= []
  @y_max ||= []

  values.each do |value|
    x_axis << value[0]
    y_axis << value[1]
  end

  @x_min << x_axis.min
  @x_max << x_axis.max
  @y_min << y_axis.min
  @y_max << y_axis.max
end
set_min_and_max_to_first_value() click to toggle source

Sets minimum and maximum X and Y axis variables to an array containing their first value.

@return [void]

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 147
def set_min_and_max_to_first_value
  @x_min = [@x_min.first]
  @x_max = [@x_max.first]
  @y_min = [@y_min.first]
  @y_max = [@y_max.first]
end
split_into_polygons_and_holes() click to toggle source

Adds polygons and holes from @values to @polygons and @holes.

@return [Array] @holes @return [Array] @polygons

# File lib/geosparql_to_geojson/converter/polygon_converter.rb, line 62
def split_into_polygons_and_holes
  @values.each do |value_array|
    value_array.each do |values|
      if hole?(values)
        @holes << values
      else
        @polygons << values
      end
    end
  end
end