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))
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))
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))
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)))
def relate_multisegment(multiregion: Multiregion, multisegment: Multisegment, context: Context) -> Relation: return _relate_multisegment(multiregion, multisegment, context.segments_box(multisegment.segments), context)
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