Skip to content

Commit 4a39041

Browse files
Merge pull request #16 from kaczowkad/big_decimal
Allow intersection_point_with to work with BigDecimal.
2 parents 73dc9c9 + 10f1153 commit 4a39041

File tree

2 files changed

+40
-17
lines changed

2 files changed

+40
-17
lines changed

lib/geometry/segment.rb

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
module Geometry
22
class SegmentsDoNotIntersect < Exception; end
33
class SegmentsOverlap < Exception; end
4-
4+
55
class Segment < Struct.new(:point1, :point2)
66
def self.new_by_arrays(point1_coordinates, point2_coordinates)
7-
self.new(Point.new_by_array(point1_coordinates),
8-
Point.new_by_array(point2_coordinates))
7+
new(Point.new_by_array(point1_coordinates),
8+
Point.new_by_array(point2_coordinates))
99
end
1010

1111
def leftmost_endpoint
@@ -23,8 +23,8 @@ def topmost_endpoint
2323
def bottommost_endpoint
2424
((point1.y <=> point2.y) == -1) ? point1 : point2
2525
end
26-
27-
def contains_point?(point)
26+
27+
def contains_point?(point)
2828
Geometry.distance(point1, point2) ===
2929
Geometry.distance(point1, point) + Geometry.distance(point, point2)
3030
end
@@ -43,26 +43,32 @@ def intersects_with?(segment)
4343
lies_on_line_intersecting?(segment) &&
4444
segment.lies_on_line_intersecting?(self)
4545
end
46-
46+
4747
def overlaps?(segment)
4848
Segment.have_intersecting_bounds?(self, segment) &&
4949
lies_on_one_line_with?(segment)
5050
end
51-
51+
5252
def intersection_point_with(segment)
5353
raise SegmentsDoNotIntersect unless intersects_with?(segment)
5454
raise SegmentsOverlap if overlaps?(segment)
55-
55+
5656
numerator = (segment.point1.y - point1.y) * (segment.point1.x - segment.point2.x) -
5757
(segment.point1.y - segment.point2.y) * (segment.point1.x - point1.x);
58-
denominator = (point2.y - point1.y) * (segment.point1.x - segment.point2.x) -
59-
(segment.point1.y - segment.point2.y) * (point2.x - point1.x);
58+
denominator = (point2.y - point1.y) *
59+
(segment.point1.x - segment.point2.x) -
60+
(segment.point1.y - segment.point2.y) *
61+
(point2.x - point1.x)
62+
63+
if numerator.is_a?(Integer) && denominator.is_a?(Integer)
64+
numerator = numerator.to_f
65+
end
66+
67+
t = numerator / denominator
6068

61-
t = numerator.to_f / denominator;
62-
6369
x = point1.x + t * (point2.x - point1.x)
64-
y = point1.y + t * (point2.y - point1.y)
65-
70+
y = point1.y + t * (point2.y - point1.y)
71+
6672
Point.new(x, y)
6773
end
6874

@@ -91,13 +97,13 @@ def distance_to(point)
9197
return Geometry.distance(q, p)
9298
end
9399

94-
def length
100+
def length
95101
Geometry.distance(point1, point2)
96102
end
97103

98104
def to_vector
99105
Vector.new(point2.x - point1.x, point2.y - point1.y)
100-
end
106+
end
101107

102108
protected
103109

@@ -107,7 +113,7 @@ def self.have_intersecting_bounds?(segment1, segment2)
107113
segment1.leftmost_endpoint.x == segment2.rightmost_endpoint.x) &&
108114
(segment2.leftmost_endpoint.x < segment1.rightmost_endpoint.x ||
109115
segment2.leftmost_endpoint.x == segment1.rightmost_endpoint.x)
110-
116+
111117
intersects_on_y_axis =
112118
(segment1.bottommost_endpoint.y < segment2.topmost_endpoint.y ||
113119
segment1.bottommost_endpoint.y == segment2.topmost_endpoint.y) &&

test/segment/intersection_point_with_test.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require 'minitest/autorun'
22
require 'geometry'
3+
require "bigdecimal"
34

45
class IntersectionPointWithTest < Minitest::Test
56
include Geometry
@@ -18,6 +19,22 @@ def test_segments_intersect_at_the_endpoint
1819
assert_equal Point.new(2, 2), segment1.intersection_point_with(segment2)
1920
end
2021

22+
def test_big_decimal_segments_intersect_at_the_endpoint
23+
segment1 = Segment.new_by_arrays([BigDecimal.new("-109.775390625"),
24+
BigDecimal.new("42.734102391081")],
25+
[BigDecimal.new("-91.23046875"),
26+
BigDecimal.new("42.734102391081")])
27+
28+
segment2 = Segment.new_by_arrays([BigDecimal.new("-91.23046875"),
29+
BigDecimal.new("42.734102391081")],
30+
[BigDecimal.new("-91.23046875"),
31+
BigDecimal.new("34.147272023649")])
32+
33+
assert_equal Point.new(BigDecimal.new("-91.23046875"),
34+
BigDecimal.new("42.734102391081")),
35+
segment1.intersection_point_with(segment2)
36+
end
37+
2138
def test_segments_do_not_intersect
2239
segment1 = Segment.new_by_arrays([0, 0], [0, 2])
2340
segment2 = Segment.new_by_arrays([1, 1], [2, 1])

0 commit comments

Comments
 (0)