winding-polygon 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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