def __init__(self, segment_list): self.event_queue = PriorityQueue() # sorted along x self.sweep_line = SlowTree() # sorted along y for segment in segment_list: # Zalozone segment.pt1.x < segment.pt2.x. # Trzeba obsluzyc druga mozliwosc. if segment.pt1.x > segment.pt2.x: segment = ~segment self.event_queue.push(Event(segment.pt1, Event.LEFT, segment)) self.event_queue.push(Event(segment.pt2, Event.RIGHT, segment))
def test_pq(self): pq = PriorityQueue() self.assertTrue(pq.empty()) self.assertEqual(len(pq), 0) self.assertEqual(str(pq), "[]") pq.push(3) self.assertFalse(pq.empty()) self.assertEqual(len(pq), 1) self.assertEqual(str(pq), "[3]") pq.push(3) # ignored self.assertEqual(len(pq), 1) pq.push(5) self.assertEqual(len(pq), 2) pq.push(2) self.assertEqual(str(pq), "[2, 5, 3]") # heap self.assertEqual(len(pq), 3) self.assertEqual(pq.pop(), 2) self.assertEqual(pq.pop(), 3) self.assertEqual(pq.pop(), 5)
class ShamosHoey: """Shamos-Hoey algorithm - educational version. http://geomalgorithms.com/a09-_intersect-3.html """ def __init__(self, segment_list): self.event_queue = PriorityQueue() # sorted along x self.sweep_line = SlowTree() # sorted along y for segment in segment_list: # Zalozone segment.pt1.x < segment.pt2.x. # Trzeba obsluzyc druga mozliwosc. if segment.pt1.x > segment.pt2.x: segment = ~segment self.event_queue.push(Event(segment.pt1, Event.LEFT, segment)) self.event_queue.push(Event(segment.pt2, Event.RIGHT, segment)) def run(self): while not self.event_queue.empty(): event = self.event_queue.pop() if event.type == Event.LEFT: if self._handle_left_endpoint(event): return True elif event.type == Event.RIGHT: if self._handle_right_endpoint(event): return True else: raise ValueError("unknown event") return False def _handle_left_endpoint(self, event): segment_e = event.segment # Let segE = E's segment self.sweep_line.insert(segment_e) # Add segE to SL segment_above = self.sweep_line.successor(segment_e) # Let segA = the segment Above segE in SL segment_below = self.sweep_line.predecessor(segment_e) # Let segB = the segment Below segE in SL if segment_above: # if exists segment_above = segment_above.value # get segment from node if segment_e.intersect(segment_above): # If (I = Intersect( segE with segA) exists) return True if segment_below: # if exists segment_below = segment_below.value # get segment from node if segment_e.intersect(segment_below): # If (I = Intersect( segE with segB) exists) return True return False def _handle_right_endpoint(self, event): segment_e = event.segment # Let segE = E's segment segment_above = self.sweep_line.successor(segment_e) # Let segA = the segment Above segE in SL segment_below = self.sweep_line.predecessor(segment_e) # Let segB = the segment Below segE in SL if segment_above and segment_below: # if exists segment_above = segment_above.value # get segment from node segment_below = segment_below.value # get segment from node if segment_above.intersect(segment_below): # If (I = Intersect( segA with segB) exists) return True self.sweep_line.remove(segment_e) return False
class BentleyOttmann: """Bentley-Ottmann algorithm - educational version.""" def __init__(self, segment_list): self.event_queue = PriorityQueue() # sorted along x self.sweep_line = SlowTree() # sorted along y for segment in segment_list: # Zalozone segment.pt1.x < segment.pt2.x. # Trzeba obsluzyc druga mozliwosc. if segment.pt1.x > segment.pt2.x: segment = ~segment self.event_queue.push(Event(segment.pt1, Event.LEFT, segment)) self.event_queue.push(Event(segment.pt2, Event.RIGHT, segment)) self.il = [] # intersection list def run(self): while not self.event_queue.empty(): event = self.event_queue.pop() if event.type == Event.LEFT: self._handle_left_endpoint(event) elif event.type == Event.RIGHT: self._handle_right_endpoint(event) elif event.type == Event.CROSSING: self._handle_crossing(event) else: raise ValueError("unknown event") del self.event_queue del self.sweep_line return self.il def _handle_left_endpoint(self, event): segment_e = event.segment # Let segE = E's segment self.sweep_line.insert(segment_e) # Add segE to SL segment_above = self.sweep_line.successor( segment_e) # Let segA = the segment Above segE in SL segment_below = self.sweep_line.predecessor( segment_e) # Let segB = the segment Below segE in SL if segment_above: # if exists segment_above = segment_above.value # get segment from node point = segment_e.intersection_point(segment_above) if point and point.x > event.point.x: self.event_queue.push( Event(point, Event.CROSSING, segment_above, segment_e)) if segment_below: # if exists segment_below = segment_below.value # get segment from node point = segment_e.intersection_point(segment_below) if point and point.x > event.point.x: self.event_queue.push( Event(point, Event.CROSSING, segment_e, segment_below)) def _handle_right_endpoint(self, event): segment_e = event.segment # Let segE = E's segment segment_above = self.sweep_line.successor( segment_e) # Let segA = the segment Above segE in SL segment_below = self.sweep_line.predecessor( segment_e) # Let segB = the segment Below segE in SL if segment_above and segment_below: # if exists segment_above = segment_above.value # get segment from node segment_below = segment_below.value # get segment from node point = segment_above.intersection_point(segment_below) if point and point.x > event.point.x: self.event_queue.push( Event(point, Event.CROSSING, segment_above, segment_below)) self.sweep_line.remove(segment_e) def _handle_crossing(self, event): self.il.append( event.point) # Add Es intersect point to the output list IL # Let segE1 above segE2 be E's intersecting segments in SL segment_e1 = event.segment_above segment_e2 = event.segment_below # Swap their positions so that segE2 is now above segE1; self.sweep_line.swap(segment_e1, segment_e2) segment_above_e2 = self.sweep_line.successor( segment_e2) # Let segA = the segment above segE2 in SL segment_below_e1 = self.sweep_line.predecessor( segment_e1) # Let segB = the segment below segE1 in SL if segment_above_e2: segment_above_e2 = segment_above_e2.value point = segment_above_e2.intersection_point(segment_e2) if point and point.x > event.point.x: self.event_queue.push( Event(point, Event.CROSSING, segment_above_e2, segment_e2)) if segment_below_e1: segment_below_e1 = segment_below_e1.value point = segment_below_e1.intersection_point(segment_e1) if point and point.x > event.point.x: self.event_queue.push( Event(point, Event.CROSSING, segment_e1, segment_below_e1))