Example #1
0
    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))
Example #2
0
 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)
Example #3
0
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
Example #4
0
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))