Ejemplo n.º 1
0
def relate_multisegment(goal: Multisegment, test: Multisegment,
                        context: Context) -> Relation:
    goal_bounding_box = context.segments_box(goal.segments)
    test_bounding_box = context.segments_box(test.segments)
    if box.disjoint_with(goal_bounding_box, test_bounding_box):
        return Relation.DISJOINT
    events_queue = LinearEventsQueue(context)
    events_queue.register(to_segments_endpoints(goal), from_test=False)
    events_queue.register(to_segments_endpoints(test), from_test=True)
    return process_open_linear_queue(
        events_queue, min(goal_bounding_box.max_x, test_bounding_box.max_x))
Ejemplo n.º 2
0
def relate_multisegment(contour: Contour, multisegment: Multisegment,
                        context: Context) -> Relation:
    contour_bounding_box = context.contour_box(contour)
    multisegment_bounding_box = context.segments_box(multisegment.segments)
    if box.disjoint_with(contour_bounding_box, multisegment_bounding_box):
        return Relation.DISJOINT
    events_queue = LinearEventsQueue(context)
    events_queue.register(to_edges_endpoints(contour), from_test=False)
    events_queue.register(to_segments_endpoints(multisegment), from_test=True)
    return process_open_linear_queue(
        events_queue,
        min(contour_bounding_box.max_x, multisegment_bounding_box.max_x))
Ejemplo n.º 3
0
def relate_multisegment(polygon: Polygon, multisegment: Multisegment,
                        context: Context) -> Relation:
    polygon_bounding_box = context.polygon_box(polygon)
    multisegment_bounding_box = context.segments_box(multisegment.segments)
    if box.disjoint_with(polygon_bounding_box, multisegment_bounding_box):
        return Relation.DISJOINT
    events_queue = CompoundEventsQueue(context)
    events_queue.register(to_oriented_edges_endpoints(polygon, context),
                          from_test=False)
    events_queue.register(to_segments_endpoints(multisegment), from_test=True)
    return process_linear_compound_queue(
        events_queue,
        min(multisegment_bounding_box.max_x, polygon_bounding_box.max_x))
Ejemplo n.º 4
0
def relate_multisegment(multipolygon: Multipolygon, multisegment: Multisegment,
                        context: Context) -> Relation:
    multisegment_bounding_box = context.segments_box(multisegment.segments)
    disjoint, multipolygon_max_x, events_queue = True, None, None
    for polygon in multipolygon.polygons:
        polygon_bounding_box = context.polygon_box(polygon)
        if not box.disjoint_with(polygon_bounding_box,
                                 multisegment_bounding_box):
            if disjoint:
                disjoint = False
                multipolygon_max_x = polygon_bounding_box.max_x
                events_queue = CompoundEventsQueue(context)
                events_queue.register(to_segments_endpoints(multisegment),
                                      from_test=True)
            else:
                multipolygon_max_x = max(multipolygon_max_x,
                                         polygon_bounding_box.max_x)
            events_queue.register(polygon_to_oriented_segments(
                polygon, context),
                                  from_test=False)
    return (Relation.DISJOINT if disjoint else process_linear_compound_queue(
        events_queue, min(multisegment_bounding_box.max_x,
                          multipolygon_max_x)))
Ejemplo n.º 5
0
def relate_multisegment(multiregion: Multiregion, multisegment: Multisegment,
                        context: Context) -> Relation:
    return _relate_multisegment(multiregion, multisegment,
                                context.segments_box(multisegment.segments),
                                context)
Ejemplo n.º 6
0
    def from_multisegment(cls,
                          multisegment: Multisegment,
                          *,
                          shuffler: Shuffler = random.shuffle,
                          context: Context) -> 'Graph':
        """
        Constructs trapezoidal decomposition graph of given multisegment.

        Based on incremental randomized algorithm by R. Seidel.

        Time complexity:
            ``O(segments_count * log segments_count)`` expected,
            ``O(segments_count ** 2)`` worst
        Memory complexity:
            ``O(segments_count)``

        where ``segments_count = len(multisegment.segments)``

        Reference:
            https://doi.org/10.1016%2F0925-7721%2891%2990012-4
            https://www.cs.princeton.edu/courses/archive/fall05/cos528/handouts/A%20Simple%20and%20fast.pdf

        :param multisegment: target multisegment.
        :param shuffler:
            function which mutates sequence by shuffling its elements,
            required for randomization.
        :param context: geometric context.
        :returns: trapezoidal decomposition graph of the multisegment.

        >>> from ground.base import get_context
        >>> context = get_context()
        >>> Multisegment, Point, Segment = (context.multisegment_cls,
        ...                                 context.point_cls,
        ...                                 context.segment_cls)
        >>> graph = Graph.from_multisegment(
        ...     Multisegment([Segment(Point(0, 0), Point(1, 0)),
        ...                   Segment(Point(0, 0), Point(0, 1))]),
        ...     context=context)
        >>> Point(1, 0) in graph
        True
        >>> Point(0, 1) in graph
        True
        >>> Point(1, 1) in graph
        False
        >>> graph.locate(Point(1, 0)) is Location.BOUNDARY
        True
        >>> graph.locate(Point(0, 1)) is Location.BOUNDARY
        True
        >>> graph.locate(Point(1, 1)) is Location.EXTERIOR
        True
        """
        edges = [
            Edge.from_endpoints(segment.start, segment.end, False, context)
            if segment.start < segment.end else Edge.from_endpoints(
                segment.end, segment.start, False, context)
            for segment in multisegment.segments
        ]
        shuffler(edges)
        result = cls(
            box_to_node(context.segments_box(multisegment.segments), context))
        for edge in edges:
            add_edge(result, edge)
        return result