winding-polygon 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,34 +1,36 @@
1
- class EventQueue
2
- attr_reader :number_of_events
3
- attr_reader :events
4
- attr_reader :individual_vertices
1
+ module WindingPolygon
2
+ class EventQueue
3
+ attr_reader :number_of_events
4
+ attr_reader :events
5
+ attr_reader :individual_vertices
5
6
 
6
- def initialize(polygon)
7
- #last vertex in geojson is equal to first vertex
8
- @individual_vertices = polygon.vertices.length - 1
9
- #2 per edge - last event looping back to 0 is handled by +1 below
10
- @number_of_events = 2 * (@individual_vertices)
11
- @events = []
7
+ def initialize(polygon)
8
+ #last vertex in geojson is equal to first vertex
9
+ @individual_vertices = polygon.vertices.length - 1
10
+ #2 per edge - last event looping back to 0 is handled by +1 below
11
+ @number_of_events = 2 * (@individual_vertices)
12
+ @events = []
12
13
 
13
- #build up 2 'events' per edge. One for left vertex, one for right.
14
- for i in 0..@individual_vertices-1
15
- a = 2*i
16
- b = 2*i+1
17
- @events[a] = {:edge=>i}
18
- @events[b] = {:edge=>i}
19
- @events[a][:vertex] = polygon.vertices[i]
20
- @events[b][:vertex] = polygon.vertices[i+1]
21
- if @events[a][:vertex].compare(@events[b][:vertex]) < 0
22
- @events[a][:type] = 'left'
23
- @events[b][:type] = 'right'
24
- else
25
- @events[a][:type] = 'right'
26
- @events[b][:type] = 'left'
14
+ #build up 2 'events' per edge. One for left vertex, one for right.
15
+ for i in 0..@individual_vertices-1
16
+ a = 2*i
17
+ b = 2*i+1
18
+ @events[a] = {:edge=>i}
19
+ @events[b] = {:edge=>i}
20
+ @events[a][:vertex] = polygon.vertices[i]
21
+ @events[b][:vertex] = polygon.vertices[i+1]
22
+ if @events[a][:vertex].compare(@events[b][:vertex]) < 0
23
+ @events[a][:type] = 'left'
24
+ @events[b][:type] = 'right'
25
+ else
26
+ @events[a][:type] = 'right'
27
+ @events[b][:type] = 'left'
28
+ end
27
29
  end
30
+
31
+ # sort events lexicographically
32
+ @events.sort!{|a,b| a[:vertex].compare(b[:vertex])}
28
33
  end
29
34
 
30
- # sort events lexicographically
31
- @events.sort!{|a,b| a[:vertex].compare(b[:vertex])}
32
35
  end
33
-
34
- end
36
+ end
@@ -1,40 +1,42 @@
1
- class Point
1
+ module WindingPolygon
2
+ class Point
3
+
4
+ attr_reader :x
5
+ attr_reader :y
6
+
7
+ def initialize(x,y)
8
+ @x=x
9
+ @y=y
10
+ end
11
+
12
+ # Determines the xy lexicographical order of two points
13
+ def compare other_point
14
+ raise Exception.new("Self is x=#{@x},y=#{@y}, the other_point is nil") if other_point.nil?
15
+ # x-coord first
16
+ return 1 if @x > other_point.x
17
+ return -1 if @x < other_point.x
18
+
19
+ # y-coord second
20
+ return 1 if @y > other_point.y
21
+ return -1 if @y < other_point.y
22
+
23
+ # they are the same point
24
+ return 0
25
+ end
26
+
27
+ def == (other_point)
28
+ @x==other_point.x && @y==other_point.y
29
+ end
30
+
31
+ # tests if point is Left|On|Right of the line P0 to P1.
32
+ #
33
+ # returns:
34
+ # >0 for left of the line
35
+ # 0 for on the line
36
+ # <0 for right of the line
37
+ def is_left p0, p1
38
+ return (p1.x - p0.x) * (@y - p0.y) - (@x - p0.x) * (p1.y - p0.y)
39
+ end
2
40
 
3
- attr_reader :x
4
- attr_reader :y
5
-
6
- def initialize(x,y)
7
- @x=x
8
- @y=y
9
- end
10
-
11
- # Determines the xy lexicographical order of two points
12
- def compare other_point
13
- raise Exception.new("Self is x=#{@x},y=#{@y}, the other_point is nil") if other_point.nil?
14
- # x-coord first
15
- return 1 if @x > other_point.x
16
- return -1 if @x < other_point.x
17
-
18
- # y-coord second
19
- return 1 if @y > other_point.y
20
- return -1 if @y < other_point.y
21
-
22
- # they are the same point
23
- return 0
24
41
  end
25
-
26
- def == (other_point)
27
- @x==other_point.x && @y==other_point.y
28
- end
29
-
30
- # tests if point is Left|On|Right of the line P0 to P1.
31
- #
32
- # returns:
33
- # >0 for left of the line
34
- # 0 for on the line
35
- # <0 for right of the line
36
- def is_left p0, p1
37
- return (p1.x - p0.x) * (@y - p0.y) - (@x - p0.x) * (p1.y - p0.y)
38
- end
39
-
40
42
  end
@@ -1,114 +1,116 @@
1
- class Polygon
2
- attr_reader :vertices
3
- attr_reader :intersection_points
1
+ module WindingPolygon
2
+ class Polygon
3
+ attr_reader :vertices
4
+ attr_reader :intersection_points
5
+
6
+ def initialize(points)
7
+ @vertices = points
8
+ @intersection_points = Array.new
9
+ end
4
10
 
5
- def initialize(points)
6
- @vertices = points
7
- @intersection_points = Array.new
8
- end
11
+ def is_simple
12
+ event_queue = EventQueue.new(self)
13
+ sweep_line = SweepLine.new(self)
9
14
 
10
- def is_simple
11
- event_queue = EventQueue.new(self)
12
- sweep_line = SweepLine.new(self)
15
+ # This loop processes all events in the sorted queue
16
+ # Events are only left or right vertices
17
+ e = event_queue.events.shift
18
+ while !e.nil? do
13
19
 
14
- # This loop processes all events in the sorted queue
15
- # Events are only left or right vertices
16
- e = event_queue.events.shift
17
- while !e.nil? do
20
+ if e[:type] == 'left'
21
+ s = sweep_line.add(e)
18
22
 
19
- if e[:type] == 'left'
20
- s = sweep_line.add(e)
23
+ return false if !sweep_line.intersect(s, s.above).nil?
24
+ return false if !sweep_line.intersect(s, s.below).nil?
25
+ else
26
+ s = sweep_line.find(e)
27
+ return false if !sweep_line.intersect(s.above, s.below).nil?
28
+ sweep_line.remove(s)
29
+ end
21
30
 
22
- return false if !sweep_line.intersect(s, s.above).nil?
23
- return false if !sweep_line.intersect(s, s.below).nil?
24
- else
25
- s = sweep_line.find(e)
26
- return false if !sweep_line.intersect(s.above, s.below).nil?
27
- sweep_line.remove(s)
31
+ e = event_queue.events.shift
28
32
  end
29
33
 
30
- e = event_queue.events.shift
34
+ return true
31
35
  end
32
36
 
33
- return true
34
- end
37
+ def get_intersection_points
38
+ event_queue = EventQueue.new(self)
39
+ sweep_line = SweepLine.new(self)
35
40
 
36
- def get_intersection_points
37
- event_queue = EventQueue.new(self)
38
- sweep_line = SweepLine.new(self)
41
+ # This loop processes all events in the sorted queue
42
+ # Events are only left or right vertices
43
+ e = event_queue.events.shift
44
+ while !e.nil? do
39
45
 
40
- # This loop processes all events in the sorted queue
41
- # Events are only left or right vertices
42
- e = event_queue.events.shift
43
- while !e.nil? do
46
+ if e[:type] == 'left'
47
+ s = sweep_line.add(e)
44
48
 
45
- if e[:type] == 'left'
46
- s = sweep_line.add(e)
49
+ add_to_intersection_point_collection(sweep_line.intersect(s, s.above))
50
+ add_to_intersection_point_collection(sweep_line.intersect(s, s.below))
47
51
 
48
- add_to_intersection_point_collection(sweep_line.intersect(s, s.above))
49
- add_to_intersection_point_collection(sweep_line.intersect(s, s.below))
52
+ else
53
+ s = sweep_line.find(e)
54
+ add_to_intersection_point_collection(sweep_line.intersect(s.above, s.below))
55
+ sweep_line.remove(s)
56
+ end
50
57
 
51
- else
52
- s = sweep_line.find(e)
53
- add_to_intersection_point_collection(sweep_line.intersect(s.above, s.below))
54
- sweep_line.remove(s)
58
+ e = event_queue.events.shift
55
59
  end
56
60
 
57
- e = event_queue.events.shift
61
+ return nil if intersection_points.size==0
62
+ @intersection_points
58
63
  end
59
64
 
60
- return nil if intersection_points.size==0
61
- @intersection_points
62
- end
65
+ def add_to_intersection_point_collection(point)
66
+ @intersection_points << point if !point.nil? && !@intersection_points.any?{|p| p.compare(point)==0}
67
+ end
63
68
 
64
- def add_to_intersection_point_collection(point)
65
- @intersection_points << point if !point.nil? && !@intersection_points.any?{|p| p.compare(point)==0}
66
- end
69
+ def get_first_intersection_point_hash
70
+ event_queue = EventQueue.new(self)
71
+ sweep_line = SweepLine.new(self)
67
72
 
68
- def get_first_intersection_point_hash
69
- event_queue = EventQueue.new(self)
70
- sweep_line = SweepLine.new(self)
71
-
72
- # This loop processes all events in the sorted queue
73
- # Events are only left or right vertices
74
- e = event_queue.events.shift
75
- while !e.nil? do
76
- if e[:type] == 'left'
77
- s = sweep_line.add(e)
78
-
79
- point = sweep_line.intersect(s, s.above)
80
- return point_hash_with_edge_info(point, s, s.above) if !point.nil?
81
-
82
- point = sweep_line.intersect(s, s.below)
83
- return point_hash_with_edge_info(point, s, s.below) if !point.nil?
84
- else
85
- s = sweep_line.find(e)
86
- point = sweep_line.intersect(s.above, s.below)
87
- return point_hash_with_edge_info(point, s.above, s.below) if !point.nil?
88
- sweep_line.remove(s)
89
- end
73
+ # This loop processes all events in the sorted queue
74
+ # Events are only left or right vertices
90
75
  e = event_queue.events.shift
76
+ while !e.nil? do
77
+ if e[:type] == 'left'
78
+ s = sweep_line.add(e)
79
+
80
+ point = sweep_line.intersect(s, s.above)
81
+ return point_hash_with_edge_info(point, s, s.above) if !point.nil?
82
+
83
+ point = sweep_line.intersect(s, s.below)
84
+ return point_hash_with_edge_info(point, s, s.below) if !point.nil?
85
+ else
86
+ s = sweep_line.find(e)
87
+ point = sweep_line.intersect(s.above, s.below)
88
+ return point_hash_with_edge_info(point, s.above, s.below) if !point.nil?
89
+ sweep_line.remove(s)
90
+ end
91
+ e = event_queue.events.shift
92
+ end
93
+ return nil
91
94
  end
92
- return nil
93
- end
94
95
 
95
- def decompose
96
- intersection_point = get_first_intersection_point_hash
97
- return [self] if intersection_point.nil?
98
- first_polygon = Polygon.new((@vertices[0..intersection_point[:edge1]]<<intersection_point[:point]).concat( @vertices[intersection_point[:edge2]+1,@vertices.length-intersection_point[:edge2]]))
99
- second_polygon = Polygon.new(@vertices[intersection_point[:edge1]+1..intersection_point[:edge2]].insert(0,intersection_point[:point])<<intersection_point[:point])
100
- return [first_polygon,second_polygon]
101
- end
96
+ def decompose
97
+ intersection_point = get_first_intersection_point_hash
98
+ return [self] if intersection_point.nil?
99
+ first_polygon = Polygon.new((@vertices[0..intersection_point[:edge1]]<<intersection_point[:point]).concat( @vertices[intersection_point[:edge2]+1,@vertices.length-intersection_point[:edge2]]))
100
+ second_polygon = Polygon.new(@vertices[intersection_point[:edge1]+1..intersection_point[:edge2]].insert(0,intersection_point[:point])<<intersection_point[:point])
101
+ return [first_polygon,second_polygon]
102
+ end
102
103
 
103
- def point_hash_with_edge_info(point, s1, s2)
104
- edges=[s1.edge, s2.edge].sort!
105
- {:point => point, :edge1 => edges[0], :edge2 => edges[1]}
106
- end
104
+ def point_hash_with_edge_info(point, s1, s2)
105
+ edges=[s1.edge, s2.edge].sort!
106
+ {:point => point, :edge1 => edges[0], :edge2 => edges[1]}
107
+ end
107
108
 
108
- def ==(other_polygon)
109
- for i in 0..@vertices.size-1
110
- return false if @vertices[i] != other_polygon.vertices[i]
109
+ def ==(other_polygon)
110
+ for i in 0..@vertices.size-1
111
+ return false if @vertices[i] != other_polygon.vertices[i]
112
+ end
113
+ return true
111
114
  end
112
- return true
113
115
  end
114
116
  end
@@ -1,48 +1,49 @@
1
- #A container class for segments (or edges) of the polygon to test
2
- #Allows storage and retrieval from the Balanced Binary Tree
3
- class Segment
4
- attr_reader :edge
5
- attr_accessor :left_point
6
- attr_accessor :right_point
7
- attr_accessor :above
8
- attr_accessor :below
9
-
10
-
11
- def initialize(event)
12
- @edge = event[:edge]
13
- end
1
+ module WindingPolygon
2
+ #A container class for segments (or edges) of the polygon to test
3
+ #Allows storage and retrieval from the Balanced Binary Tree
4
+ class Segment
5
+ attr_reader :edge
6
+ attr_accessor :left_point
7
+ attr_accessor :right_point
8
+ attr_accessor :above
9
+ attr_accessor :below
14
10
 
15
- def <(other_segment)
16
- return true if @edge<other_segment.edge
17
- return false
18
- end
19
11
 
20
- def >(other_segment)
21
- return true if @edge>other_segment.edge
22
- return false
23
- end
12
+ def initialize(event)
13
+ @edge = event[:edge]
14
+ end
24
15
 
25
- def == (other_segment)
26
- @edge == other_segment.edge && @left_point == other_segment.left_point && @right_point == other_segment.right_point
27
- end
16
+ def <(other_segment)
17
+ return true if @edge<other_segment.edge
18
+ return false
19
+ end
28
20
 
29
- def to_s
30
- return "edge:#{@edge.to_s}"
31
- end
21
+ def >(other_segment)
22
+ return true if @edge>other_segment.edge
23
+ return false
24
+ end
32
25
 
33
- def intersection_point_with(other_segment)
34
- numerator = (other_segment.left_point.y - @left_point.y) * (other_segment.left_point.x - other_segment.right_point.x) -
35
- (other_segment.left_point.y - other_segment.right_point.y) * (other_segment.left_point.x - @left_point.x)
26
+ def == (other_segment)
27
+ @edge == other_segment.edge && @left_point == other_segment.left_point && @right_point == other_segment.right_point
28
+ end
36
29
 
37
- denominator = (@right_point.y - @left_point.y) * (other_segment.left_point.x - other_segment.right_point.x) -
38
- (other_segment.left_point.y - other_segment.right_point.y) * (@right_point.x - @left_point.x)
30
+ def to_s
31
+ return "edge:#{@edge.to_s}"
32
+ end
39
33
 
40
- t = numerator.to_f / denominator
34
+ def intersection_point_with(other_segment)
35
+ numerator = (other_segment.left_point.y - @left_point.y) * (other_segment.left_point.x - other_segment.right_point.x) -
36
+ (other_segment.left_point.y - other_segment.right_point.y) * (other_segment.left_point.x - @left_point.x)
41
37
 
42
- x = @left_point.x + t * (@right_point.x - @left_point.x)
43
- y = @left_point.y + t * (@right_point.y - @left_point.y)
38
+ denominator = (@right_point.y - @left_point.y) * (other_segment.left_point.x - other_segment.right_point.x) -
39
+ (other_segment.left_point.y - other_segment.right_point.y) * (@right_point.x - @left_point.x)
44
40
 
45
- Point.new(x, y)
46
- end
41
+ t = numerator.to_f / denominator
47
42
 
43
+ x = @left_point.x + t * (@right_point.x - @left_point.x)
44
+ y = @left_point.y + t * (@right_point.y - @left_point.y)
45
+
46
+ Point.new(x, y)
47
+ end
48
+ end
48
49
  end
@@ -1,138 +1,140 @@
1
- class SweepLine
2
- attr_reader :tree
3
- attr_reader :polygon
4
-
5
- def initialize(polygon)
6
- @tree = AVLTree.new
7
- @polygon = polygon
8
- end
9
-
10
- def add(event)
11
- # build up segment data
12
- seg = Segment.new(event)
13
- p1 = @polygon.vertices[seg.edge]
14
- p2 = @polygon.vertices[seg.edge + 1]
15
-
16
- # if it is being added, then it must be a LEFT edge event
17
- # but need to determine which endpoint is the left one first
18
-
19
- if p1.compare(p2) < 0
20
- seg.left_point = p1
21
- seg.right_point = p2
22
- else
23
- seg.left_point = p2
24
- seg.right_point = p1
1
+ module WindingPolygon
2
+ class SweepLine
3
+ attr_reader :tree
4
+ attr_reader :polygon
5
+
6
+ def initialize(polygon)
7
+ @tree = AVLTree.new
8
+ @polygon = polygon
25
9
  end
26
10
 
27
- # Add node to tree and setup linkages to "above" and "below"
28
- # edges as per algorithm
29
- nd = @tree.insert(seg)
30
-
31
- nx = nd.next
32
- np = nd.prev
11
+ def add(event)
12
+ # build up segment data
13
+ seg = Segment.new(event)
14
+ p1 = @polygon.vertices[seg.edge]
15
+ p2 = @polygon.vertices[seg.edge + 1]
16
+
17
+ # if it is being added, then it must be a LEFT edge event
18
+ # but need to determine which endpoint is the left one first
19
+
20
+ if p1.compare(p2) < 0
21
+ seg.left_point = p1
22
+ seg.right_point = p2
23
+ else
24
+ seg.left_point = p2
25
+ seg.right_point = p1
26
+ end
27
+
28
+ # Add node to tree and setup linkages to "above" and "below"
29
+ # edges as per algorithm
30
+ nd = @tree.insert(seg)
31
+
32
+ nx = nd.next
33
+ np = nd.prev
34
+
35
+ if !nx.nil?
36
+ seg.above = nx.value
37
+ seg.above.below = seg
38
+ end
39
+
40
+ if !np.nil?
41
+ seg.below = np.value
42
+ seg.below.above = seg
43
+ end
44
+ return seg
33
45
 
34
- if !nx.nil?
35
- seg.above = nx.value
36
- seg.above.below = seg
37
46
  end
38
47
 
39
- if !np.nil?
40
- seg.below = np.value
41
- seg.below.above = seg
42
- end
43
- return seg
44
-
45
- end
48
+ def find(event)
49
+ # need a segment to find it in the tree
50
+ seg = Segment.new(event)
51
+ p1 = @polygon.vertices[seg.edge]
52
+ p2 = @polygon.vertices[seg.edge + 1]
46
53
 
47
- def find(event)
48
- # need a segment to find it in the tree
49
- seg = Segment.new(event)
50
- p1 = @polygon.vertices[seg.edge]
51
- p2 = @polygon.vertices[seg.edge + 1]
52
-
53
- # if it is being added, then it must be a LEFT edge event
54
- # but need to determine which endpoint is the left one first
55
- if p1.compare(p2) < 0
56
- seg.left_point = p1
57
- seg.right_point = p2
58
- else
59
- seg.left_point = p2
60
- seg.right_point = p1
61
- end
54
+ # if it is being added, then it must be a LEFT edge event
55
+ # but need to determine which endpoint is the left one first
56
+ if p1.compare(p2) < 0
57
+ seg.left_point = p1
58
+ seg.right_point = p2
59
+ else
60
+ seg.left_point = p2
61
+ seg.right_point = p1
62
+ end
62
63
 
63
- node = @tree.search(seg)
64
+ node = @tree.search(seg)
64
65
 
65
- return nil if node.nil?
66
+ return nil if node.nil?
66
67
 
67
- node.value
68
- end
68
+ node.value
69
+ end
69
70
 
70
- def remove(seg)
71
- nd = @tree.search(seg)
72
- return if nd.nil?
71
+ def remove(seg)
72
+ nd = @tree.search(seg)
73
+ return if nd.nil?
73
74
 
74
- nx = nd.next
75
- nx.value.below = seg.below if !nx.nil?
75
+ nx = nd.next
76
+ nx.value.below = seg.below if !nx.nil?
76
77
 
77
- np = nd.prev
78
- np.value.above = seg.above if !np.nil?
78
+ np = nd.prev
79
+ np.value.above = seg.above if !np.nil?
79
80
 
80
- @tree.delete(seg)
81
- end
81
+ @tree.delete(seg)
82
+ end
82
83
 
83
- def switch(s1,s2)
84
- nd1 = @tree.search(s1)
85
- return if nd1.nil?
84
+ def switch(s1,s2)
85
+ nd1 = @tree.search(s1)
86
+ return if nd1.nil?
86
87
 
87
- nd2 = @tree.search(s2)
88
- return if nd2.nil?
88
+ nd2 = @tree.search(s2)
89
+ return if nd2.nil?
89
90
 
90
- nx1 = nd1.next
91
- nx1.value.below = nd2.value if !nx1.nil?
91
+ nx1 = nd1.next
92
+ nx1.value.below = nd2.value if !nx1.nil?
92
93
 
93
- np1 = nd1.prev
94
- np1.value.above = nd2.value if !np1.nil?
94
+ np1 = nd1.prev
95
+ np1.value.above = nd2.value if !np1.nil?
95
96
 
96
- nx2 = nd2.next
97
- nx2.value.below = nd1.value if !nx2.nil?
97
+ nx2 = nd2.next
98
+ nx2.value.below = nd1.value if !nx2.nil?
98
99
 
99
- np2 = nd2.prev
100
- np2.value.above = nd1.value if !np2.nil?
100
+ np2 = nd2.prev
101
+ np2.value.above = nd1.value if !np2.nil?
101
102
 
102
- end
103
+ end
103
104
 
104
- #test intersect of 2 segments and return: nil when none, point when intersecting
105
- def intersect(s1,s2)
106
- # no intersect if either segment doesn't existend
107
- return nil if s1.nil? || s2.nil?
105
+ #test intersect of 2 segments and return: nil when none, point when intersecting
106
+ def intersect(s1,s2)
107
+ # no intersect if either segment doesn't existend
108
+ return nil if s1.nil? || s2.nil?
108
109
 
109
- # check for consecutive edges in polygon
110
- e1 = s1.edge
111
- e2 = s2.edge
110
+ # check for consecutive edges in polygon
111
+ e1 = s1.edge
112
+ e2 = s2.edge
112
113
 
113
- # no non-simple intersect since consecutive
114
- polygon_edges = @polygon.vertices.length-1
115
- return nil if (((e1+1)%polygon_edges === e2) || (e1 === (e2+1)%polygon_edges))
114
+ # no non-simple intersect since consecutive
115
+ polygon_edges = @polygon.vertices.length-1
116
+ return nil if (((e1+1)%polygon_edges === e2) || (e1 === (e2+1)%polygon_edges))
116
117
 
117
118
 
118
- #test for existence of an intersect point
119
- #s2 left point sign
120
- lsign = s2.left_point.is_left(s1.left_point, s1.right_point)
121
- #s2 right point sign
122
- rsign = s2.right_point.is_left(s1.left_point, s1.right_point)
119
+ #test for existence of an intersect point
120
+ #s2 left point sign
121
+ lsign = s2.left_point.is_left(s1.left_point, s1.right_point)
122
+ #s2 right point sign
123
+ rsign = s2.right_point.is_left(s1.left_point, s1.right_point)
123
124
 
124
- # s2 endpoints have same sign relative to s1 => on same side => no intersect is possible
125
- return nil if (lsign * rsign > 0)
125
+ # s2 endpoints have same sign relative to s1 => on same side => no intersect is possible
126
+ return nil if (lsign * rsign > 0)
126
127
 
127
- # s1 left point sign
128
- lsign = s1.left_point.is_left(s2.left_point, s2.right_point)
129
- #s1 right point sign
130
- rsign = s1.right_point.is_left(s2.left_point, s2.right_point)
128
+ # s1 left point sign
129
+ lsign = s1.left_point.is_left(s2.left_point, s2.right_point)
130
+ #s1 right point sign
131
+ rsign = s1.right_point.is_left(s2.left_point, s2.right_point)
131
132
 
132
- # s1 endpoints have same sign relative to s2 => on same side => no intersect is possible
133
- return nil if (lsign * rsign > 0)
133
+ # s1 endpoints have same sign relative to s2 => on same side => no intersect is possible
134
+ return nil if (lsign * rsign > 0)
134
135
 
135
- #segments s1 and s2 straddle. Intersect exists.
136
- s1.intersection_point_with(s2)
136
+ #segments s1 and s2 straddle. Intersect exists.
137
+ s1.intersection_point_with(s2)
138
+ end
137
139
  end
138
140
  end