Sha256: 3ca20748e8cbd67f8bc8746998746159c76fedf6317315d4a6b278663e58b996

Contents?: true

Size: 1.89 KB

Versions: 1

Compression:

Stored size: 1.89 KB

Contents

class Is
  class Area

    attr_reader :area

    def initialize(points)
      @area = points.map { |it| Is::Point.new *it }
    end

    def contains?(point)
      point = Is::Point.new(*point) unless point.is_a?(Is::Point)
      return false if outside_box? point

      contains_point = false
      area_size = area.size
      i = -1
      j = area_size - 1

      while (i += 1) < area_size
        vertex1, vertex2 = area.values_at i, j
        if conditions_passed?(point, vertex1, vertex2)
          contains_point = !contains_point
        end
        j = i
      end

      contains_point
    end

    private

    def conditions_passed?(*args)
      orig_lat_between_vertices_lats?(*args.map(&:latitude)) and ray_crosses_segment?(*args)
    end

    def orig_lat_between_vertices_lats?(orig_lat, vertex1_lat, vertex2_lat)
      (vertex1_lat..vertex2_lat).include?(orig_lat) or
      (vertex2_lat..vertex1_lat).include?(orig_lat)
    end

    def ray_crosses_segment?(orig, vertex1, vertex2)
      olt  = orig.latitude
      olg  = orig.longitude
      v1lt = vertex1.latitude
      v1lg = vertex1.longitude
      v2lt = vertex2.latitude
      v2lg = vertex2.longitude

      olg < (v2lg - v1lg) * (olt - v1lt) / (v2lt - v1lt) + v1lg
    end

    def bounding_box
      {
        'left'   => area.min{|a, b| a.longitude <=> b.longitude}.longitude,
        'right'  => area.max{|a, b| a.longitude <=> b.longitude}.longitude,
        'top'    => area.max{|a, b| a.latitude <=> b.latitude}.latitude,
        'bottom' => area.min{|a, b| a.latitude <=> b.latitude}.latitude
      }
    end

    def outside_box?(point)
      if point.nil? or point.longitude.nil? or point.latitude.nil?
        true
      else
        box = bounding_box
        point.longitude < box['left']   or
        point.longitude > box['right']  or
        point.latitude  < box['bottom'] or
        point.latitude  > box['top']
      end
    end

  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
is-0.0.2 lib/is/area.rb