Class: PerfectShape::Polygon

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

Overview

Instance Attribute Summary

Attributes included from MultiPoint

#points

Instance Method Summary collapse

Methods included from MultiPoint

#initialize, #max_x, #max_y, #min_x, #min_y

Methods inherited from Shape

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

Instance Method Details

#contain?(x_or_point, y = nil) ⇒ @code true

Checks if polygon contains point (two-number Array or x, y args) using the Ray Casting Algorithm (aka Even-Odd Rule): 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:

  • (@code true)

    if the point lies within the bound of



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/perfect_shape/polygon.rb', line 40

def contain?(x_or_point, y = nil)
  x, y = normalize_point(x_or_point, y)
  return unless x && y
  npoints = points.count
  xpoints = points.map(&:first)
  ypoints = points.map(&:last)
  return false if npoints <= 2 || !bounding_box.contain?(x, y)
  hits = 0

  lastx = xpoints[npoints - 1]
  lasty = ypoints[npoints - 1]

  # Walk the edges of the polygon
  npoints.times do |i|
    curx = xpoints[i]
    cury = ypoints[i]

    if cury == lasty
      lastx = curx
      lasty = cury
      next
    end

    if curx < lastx
      if x >= lastx
        lastx = curx
        lasty = cury
        next
      end
      leftx = curx
    else
      if x >= curx
        lastx = curx
        lasty = cury
        next
      end
      leftx = lastx
    end

    if cury < lasty
      if y < cury || y >= lasty
        lastx = curx
        lasty = cury
        next
      end
      if x < leftx
        hits += 1
        lastx = curx
        lasty = cury
        next
      end
      test1 = x - curx
      test2 = y - cury
    else
      if y < lasty || y >= cury
        lastx = curx
        lasty = cury
        next
      end
      if x < leftx
        hits += 1
        lastx = curx
        lasty = cury
        next
      end
      test1 = x - lastx
      test2 = y - lasty
    end

    hits += 1 if (test1 < (test2 / (lasty - cury) * (lastx - curx)))
  end

  (hits & 1) != 0
end