Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions lib/algorithms/point_in_polygon.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
module Geometry
class PointInPolygon < Struct.new(:point, :polygon)
extend Memoist


MAX_SEED = 1000000.0

def inside?
point_location == :inside
end
Expand Down Expand Up @@ -36,23 +38,25 @@ def point_on_edge?

def choose_good_ray
ray = random_ray
while ! good_ray?(ray) do
ray = random_ray
seed = 1.0
while (seed < MAX_SEED) && (! good_ray?(ray)) do
seed += 1.0
ray = random_ray(seed)
end
ray
end

def good_ray?(ray)
edges.none? { |edge| !edge.length.zero? && edge.parallel_to?(ray) } && vertices.none? { |vertex| ray.contains_point?(vertex) }
end

def intersection_count(ray)
edges.select { |edge| edge.intersects_with?(ray) }.size
end
def random_ray
random_direction = rand * (2 * Math::PI)

def random_ray(seed = 1.0)
random_direction = (Math::PI / 2.0 * seed + Math::PI / (seed + 1.0)) % (Math::PI * 2.0)

ray_endpoint = Point sufficient_ray_radius * Math.cos(random_direction), sufficient_ray_radius * Math.sin(random_direction)
Segment point, ray_endpoint
end
Expand Down
17 changes: 17 additions & 0 deletions test/polygon/contains_point_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,21 @@ def test_nonconvex
assert ! nonconvex_polygon.contains?(outer_point)
end
end

def test_closed_polygon
coordinates_raw = "114.146011,22.284090 114.145050,22.282860 114.146240,22.279619 114.151176,22.277014 114.151833,22.276251 114.151443,22.275000 114.151550,22.273470 114.153198,22.272249 114.156143,22.272970 114.161690,22.271900 114.162521,22.274820 114.162697,22.276211 114.160957,22.275850 114.159927,22.276190 114.158340,22.276270 114.157082,22.276661 114.155312,22.276310 114.153732,22.278000 114.154312,22.278870 114.153992,22.279900 114.152321,22.280890 114.150261,22.282721 114.146011,22.284090"
coordinates = coordinates_raw.split(/\s+/).map do |raw_coor|
# latitude and longitude are reversed since they are from KML
# most important point : the last point is the same as the first one
raw_coor.split(',').map(&:to_f).reverse
end

vertices = coordinates.map do |coordinate_array|
Point.new_by_array(coordinate_array)
end
rectangle = Polygon.new(vertices)

inner = Point(22.2817, 114.14932)
assert rectangle.contains?(inner)
end
end