From 55f4f5b51471774cba0bc776b1c6f0ed13e9e301 Mon Sep 17 00:00:00 2001 From: Fabian Fiorotto Date: Mon, 15 Dec 2014 20:09:48 -0300 Subject: [PATCH 1/5] line intersection --- lib/geometry/line.rb | 39 +++++++++++++++++++++++++++++++++++++-- test/geometry/line.rb | 25 +++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/lib/geometry/line.rb b/lib/geometry/line.rb index b454a64..9348e0d 100644 --- a/lib/geometry/line.rb +++ b/lib/geometry/line.rb @@ -67,6 +67,42 @@ def self.[](*args) end end + + def intersection(object) + case(object) + when Line + if object.vertical? && self.vertical? then + return [] + end + + if object.vertical? || self.vertical? then + if object.vertical? then + vline = object ; line = self + else + vline = self ; line = object + end + m = line.slope + c = line.intercept + x = vline.intercept(:x) + y = m * x + c + return [Point[x,y]] + else + m1 = self.slope + m2 = object.slope + c1 = self.intercept + c2 = object.intercept + return [] if m1 == m2 + x = (c2 - c1) / (m1 - m2) + y = m1 * x + c1 + return [Point[x,y]] + end + when Polyline + raise NotImplementedError + end + return nil + end + + # @overload new(from, to) # @option options [Point] :from A starting {Point} # @option options [Point] :to An end {Point} @@ -271,7 +307,7 @@ def vertical? def intercept(axis=:y) case axis when :x - vertical? ? @intercept : (horizontal? ? nil : (first.x - first.y/slope)) + vertical? ? first.x : (horizontal? ? nil : (first.x - first.y/slope)) when :y vertical? ? nil : (horizontal? ? first.y : (first.y - slope * first.x)) end @@ -280,4 +316,3 @@ def intercept(axis=:y) # @endgroup end end - diff --git a/test/geometry/line.rb b/test/geometry/line.rb index 9c9a84a..b1f4ad9 100644 --- a/test/geometry/line.rb +++ b/test/geometry/line.rb @@ -105,6 +105,31 @@ line = Geometry::Line[[0,0], [10,10]] assert_equal('Line(Point[0, 0], Point[10, 10])', line.to_s) end + it "line intersection" do + line1 = Geometry::Line[[1,1],[3,3]] + line2 = Geometry::Line[[1,3],[3,1]] + assert_equal [Geometry::Point[2,2]], line1.intersection(line2) + assert_equal [Geometry::Point[2,2]], line2.intersection(line1) + end + it "verctical line intersection" do + line1 = Geometry::Line[[1,1],[1,2]] + line2 = Geometry::Line[[0,0],[2,2]] + assert_equal [Geometry::Point[1,1]], line2.intersection(line1) + assert_equal [Geometry::Point[1,1]], line1.intersection(line2) + end + it "paralells lines shouldn't intercept" do + line1 = Geometry::Line[[2,0],[2,0]] + line2 = Geometry::Line[[1,0],[1,0]] + assert_equal [], line2.intersection(line1) + + line1 = Geometry::Line[[0,2],[0,2]] + line2 = Geometry::Line[[0,1],[0,1]] + assert_equal [], line2.intersection(line1) + + line1 = Geometry::Line[[0,0],[1,1]] + line2 = Geometry::Line[[2,3],[3,4]] + assert_equal [], line2.intersection(line1) + end end describe Geometry::PointSlopeLine do From 15f52f10568c14fc464e5095e1be1b0c04ed11ba Mon Sep 17 00:00:00 2001 From: Fabian Fiorotto Date: Tue, 16 Dec 2014 10:12:33 -0300 Subject: [PATCH 2/5] polygon intersection --- lib/geometry/line.rb | 15 +++++++++++++-- test/geometry/line.rb | 12 ++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/geometry/line.rb b/lib/geometry/line.rb index 9348e0d..3266140 100644 --- a/lib/geometry/line.rb +++ b/lib/geometry/line.rb @@ -67,7 +67,7 @@ def self.[](*args) end end - + # @return [Array] intersection points def intersection(object) case(object) when Line @@ -97,7 +97,18 @@ def intersection(object) return [Point[x,y]] end when Polyline - raise NotImplementedError + points = object.edges.map do |edge| + point = self.intersection(Line[edge.first,edge.last]).first + next nil if point.nil? + x1 , x2 = [edge.first.x , edge.last.x ].sort + y1 , y2 = [edge.first.y , edge.last.y ].sort + if (x1 .. x2).include?(point.x) && (y1 .. y2).include?(point.y) then + next point + else + next nil + end + end + return points.compact.uniq end return nil end diff --git a/test/geometry/line.rb b/test/geometry/line.rb index b1f4ad9..4a34b67 100644 --- a/test/geometry/line.rb +++ b/test/geometry/line.rb @@ -130,6 +130,18 @@ line2 = Geometry::Line[[2,3],[3,4]] assert_equal [], line2.intersection(line1) end + it "polygon intersection" do + b = proc{ |p1,p2| p1.to_a <=> p2.to_a } + polygon = Geometry::Polygon.new([1,1] ,[1,3], [3,3], [3,1]) + line = Geometry::Line[[0,2],[4,2]] + assert_equal [Geometry::Point[1, 2],Geometry::Point[3, 2]].sort(&b) , line.intersection(polygon).sort(&b) + line = Geometry::Line[[2,0],[2,4]] + assert_equal [Geometry::Point[2, 3],Geometry::Point[2, 1]].sort(&b), line.intersection(polygon).sort(&b) + line = Geometry::Line[[3,3],[4,4]] + assert_equal [Geometry::Point[1, 1],Geometry::Point[3, 3]].sort(&b), line.intersection(polygon).sort(&b) + line = Geometry::Line[[0,6],[10,15]] + assert_equal [], line.intersection(polygon) + end end describe Geometry::PointSlopeLine do From b442340936001694b0b2af55440af15914dacce9 Mon Sep 17 00:00:00 2001 From: Fabian Fiorotto Date: Mon, 22 Dec 2014 09:50:58 -0300 Subject: [PATCH 3/5] reduce the use of return and next statements --- lib/geometry/line.rb | 69 ++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/lib/geometry/line.rb b/lib/geometry/line.rb index 3266140..d091047 100644 --- a/lib/geometry/line.rb +++ b/lib/geometry/line.rb @@ -69,48 +69,49 @@ def self.[](*args) # @return [Array] intersection points def intersection(object) - case(object) - when Line - if object.vertical? && self.vertical? then - return [] - end - - if object.vertical? || self.vertical? then - if object.vertical? then - vline = object ; line = self + result = [] + if object.kind_of?(Line) then + unless object.vertical? && self.vertical? then + if object.vertical? || self.vertical? then + if object.vertical? then + vline = object ; line = self + else + vline = self ; line = object + end + m = line.slope + c = line.intercept + x = vline.intercept(:x) + y = m * x + c + result = [Point[x,y]] else - vline = self ; line = object + m1 = self.slope + m2 = object.slope + c1 = self.intercept + c2 = object.intercept + if m1 != m2 then + x = (c2 - c1) / (m1 - m2) + y = m1 * x + c1 + result = [Point[x,y]] + end end - m = line.slope - c = line.intercept - x = vline.intercept(:x) - y = m * x + c - return [Point[x,y]] - else - m1 = self.slope - m2 = object.slope - c1 = self.intercept - c2 = object.intercept - return [] if m1 == m2 - x = (c2 - c1) / (m1 - m2) - y = m1 * x + c1 - return [Point[x,y]] end - when Polyline + elsif object.kind_of?(Polyline) then points = object.edges.map do |edge| point = self.intersection(Line[edge.first,edge.last]).first - next nil if point.nil? - x1 , x2 = [edge.first.x , edge.last.x ].sort - y1 , y2 = [edge.first.y , edge.last.y ].sort - if (x1 .. x2).include?(point.x) && (y1 .. y2).include?(point.y) then - next point - else - next nil + if point != nil then + x1 , x2 = [edge.first.x , edge.last.x ].sort + y1 , y2 = [edge.first.y , edge.last.y ].sort + unless (x1 .. x2).include?(point.x) && (y1 .. y2).include?(point.y) then + point = nil + end end + next point end - return points.compact.uniq + result = points.compact.uniq + else + raise ArgumentError end - return nil + return result end From 3320c951c1c2f95da651fbdb6fd014c23871158b Mon Sep 17 00:00:00 2001 From: Fabian Fiorotto Date: Mon, 22 Dec 2014 09:54:43 -0300 Subject: [PATCH 4/5] reduce use of self --- lib/geometry/line.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/geometry/line.rb b/lib/geometry/line.rb index d091047..2b5a6d3 100644 --- a/lib/geometry/line.rb +++ b/lib/geometry/line.rb @@ -74,19 +74,20 @@ def intersection(object) unless object.vertical? && self.vertical? then if object.vertical? || self.vertical? then if object.vertical? then - vline = object ; line = self + m = slope + c = intercept + x = object.intercept(:x) else - vline = self ; line = object + m = object.slope + c = object.intercept + x = intercept(:x) end - m = line.slope - c = line.intercept - x = vline.intercept(:x) y = m * x + c result = [Point[x,y]] else - m1 = self.slope + m1 = slope m2 = object.slope - c1 = self.intercept + c1 = intercept c2 = object.intercept if m1 != m2 then x = (c2 - c1) / (m1 - m2) From b8b26356b1f1e05290bb0e8abb94e40d1c15bebc Mon Sep 17 00:00:00 2001 From: Fabian Fiorotto Date: Mon, 22 Dec 2014 10:00:44 -0300 Subject: [PATCH 5/5] reduce use of self --- lib/geometry/line.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/geometry/line.rb b/lib/geometry/line.rb index 2b5a6d3..b5e7a69 100644 --- a/lib/geometry/line.rb +++ b/lib/geometry/line.rb @@ -98,7 +98,7 @@ def intersection(object) end elsif object.kind_of?(Polyline) then points = object.edges.map do |edge| - point = self.intersection(Line[edge.first,edge.last]).first + point = intersection(Line[edge.first,edge.last]).first if point != nil then x1 , x2 = [edge.first.x , edge.last.x ].sort y1 , y2 = [edge.first.y , edge.last.y ].sort