Class: PerfectShape::Polygon

Inherits:
Shape
  • Object
show all
Includes:
MultiPoint
Defined in:
lib/perfect_shape/polygon.rb

Constant Summary collapse

WINDING_RULES =
PerfectShape::Path::WINDING_RULES

Instance Attribute Summary collapse

Attributes included from MultiPoint

#points

Instance Method Summary collapse

Methods included from MultiPoint

#first_point, #max_x, #max_y, #min_x, #min_y, normalize_point_array

Methods inherited from Shape

#==, #bounding_box, #center_point, #center_x, #center_y, #height, #max_x, #max_y, #min_x, #min_y, #width

Constructor Details

#initialize(points: [], winding_rule: :wind_even_odd) ⇒ Polygon

Returns a new instance of Polygon.



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

def initialize(points: [], winding_rule: :wind_even_odd)
  super(points: points)
  self.winding_rule = winding_rule
end

Instance Attribute Details

#winding_ruleObject

Returns the value of attribute winding_rule.



34
35
36
# File 'lib/perfect_shape/polygon.rb', line 34

def winding_rule
  @winding_rule
end

Instance Method Details

#contain?(x_or_point, y = nil, outline: false, distance_tolerance: 0) ⇒ Boolean

Checks if polygon contains point (two-number Array or x, y args) using the Ray Casting Algorithm (aka Even-Odd Rule) or Winding Number Algorithm (aka Nonzero Rule) Details: en.wikipedia.org/wiki/Point_in_polygon

the polygon, false if the point lies outside of the polygon’s bounds.

Parameters:

  • x

    The X coordinate of the point to test.

  • y (defaults to: nil)

    The Y coordinate of the point to test.

Returns:

  • (Boolean)

    true if the point lies within the bound of



57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/perfect_shape/polygon.rb', line 57

def contain?(x_or_point, y = nil, outline: false, distance_tolerance: 0)
  x, y = Point.normalize_point(x_or_point, y)
  return unless x && y
  if outline
    edges.any? { |edge| edge.contain?(x, y, distance_tolerance: distance_tolerance) }
  else
    if winding_rule == :wind_even_odd
      wind_even_odd_contain?(x, y)
    else
      path.contain?(x, y)
    end
  end
end

#edgesObject



71
72
73
74
75
# File 'lib/perfect_shape/polygon.rb', line 71

def edges
  points.zip(points.rotate(1)).map do |point1, point2|
    Line.new(points: [[point1.first, point1.last], [point2.first, point2.last]])
  end
end

#intersect?(rectangle) ⇒ Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/perfect_shape/polygon.rb', line 84

def intersect?(rectangle)
  path.intersect?(rectangle)
end

#pathObject



77
78
79
80
81
82
# File 'lib/perfect_shape/polygon.rb', line 77

def path
  path_shapes = []
  path_shapes << PerfectShape::Point.new(points[0])
  path_shapes += points[1..-1].map { |point| PerfectShape::Line.new(points: [point]) }
  PerfectShape::Path.new(shapes: path_shapes, closed: true, winding_rule: winding_rule)
end