示例#1
0
def intersects_with_polygon(box: Box, polygon: Polygon,
                            context: Context) -> bool:
    """
    Checks if the box intersects the polygon.
    """
    border = polygon.border
    polygon_box = context.contour_box(border)
    if not intersects_with(polygon_box, box):
        return False
    elif (is_subset_of(polygon_box, box)
          or any(contains_point(box, vertex) for vertex in border.vertices)):
        return True
    locations = [
        point_in_region(vertex, border)
        for vertex in to_vertices(box, context)
    ]
    if (within_of(box, polygon_box)
            and all(location is Location.INTERIOR for location in locations)
            and all(
                context.segments_relation(edge, border_edge) is
                Relation.DISJOINT for edge in to_edges(box, context)
                for border_edge in context.contour_segments(border))):
        return not any(
            within_of(box, context.contour_box(hole))
            and within_of_region(box, hole, context) for hole in polygon.holes)
    else:
        return (any(location is not Location.EXTERIOR
                    for location in locations) or any(
                        intersects_with_segment(box, edge, context)
                        for edge in context.contour_segments(border)))
def test_step(context: Context, contour: Contour) -> None:
    first_vertex, rest_contour = pop_left_vertex(contour)
    rest_vertices = rest_contour.vertices

    result = contour_self_intersects(rest_contour)
    next_result = contour_self_intersects(contour)

    first_edge = context.segment_cls(first_vertex, rest_vertices[0])
    last_edge = context.segment_cls(rest_vertices[-1], first_vertex)
    rest_edges = contour_to_edges(rest_contour)
    overlap_relations = (Relation.COMPONENT, Relation.COMPOSITE,
                         Relation.EQUAL, Relation.OVERLAP)
    assert (next_result is (result and len(rest_vertices) > 2 and (any(
        context.segments_relation(rest_edges[index], rest_edges[other_index])
        is not Relation.DISJOINT for index in range(len(rest_edges) - 1)
        for other_index in chain(range(index -
                                       1), range(index + 2,
                                                 len(rest_edges) - 1))
    ) or any(
        context.segments_relation(edge, other_edge) in overlap_relations
        for edge, other_edge in combinations(rest_edges[:-1], 2)
    )) or any(
        context.segments_relation(first_edge, edge) is not Relation.DISJOINT
        for edge in rest_edges[1:-1]) or any(
            context.segments_relation(last_edge, edge) is not Relation.DISJOINT
            for edge in rest_edges[:-2]) or len(rest_vertices) > 1 and (
                context.segments_relation(first_edge, rest_edges[0])
                in overlap_relations or context.segments_relation(
                    first_edge, last_edge) in overlap_relations
                or context.segments_relation(
                    last_edge, rest_edges[0]) in overlap_relations)))
示例#3
0
def test_step(context: Context, segments: List[Segment]) -> None:
    first_segment, *rest_segments = segments

    result = segments_cross_or_overlap(rest_segments)
    next_result = segments_cross_or_overlap(segments)

    assert (next_result is (result or any(
        context.segments_relation(first_segment, segment) in
        (Relation.COMPONENT, Relation.COMPOSITE, Relation.CROSS,
         Relation.EQUAL, Relation.OVERLAP) for segment in rest_segments)))
示例#4
0
def within_of_region(box: Box, border: Contour, context: Context) -> bool:
    """
    Checks if the box is contained in an interior of the region.
    """
    return (all(
        point_in_region(vertex, border) is Location.INTERIOR
        for vertex in to_vertices(box, context)) and all(
            context.segments_relation(edge, border_edge) is Relation.DISJOINT
            for edge in to_edges(box, context)
            for border_edge in context.contour_segments(border)))
示例#5
0
def coupled_with_segment(box: Box, segment: Segment, context: Context) -> bool:
    """
    Checks if the box intersects the segment at more than one point.
    """
    segment_box = context.segment_box(segment)
    return (coupled_with(segment_box, box)
            and (is_subset_of(segment_box, box) or any(
                context.segments_relation(edge, segment) not in
                (Relation.TOUCH, Relation.DISJOINT)
                for edge in to_edges(box, context))))
示例#6
0
def intersects_with_segment(box: Box, segment: Segment,
                            context: Context) -> bool:
    """
    Checks if the box intersects the segment.
    """
    segment_box = context.segment_box(segment)
    return (intersects_with(
        segment_box, box) and (is_subset_of(segment_box, box) or any(
            context.segments_relation(edge, segment) is not Relation.DISJOINT
            for edge in to_edges(box, context))))
def test_step(context: Context, contour: Contour) -> None:
    first_vertex, *rest_vertices = contour.vertices
    rest_contour = Contour(rest_vertices)

    result = edges_intersect(rest_contour)
    next_result = edges_intersect(contour)

    first_edge, last_edge = (Segment(first_vertex, rest_vertices[0]),
                             Segment(rest_vertices[-1], first_vertex))
    rest_edges = contour_to_edges(rest_contour)
    overlap_relations = (Relation.COMPONENT, Relation.COMPOSITE,
                         Relation.EQUAL, Relation.OVERLAP)
    assert (next_result is (result and len(rest_vertices) > 2 and (any(
        segments_pair_intersections(
            rest_edges[index].start, rest_edges[index].end,
            rest_edges[other_index].start, rest_edges[other_index].end)
        for index in range(len(rest_edges) - 1)
        for other_index in chain(range(index -
                                       1), range(index + 2,
                                                 len(rest_edges) - 1))
    ) or any(
        segments_pair_intersections(edge.start, edge.end, other_edge.start,
                                    other_edge.end) in overlap_relations
        for edge, other_edge in combinations(rest_edges[:-1], 2))) or any(
            segments_pair_intersections(first_edge.start, first_edge.end,
                                        edge.start, edge.end)
            for edge in rest_edges[1:-1]) or any(
                segments_pair_intersections(last_edge.start, last_edge.end,
                                            edge.start, edge.end)
                for edge in rest_edges[:-2]) or len(rest_vertices) > 1 and (
                    context.segments_relation(
                        first_edge.start, first_edge.end, rest_edges[0].start,
                        rest_edges[0].end) in overlap_relations or
                    context.segments_relation(first_edge.start, first_edge.end,
                                              last_edge.start, last_edge.end)
                    in overlap_relations or context.segments_relation(
                        last_edge.start, last_edge.end, rest_edges[0].start,
                        rest_edges[0].end) in overlap_relations)))
示例#8
0
def unite_segments(first: Segment,
                   second: Segment,
                   context: Context) -> Union_[Multisegment, Segment]:
    relation = context.segments_relation(first, second)
    if relation is Relation.DISJOINT:
        return context.multisegment_cls([first, second])
    elif relation is Relation.EQUAL or relation is Relation.COMPOSITE:
        return first
    elif relation is Relation.COMPONENT:
        return second
    else:
        return (_unite_segments_touch
                if relation is Relation.TOUCH
                else (_unite_segments_cross
                      if relation is Relation.CROSS
                      else _unite_segments_overlap))(first, second, context)
示例#9
0
def subtract_segments(minuend: Segment,
                      subtrahend: Segment,
                      context: Context
                      ) -> Union_[Empty, Multisegment, Segment]:
    relation = context.segments_relation(minuend, subtrahend)
    if relation is Relation.COMPONENT or relation is Relation.EQUAL:
        return context.empty
    elif (relation is Relation.DISJOINT
          or relation is Relation.TOUCH
          or relation is Relation.CROSS):
        return minuend
    else:
        return (_subtract_segments_overlap(minuend, subtrahend, context)
                if relation is Relation.OVERLAP
                else _subtract_segments_composite(minuend, subtrahend,
                                                  context))
示例#10
0
def intersect_segments(first: Segment,
                       second: Segment,
                       context: Context) -> Union_[Empty, Multipoint, Segment]:
    relation = context.segments_relation(first, second)
    if relation is Relation.DISJOINT:
        return context.empty
    elif relation is Relation.TOUCH or relation is Relation.CROSS:
        return context.multipoint_cls([context.segments_intersection(first,
                                                                     second)])
    else:
        return (first
                if relation is Relation.EQUAL or relation is Relation.COMPONENT
                else
                (second
                 if relation is Relation.COMPOSITE
                 else _intersect_segments_overlap(first, second, context)))
示例#11
0
def _intersect_segment_with_multisegment(segment: Segment,
                                         multisegment: Multisegment,
                                         context: Context) -> List[Segment]:
    result = []
    for sub_segment in multisegment.segments:
        relation = context.segments_relation(segment, sub_segment)
        if (relation is not Relation.DISJOINT
                and relation is not Relation.TOUCH
                and relation is not Relation.CROSS):
            result.append(segment
                          if (relation is Relation.EQUAL
                              or relation is Relation.COMPONENT)
                          else (sub_segment
                                if relation is Relation.COMPOSITE
                                else _intersect_segments_overlap(segment,
                                                                 sub_segment,
                                                                 context)))
    return result
示例#12
0
def _subtract_segment_from_multisegment(multisegment: Multisegment,
                                        segment: Segment,
                                        context: Context) -> List[Segment]:
    result = []
    segment_cls = context.segment_cls
    for index, sub_segment in enumerate(multisegment.segments):
        relation = context.segments_relation(segment, sub_segment)
        if relation is Relation.EQUAL:
            result.extend(multisegment.segments[index + 1:])
            break
        elif relation is Relation.COMPONENT:
            left_start, left_end, right_start, right_end = sorted([
                sub_segment.start, sub_segment.end, segment.start,
                segment.end])
            result.extend(
                    [segment_cls(right_start, right_end)]
                    if left_start == segment.start or left_start == segment.end
                    else
                    ((([segment_cls(left_start, left_end)]
                       if right_start == right_end
                       else [segment_cls(left_start, left_end),
                             segment_cls(right_start, right_end)])
                      if (right_start == segment.start
                          or right_start == segment.end)
                      else [segment_cls(left_start, left_end)])
                     if left_end == segment.start or left_end == segment.end
                     else [segment_cls(left_start, right_start)]))
            result.extend(multisegment.segments[index + 1:])
            break
        elif relation is Relation.CROSS:
            cross_point = context.segments_intersection(sub_segment, segment)
            result.append(segment_cls(sub_segment.start, cross_point))
            result.append(segment_cls(cross_point, sub_segment.end))
        elif relation is Relation.OVERLAP:
            result.append(_subtract_segments_overlap(sub_segment, segment,
                                                     context))
        elif relation is not Relation.COMPOSITE:
            result.append(sub_segment)
    return result
示例#13
0
def symmetric_subtract_segments(first: Segment,
                                second: Segment,
                                context: Context
                                ) -> Union_[Empty, Multisegment, Segment]:
    relation = context.segments_relation(first, second)
    if relation is Relation.DISJOINT:
        return context.multisegment_cls([first, second])
    elif relation is Relation.EQUAL:
        return context.empty
    else:
        return (_unite_segments_touch(first, second, context)
                if relation is Relation.TOUCH
                else
                (_unite_segments_cross(first, second, context)
                 if relation is Relation.CROSS
                 else
                 (_symmetric_subtract_segments_overlap(first, second, context)
                  if relation is Relation.OVERLAP
                  else (_subtract_segments_composite(first, second, context)
                        if relation is Relation.COMPOSITE
                        else _subtract_segments_composite(second, first,
                                                          context)))))
示例#14
0
def test_step(context: Context, segments: List[Segment]) -> None:
    *rest_segments, last_segment = segments

    result = segments_intersections(rest_segments)
    next_result = segments_intersections(segments)

    assert (next_result.keys() == (
        result.keys()
        | {(index, len(segments) - 1)
           for index, segment in enumerate(rest_segments) if context.
           segments_relation(segment, last_segment) is not Relation.DISJOINT}))
    assert result.items() <= next_result.items()
    assert all(segment_id < next_segment_id == len(segments) - 1
               for segment_id, next_segment_id in (next_result.keys() -
                                                   result.keys()))
    assert all(
        context.segments_intersection(
            segments[segment_id], segments[next_segment_id]) == next_result[(
                segment_id, next_segment_id)][0] if len(next_result[(
                    segment_id,
                    next_segment_id)]) == 1 else context.segments_intersection(
                        segments[segment_id], segments[next_segment_id]) not in
        (Relation.DISJOINT, Relation.TOUCH, Relation.CROSS) and (
            to_sorted_pair(*next_result[(segment_id, next_segment_id)]) ==
            next_result[(segment_id, next_segment_id)]) and all(
                context.segment_contains_point(segments[segment_id], point)
                for point in next_result[(segment_id, next_segment_id)])
        and all(
            context.segment_contains_point(segments[next_segment_id], point)
            for point in next_result[(segment_id, next_segment_id)])
        for segment_id, next_segment_id in (next_result.keys() -
                                            result.keys()))
    assert all(
        context.segments_relation(segments[segment_id],
                                  segments[next_segment_id])
        is not Relation.DISJOINT
        for segment_id, next_segment_id in (next_result.keys() -
                                            result.keys()))
示例#15
0
def relate_segment(goal: Segment, test: Segment, context: Context) -> Relation:
    return context.segments_relation(test, goal)