def unpack_segments(segments: Sequence[Segment], context: Context) -> Union[Empty, Multisegment, Segment]: return ((context.multisegment_cls(segments) if len(segments) > 1 else segments[0]) if segments else context.empty)
def _symmetric_subtract_segments_overlap(minuend: Segment, subtrahend: Segment, context: Context) -> Multisegment: left_start, left_end, right_start, right_end = sorted([ minuend.start, minuend.end, subtrahend.start, subtrahend.end]) return context.multisegment_cls([context.segment_cls(left_start, left_end), context.segment_cls(right_start, right_end)])
def _unite_segments_cross(first: Segment, second: Segment, context: Context) -> Multisegment: cross_point = context.segments_intersection(first, second) segment_cls = context.segment_cls return context.multisegment_cls([segment_cls(first.start, cross_point), segment_cls(second.start, cross_point), segment_cls(cross_point, first.end), segment_cls(cross_point, second.end)])
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)
def _subtract_segments_composite(minuend: Segment, subtrahend: Segment, context: Context ) -> Union_[Multisegment, Segment]: left_start, left_end, right_start, right_end = sorted([ minuend.start, minuend.end, subtrahend.start, subtrahend.end]) return (context.segment_cls(right_start, right_end) if left_start == subtrahend.start or left_start == subtrahend.end else (((context.segment_cls(left_start, left_end) if right_start == right_end else context.multisegment_cls([context.segment_cls(left_start, left_end), context.segment_cls(right_start, right_end)])) if (right_start == subtrahend.start or right_start == subtrahend.end) else context.segment_cls(left_start, left_end)) if left_end == subtrahend.start or left_end == subtrahend.end else context.segment_cls(left_start, right_start)))
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)))))
def _unite_segments_touch(first: Segment, second: Segment, context: Context) -> Union_[Multisegment, Segment]: return (context.multisegment_cls([first, second]) if ((first.start != second.start or (context.angle_orientation(first.start, first.end, second.end) is not Orientation.COLLINEAR)) and (first.start != second.end or (context.angle_orientation(first.start, first.end, second.start) is not Orientation.COLLINEAR)) and (first.end != second.start or (context.angle_orientation(first.end, first.start, second.end) is not Orientation.COLLINEAR)) and (first.end != second.end or (context.angle_orientation(first.end, first.start, second.start) is not Orientation.COLLINEAR))) else context.segment_cls(min(first.start, first.end, second.start, second.end), max(first.start, first.end, second.start, second.end)))
def merge_segments(segments: Sequence[Segment], *, context: Context) -> Multisegment: return context.multisegment_cls(_merge_segments(segments, context=context))
def relate_segment(multiregion: Multiregion, segment: Segment, context: Context) -> Relation: return _relate_multisegment(multiregion, context.multisegment_cls([segment]), context.segment_box(segment), context)
def relate_segment(multipolygon: Multipolygon, segment: Segment, context: Context) -> Relation: return relate_multisegment(multipolygon, context.multisegment_cls([segment]), context)