Module: Hexagonly::Polygon::Methods

Included in:
Hexagon::Methods, Hexagonly::Polygon
Defined in:
lib/hexagonly/polygon.rb

Overview

Adds Polygon methods to an object. The Polygon corners are read via the #poly_points method. You can override this method or use the #poly_points_method class method to set a method name for reading polygon corners.

Examples:

class MyPolygon

  include Hexagonly::Polygon::Methods
  poly_points_method :corners

  attr_reader :corners
  def initialize(corners); @corners = corners; end

end

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#collected_pointsObject

Returns the value of attribute collected_points.



33
34
35
# File 'lib/hexagonly/polygon.rb', line 33

def collected_points
  @collected_points
end

#rejected_pointsObject

Returns the value of attribute rejected_points.



33
34
35
# File 'lib/hexagonly/polygon.rb', line 33

def rejected_points
  @rejected_points
end

Class Method Details

.included(base) ⇒ Object



21
22
23
# File 'lib/hexagonly/polygon.rb', line 21

def self.included(base)
  base.extend(ClassMethods)
end

Instance Method Details

#contains?(point) ⇒ Boolean

Crossing count algorithm for determining whether a point lies within a polygon. Ported from www.visibone.com/inpoly/inpoly.c.txt (original C code by Bob Stein & Craig Yap).

Returns:

  • (Boolean)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/hexagonly/polygon.rb', line 44

def contains?(point)
  raise "Not a valid polygon!" if poly_points.nil? || poly_points.size < 3

  is_inside = false
  old_p = poly_points.last
  poly_points.each do |new_p|
    if new_p.x_coord > old_p.x_coord
      first_p = old_p
      second_p = new_p
    else
      first_p = new_p
      second_p = old_p
    end
    if ((new_p.x_coord < point.x_coord) == (point.x_coord <= old_p.x_coord)) && ((point.y_coord - first_p.y_coord) * (second_p.x_coord - first_p.x_coord) < (second_p.y_coord - first_p.y_coord) * (point.x_coord - first_p.x_coord))
      is_inside = ! is_inside
    end
    old_p = new_p
  end

  is_inside
end

#grab(points) ⇒ Array<Hexagonly::Point] the grabed points

Grabs all points within the polygon boundries from an array of Points and appends them to @collected_points. All rejected Points are stored under @rejected_points (if you want to pass the to other objects).

Parameters:

Returns:

  • (Array<Hexagonly::Point] the grabed points)

    Array<Hexagonly::Point] the grabed points



73
74
75
76
77
78
79
80
# File 'lib/hexagonly/polygon.rb', line 73

def grab(points)
  parts = points.partition{ |p| contains?(p) }
  @collected_points ||= []
  @collected_points += parts[0]
  @rejected_points = parts[1]

  parts[0]
end

#poly_pointsObject

Raises:

  • (NoMethodError)


35
36
37
38
39
# File 'lib/hexagonly/polygon.rb', line 35

def poly_points
  raise NoMethodError if self.class.poly_points_method_name.nil?

  send(self.class.poly_points_method_name)
end