class HoleyEvent(ShapedEvent): __slots__ = ('interior_to_left', 'other_interior_to_left', 'overlap_kind', 'in_result', 'result_in_out', 'position', 'contour_id', 'below_in_result_event') def __init__(self, is_right_endpoint: bool, start: Point, complement: Optional['HoleyEvent'], from_left: bool, interior_to_left: bool, other_interior_to_left: bool = False, overlap_kind: OverlapKind = OverlapKind.NONE, in_result: bool = False, result_in_out: bool = False, position: int = 0, contour_id: Optional[int] = None, below_in_result_event: Optional['HoleyEvent'] = None) -> None: super().__init__(is_right_endpoint, start, complement, from_left, interior_to_left, other_interior_to_left, overlap_kind, in_result, position) self.result_in_out = result_in_out self.contour_id = contour_id self.below_in_result_event = below_in_result_event __repr__ = recursive_repr()(generate_repr(__init__))
class MyContainer3: def __repr__(self): 'Test document content' pass wrapped = __repr__ wrapper = recursive_repr()(wrapped)
class MixedEvent(BinaryEvent): __slots__ = ('interior_to_left', 'other_interior_to_left', 'is_overlap', 'in_result') def __init__(self, is_right_endpoint: bool, start: Point, complement: Optional['MixedEvent'], from_left: bool, interior_to_left: bool, other_interior_to_left: bool = False, is_overlap: bool = False, in_result: bool = False) -> None: super().__init__(is_right_endpoint, start, complement, from_left) self.interior_to_left = interior_to_left self.other_interior_to_left = other_interior_to_left self.is_overlap = is_overlap self.in_result = in_result __repr__ = recursive_repr()(generate_repr(__init__)) @property def outside(self) -> bool: """ Checks if the segment touches or disjoint with the intersection. """ return not self.other_interior_to_left and not self.is_overlap
class LeftBinaryEvent(LeftEvent): @classmethod def from_segment_endpoints(cls, segment_endpoints: SegmentEndpoints, from_first: bool) -> 'LeftBinaryEvent': start, end = segment_endpoints if start > end: start, end = end, start event = cls(start, None, from_first) event.right = RightBinaryEvent(end, event) return event __slots__ = 'from_first', '_start' def __init__(self, start: Point, right: Optional['RightBinaryEvent'], from_first: bool) -> None: self.from_first, self.right, self._start = from_first, right, start __repr__ = recursive_repr()(generate_repr(__init__)) @property def start(self) -> Point: return self._start def divide(self, point: Point) -> 'LeftBinaryEvent': tail = self.right.left = LeftBinaryEvent(point, self.right, self.from_first) self.right = RightBinaryEvent(point, self) return tail
class RightEvent(Event): is_left = False __slots__ = 'left', '_original_start', '_start' def __init__(self, start: Point, left: LeftEvent, original_start: Point) -> None: self.left, self._original_start, self._start = (left, original_start, start) __repr__ = recursive_repr()(generate_repr(__init__)) @property def end(self) -> Point: return self.left.start @property def from_goal(self) -> bool: return self.left.from_goal @property def from_test(self) -> bool: return self.left.from_test @property def original_end(self) -> Point: return self.left.original_start @property def original_start(self) -> Point: return self._original_start @property def start(self) -> Point: return self._start
class ReprHelperMixin(object): """Mixin to provide :code:`__repr__` and :code:`_repr_pretty_` for :py:mod:`IPython.lib.pretty` from user defined :code:`_repr_helper_` function. For full API, see :py:class:`represent.helper.BaseReprHelper`. .. code-block:: python def _repr_helper_(self, r): r.positional_from_attr('attrname') r.positional_with_value(value) r.keyword_from_attr('attrname') r.keyword_from_attr('keyword', 'attrname') r.keyword_with_value('keyword', value) .. versionadded:: 1.3 """ __slots__ = () def __repr__(self): r = ReprHelper(self) self._repr_helper_(r) return str(r) if recursive_repr is not None: __repr__ = recursive_repr()(__repr__) def _repr_pretty_(self, p, cycle): with PrettyReprHelper(self, p, cycle) as r: self._repr_helper_(r)
class LeftNaryEvent(LeftEvent): @classmethod def from_segment_endpoints( cls, segment_endpoints: SegmentEndpoints) -> 'LeftNaryEvent': start, end = segment_endpoints if start > end: start, end = end, start result = cls(start, None) result.right = RightNaryEvent(end, result) return result __slots__ = '_start', def __init__(self, start: Point, right: Optional['RightNaryEvent']) -> None: self.right, self._start = right, start __repr__ = recursive_repr()(generate_repr(__init__)) @property def start(self) -> Point: return self._start def divide(self, break_point: Point) -> 'LeftNaryEvent': tail = self.right.left = LeftNaryEvent(break_point, self.right) self.right = RightNaryEvent(break_point, self) return tail
class ShapedEvent(BinaryEvent): __slots__ = ('interior_to_left', 'other_interior_to_left', 'overlap_kind', 'in_result', 'position') def __init__(self, is_right_endpoint: bool, start: Point, complement: Optional['ShapedEvent'], from_left: bool, interior_to_left: bool, other_interior_to_left: bool = False, overlap_kind: OverlapKind = OverlapKind.NONE, in_result: bool = False, position: int = 0) -> None: super().__init__(is_right_endpoint, start, complement, from_left) self.interior_to_left = interior_to_left self.other_interior_to_left = other_interior_to_left self.overlap_kind = overlap_kind self.in_result = in_result self.position = position __repr__ = recursive_repr()(generate_repr(__init__)) @property def inside(self) -> bool: """ Checks if the segment enclosed by or lies within the region of the intersection. """ return (self.other_interior_to_left and self.overlap_kind is OverlapKind.NONE) @property def is_common_polyline_component(self) -> bool: """ Checks if the segment is a component of intersection's polyline. """ return self.overlap_kind is OverlapKind.DIFFERENT_ORIENTATION @property def is_common_region_boundary(self) -> bool: """ Checks if the segment is a boundary of intersection's region. """ return self.overlap_kind is OverlapKind.SAME_ORIENTATION @property def is_overlap(self) -> bool: """ Checks if the segment lies on the boundary of both operands. """ return self.overlap_kind is not OverlapKind.NONE @property def outside(self) -> bool: """ Checks if the segment touches or disjoint with the intersection. """ return (not self.other_interior_to_left and self.overlap_kind is OverlapKind.NONE)
class Event: __slots__ = ('is_left_endpoint', 'start', 'complement', 'from_left', 'is_overlap', 'interior_to_left', 'other_interior_to_left', 'edge') def __init__(self, is_left_endpoint: bool, start: Point, complement: Optional['Event'], from_left_contour: bool, interior_to_left: bool, edge: Optional[QuadEdge] = None) -> None: self.is_left_endpoint = is_left_endpoint self.start = start self.complement = complement self.from_left = from_left_contour self.is_overlap = False self.interior_to_left = interior_to_left self.other_interior_to_left = False self.edge = edge __repr__ = recursive_repr()(generate_repr(__init__)) @property def end(self) -> Point: """ Returns end of the event's segment. >>> event = Event(True, (0, 0), None, False, False) >>> event.complement = Event(False, (1, 0), event, False, False) >>> event.end == (1, 0) True """ return self.complement.start @property def inside(self) -> bool: """ Checks if the segment enclosed by or lies within the region of the intersection. >>> event = Event(True, (0, 0), None, False, False) >>> event.complement = Event(False, (1, 0), event, False, False) >>> event.inside False """ return self.other_interior_to_left and not self.is_overlap @property def segment(self) -> Segment: """ Returns segment of the event. >>> event = Event(True, (0, 0), None, False, False) >>> event.complement = Event(False, (1, 0), event, False, False) >>> event.segment == ((0, 0), (1, 0)) True """ return self.start, self.end
class RightNaryEvent(RightEvent): __slots__ = '_start', def __init__(self, start: Point, left: LeftNaryEvent) -> None: self.left, self._start = left, start __repr__ = recursive_repr()(generate_repr(__init__)) @property def start(self) -> Point: return self._start
class LeftMixedEvent(LeftEvent): @classmethod def from_endpoints(cls, segment_endpoints: SegmentEndpoints, from_first: bool) -> 'LeftMixedEvent': start, end = segment_endpoints inside_on_left = True if start > end: start, end = end, start inside_on_left = False result = cls(start, None, from_first, inside_on_left) result.right = RightMixedEvent(end, result) return result __slots__ = ('from_first', 'from_result', 'interior_to_left', 'is_overlap', 'other_interior_to_left', '_start') def __init__(self, start: Point, right: Optional['RightMixedEvent'], from_first: bool, interior_to_left: bool, other_interior_to_left: bool = False, is_overlap: bool = False, from_result: bool = False) -> None: self.right, self._start = right, start self.from_first = from_first self.interior_to_left, self.other_interior_to_left = ( interior_to_left, other_interior_to_left) self.is_overlap = is_overlap self.from_result = from_result __repr__ = recursive_repr()(generate_repr(__init__)) @property def outside(self) -> bool: """ Checks if the segment touches or disjoint with the intersection. """ return not self.other_interior_to_left and not self.is_overlap @property def primary(self) -> 'LeftMixedEvent': return self @property def start(self) -> Point: return self._start def divide(self, point: Point) -> 'LeftMixedEvent': tail = self.right.left = LeftMixedEvent(point, self.right, self.from_first, self.interior_to_left) self.right = RightMixedEvent(point, self) return tail
class LinearLeftEvent(LeftEvent): @classmethod def from_endpoints(cls, endpoints, from_test: bool) -> 'LinearLeftEvent': start, end = endpoints if start > end: start, end = end, start result = cls(start, None, start, from_test, SegmentsRelation.DISJOINT) result.right = RightEvent(end, result, end) return result __slots__ = ('right', 'relation', '_from_test', '_original_start', '_start') def __init__(self, start: Point, right: Optional[RightEvent], original_start: Point, from_test: bool, relation: SegmentsRelation) -> None: self.right, self._original_start, self._start = (right, original_start, start) self._from_test = from_test self.relation = relation __repr__ = recursive_repr()(generate_repr(__init__)) @property def end(self) -> Point: return self.right.start @property def from_goal(self) -> bool: return not self.from_test @property def from_test(self) -> bool: return self._from_test @property def original_end(self) -> Point: return self.right.original_start @property def original_start(self) -> Point: return self._original_start @property def start(self) -> Point: return self._start def divide(self, break_point: Point) -> 'LinearLeftEvent': tail = self.right.left = LinearLeftEvent(break_point, self.right, self.original_start, self.from_test, self.relation) self.right = RightEvent(break_point, self, self.original_end) return tail
class Event: __slots__ = ('is_left_endpoint', 'relationship', 'start', 'complement', 'segments_ids') def __init__(self, is_left_endpoint: bool, relationship: SegmentsRelationship, start: Point, complement: Optional['Event'], segments_ids: Sequence[int]) -> None: self.is_left_endpoint = is_left_endpoint self.relationship = relationship self.start = start self.complement = complement self.segments_ids = segments_ids __repr__ = recursive_repr()(generate_repr(__init__)) @property def is_vertical(self) -> bool: start_x, _ = self.start end_x, _ = self.end return start_x == end_x @property def is_horizontal(self) -> bool: _, start_y = self.start _, end_y = self.end return start_y == end_y @property def end(self) -> Point: return self.complement.start @property def segment(self) -> Segment: return self.start, self.end def set_both_relationships(self, relationship: SegmentsRelationship ) -> None: self.relationship = self.complement.relationship = relationship def y_at(self, x: Coordinate) -> Coordinate: if self.is_vertical or self.is_horizontal: _, start_y = self.start return start_y else: _, start_y = self.start _, end_y = self.end _, result = segments_intersection(self.segment, ((x, start_y), (x, end_y))) return result
class NaryEvent: __slots__ = 'is_right_endpoint', 'start', 'complement' def __init__(self, is_right_endpoint: bool, start: Point, complement: Optional['Event']) -> None: self.is_right_endpoint = is_right_endpoint self.start = start self.complement = complement __repr__ = recursive_repr()(generate_repr(__init__)) @property def end(self) -> Point: return self.complement.start
class RightMixedEvent(RightEvent): __slots__ = '_start', def __init__(self, start: Point, left: LeftMixedEvent) -> None: self.left, self._start = left, start __repr__ = recursive_repr()(generate_repr(__init__)) @property def from_first(self) -> bool: return self.left.from_first @property def primary(self) -> LeftMixedEvent: return self.left @property def start(self) -> Point: return self._start
class RightEvent(Event): @property def end(self) -> Point: return self.left.start @property def original_end(self) -> Point: return self.left.original_start @property def original_start(self) -> Point: return self._original_start @property def segments_ids(self) -> Set[int]: return self.left.segments_ids @property def start(self) -> Point: return self._start @property def tangents(self) -> Sequence[Event]: return self._tangents __slots__ = 'left', '_original_start', '_start', '_tangents' def __init__(self, start: Point, left: Optional[LeftEvent], original_start: Point) -> None: self.left, self._original_start, self._start = (left, original_start, start) self._tangents = [] # type: List[Event] __repr__ = recursive_repr()(generate_repr(__init__)) def register_tangent(self, tangent: 'Event') -> None: assert self.start == tangent.start self._tangents.append(tangent)
class BinaryEvent: __slots__ = 'is_right_endpoint', 'start', 'complement', 'from_left' def __init__(self, is_right_endpoint: bool, start: Point, complement: Optional['Event'], from_left: bool) -> None: self.is_right_endpoint = is_right_endpoint self.start = start self.complement = complement self.from_left = from_left __repr__ = recursive_repr()(generate_repr(__init__)) @property def end(self) -> Point: return self.complement.start @property def is_vertical(self) -> bool: return self.start.x == self.end.x @property def primary(self) -> Optional['BinaryEvent']: return self.complement if self.is_right_endpoint else self
class Event: __slots__ = ('is_left_endpoint', 'relation', 'start', 'complement', 'segments_ids') def __init__(self, is_left_endpoint: bool, relation: Relation, start: Point, complement: Optional['Event'], segments_ids: Sequence[int]) -> None: self.is_left_endpoint = is_left_endpoint self.relation = relation self.start = start self.complement = complement self.segments_ids = segments_ids __repr__ = recursive_repr()(generate_repr(__init__)) @property def end(self) -> Point: return self.complement.start def set_both_relations(self, relation: Relation) -> None: self.relation = self.complement.relation = relation
def update_event(self, inp=-1): self.set_output_val(0, reprlib.recursive_repr(self.input(0)))
class BaseSchemaField(_Serializable): """The base JSON Schema Field.""" __serde_flags__ = SerdeFlags(omit=(None, NotImplemented)) type: ClassVar[SchemaType] = NotImplemented format: Optional[str] = None enum: Optional[Tuple[Any, ...]] = None title: Optional[str] = None description: Optional[str] = None default: Optional[Any] = None examples: Optional[List[Any]] = None readOnly: Optional[bool] = None writeOnly: Optional[bool] = None extensions: Optional[Tuple[frozendict.FrozenDict[str, Any], ...]] = None __repr = cached_property(reprlib.recursive_repr()(filtered_repr)) def __repr__(self) -> str: # pragma: nocover return self.__repr @cached_property def __str(self) -> str: # pragma: nocover fields = ([f"type={self.type.value!r}"] if isinstance( self.type, SchemaType) else []) for f in dataclasses.fields(self): val = getattr(self, f.name) if (val or val in {False, 0}) and f.repr: fields.append(f"{f.name}={val!r}") return f"({', '.join(fields)})" def __str__(self) -> str: # pragma: nocover return self.__str @cached_property def validator(self) -> Callable: # pragma: nocover """The JSON Schema validator. Notes ----- If `fastjsonschema` is not installed, this will raise a ValueError. See Also -------- `fastjsonschema <https://horejsek.github.io/python-fastjsonschema/>`_ """ if fastjsonschema: return fastjsonschema.compile(self.primitive()) raise RuntimeError( "Can't compile validator, 'fastjsonschema' is not installed.") def validate(self, obj) -> Any: # pragma: nocover """Validate an object against the defined JSON Schema.""" try: return self.validator(obj) except ( fastjsonschema.JsonSchemaException, fastjsonschema.JsonSchemaDefinitionException, ): raise ValueError( f"<{obj!r}> violates schema: {str(self)}") from None def copy(self): # pragma: nocover """Return a new copy of this schema field.""" return copy.deepcopy(self)
def __new__(mcs, name, bases, dict_, **kwargs): """Create a new data class.""" # delete what may become stale references so that Python creates new ones dict_.pop('__dict__', None) dict_ = {f: v for f, v in dict_.items() if type(v).__name__ != 'member_descriptor'} # collect functions, annotations, defaults, slots and options from this class' ancestors, in definition order all_annotations = {} all_defaults = {} all_slots = set() options = dict(mcs.DEFAULT_OPTIONS) # record all functions defined by the user up through the inheritance chain all_attrs = {a for b in bases for a in dir(b) if is_user_func(getattr(b, a, None))} | dict_.keys() dataclass_bases = [vars(b) for b in bases if hasattr(b, '__dataclass__')] for b in dataclass_bases + [dict_]: all_annotations.update(b.get('__annotations__', {})) all_defaults.update(b.get('__defaults__', {})) all_slots.update(b.get('__slots__', set())) options.update(b.get('__dataclass__', {})) post_init = '__post_init__' in all_attrs # update options and defaults for *this* class options.update(kwargs) all_defaults.update({f: v for f, v in dict_.items() if f in all_annotations}) # store defaults, annotations and decorator options for future subclasses dict_['__defaults__'] = all_defaults dict_['__annotations__'] = all_annotations dict_['__dataclass__'] = options # create and apply generated methods and attributes if options['slots']: # if the slots option is added, add __slots__. Values with default values must only be present in slots, # not dict, otherwise Python will interpret them as read only for d in all_annotations.keys() & dict_.keys(): del dict_[d] dict_['__slots__'] = tuple(all_annotations.keys() - all_slots) elif '__slots__' in dict_: # if the slots option gets removed, remove __slots__ del dict_['__slots__'] if options['init'] and all_annotations and '__init__' not in all_attrs: dict_.setdefault('__init__', generate_init(all_annotations, all_defaults, options, post_init)) if options['repr']: '__repr__' in all_attrs or dict_.setdefault('__repr__', recursive_repr()(__repr__)) if options['eq']: '__eq__' in all_attrs or dict_.setdefault('__eq__', __eq__) if options['iter']: '__iter__' in all_attrs or dict_.setdefault('__iter__', __iter__) if options['frozen']: '__delattr__' in all_attrs or dict_.setdefault('__delattr__', __setattr__) '__setattr__' in all_attrs or dict_.setdefault('__setattr__', __setattr__) if options['order']: '__lt__' in all_attrs or dict_.setdefault('__lt__', __lt__) if (options['eq'] and options['frozen']) or options['unsafe_hash']: '__hash__' in all_attrs or dict_.setdefault('__hash__', generate_hash(all_annotations)) return super().__new__(mcs, name, bases, dict_)
class LeftHoleyEvent(LeftEvent): @classmethod def from_endpoints(cls, segment_endpoints: SegmentEndpoints, from_first: bool) -> 'LeftHoleyEvent': start, end = segment_endpoints inside_on_left = True if start > end: start, end = end, start inside_on_left = False event = cls(start, None, from_first, inside_on_left) event.right = RightShapedEvent(end, event) return event __slots__ = ('below_event_from_shaped_result', 'contour_id', 'from_first', 'from_shaped_result', 'interior_to_left', 'other_interior_to_left', 'overlap_kind', 'position', 'from_in_to_out', '_start') def __init__( self, start: Point, right: Optional['RightShapedEvent'], from_first: bool, interior_to_left: bool, other_interior_to_left: bool = False, overlap_kind: OverlapKind = OverlapKind.NONE, from_shaped_result: bool = False, from_in_to_out: bool = False, position: int = 0, contour_id: Optional[int] = None, below_event_from_shaped_result: Optional['LeftHoleyEvent'] = None ) -> None: self.right, self._start = right, start self.from_first = from_first self.from_shaped_result = from_shaped_result self.interior_to_left = interior_to_left self.other_interior_to_left = other_interior_to_left self.overlap_kind = overlap_kind self.position = position self.from_in_to_out = from_in_to_out self.contour_id = contour_id self.below_event_from_shaped_result = below_event_from_shaped_result __repr__ = recursive_repr()(generate_repr(__init__)) @property def inside(self) -> bool: """ Checks if the segment enclosed by or lies within the region of the intersection. """ return (self.other_interior_to_left and self.overlap_kind is OverlapKind.NONE) @property def is_common_polyline_component(self) -> bool: """ Checks if the segment is a component of intersection's polyline. """ return self.overlap_kind is OverlapKind.DIFFERENT_ORIENTATION @property def is_common_region_boundary(self) -> bool: """ Checks if the segment is a boundary of intersection's region. """ return self.overlap_kind is OverlapKind.SAME_ORIENTATION @property def is_overlap(self) -> bool: """ Checks if the segment lies on the boundary of both operands. """ return self.overlap_kind is not OverlapKind.NONE @property def is_vertical(self) -> bool: return self.start.x == self.end.x @property def primary(self) -> 'LeftHoleyEvent': return self @property def outside(self) -> bool: """ Checks if the segment touches or disjoint with the intersection. """ return (not self.other_interior_to_left and self.overlap_kind is OverlapKind.NONE) @property def start(self) -> Point: return self._start @property def wholly_in_complete_intersection(self) -> bool: """ Checks if the segment wholly is a part of the complete intersection. """ return self.from_shaped_result or self.is_common_polyline_component def divide(self, point: Point) -> 'LeftHoleyEvent': tail = self.right.left = LeftHoleyEvent(point, self.right, self.from_first, self.interior_to_left) self.right = RightShapedEvent(point, self) return tail
class CompoundLeftEvent(LeftEvent): @classmethod def from_endpoints(cls, segment_endpoints: SegmentEndpoints, from_test: bool) -> 'CompoundLeftEvent': start, end = segment_endpoints inside_on_left = True if start > end: start, end = end, start inside_on_left = False result = cls(start, None, start, from_test, SegmentsRelation.DISJOINT, inside_on_left) result.right = RightEvent(end, result, end) return result __slots__ = ('right', 'interior_to_left', 'other_interior_to_left', 'overlap_kind', 'relation', '_from_test', '_original_start', '_start') def __init__(self, start: Point, right: Optional[RightEvent], original_start: Point, from_test: bool, relation: SegmentsRelation, interior_to_left: bool) -> None: self.right, self._original_start, self._start = (right, original_start, start) self._from_test = from_test self.relation = relation self.overlap_kind = OverlapKind.NONE self.interior_to_left = interior_to_left self.other_interior_to_left = False __repr__ = recursive_repr()(generate_repr(__init__)) @property def end(self) -> Point: return self.right.start @property def from_goal(self) -> bool: return not self.from_test @property def from_test(self) -> bool: return self._from_test @property def inside(self) -> bool: """ Checks if the segment enclosed by or lies within the region of the intersection. """ return (self.other_interior_to_left and self.overlap_kind is OverlapKind.NONE) @property def is_common_polyline_component(self) -> bool: """ Checks if the segment is a component of intersection's polyline. """ return self.overlap_kind is OverlapKind.DIFFERENT_ORIENTATION @property def is_common_region_boundary(self) -> bool: """ Checks if the segment is a boundary of intersection's region. """ return self.overlap_kind is OverlapKind.SAME_ORIENTATION @property def original_end(self) -> Point: return self.right.original_start @property def original_start(self) -> Point: return self._original_start @property def outside(self) -> bool: """ Checks if the segment touches or disjoint with the intersection. """ return (not self.other_interior_to_left and self.overlap_kind is OverlapKind.NONE) @property def start(self) -> Point: return self._start def divide(self, break_point: Point) -> 'CompoundLeftEvent': tail = self.right.left = CompoundLeftEvent(break_point, self.right, self.original_start, self.from_test, self.relation, self.interior_to_left) self.right = RightEvent(break_point, self, self.original_end) return tail
class SweepEvent: __slots__ = ('is_left', 'point', 'other_event', 'polygon_type', 'edge_type', 'in_out', 'other_in_out', 'in_result', 'result_in_out', 'position', 'contour_id', 'prev_in_result_event') def __init__(self, is_left: bool, point: Point, other_event: Optional['SweepEvent'], polygon_type: PolygonType, edge_type: EdgeType, in_out: bool = False, other_in_out: bool = False, in_result: bool = False, result_in_out: bool = False, position: int = 0, contour_id: int = 0, prev_in_result_event: Optional['SweepEvent'] = None) -> None: self.is_left = is_left self.point = point self.other_event = other_event self.polygon_type = polygon_type self.edge_type = edge_type self.in_out = in_out self.other_in_out = other_in_out self.in_result = in_result self.result_in_out = result_in_out self.position = position self.contour_id = contour_id self.prev_in_result_event = prev_in_result_event def __getstate__(self) -> SweepEventState: left_links, right_links = {}, {} events = self._traverse(self, left_links, right_links) return ([ (event.is_left, event.point, event.polygon_type, event.edge_type, event.in_out, event.other_in_out, event.in_result, event.result_in_out, event.position, event.contour_id) for event in events ], left_links, right_links) def __setstate__(self, state: SweepEventState) -> None: events_states, left_links, right_links = state (self.is_left, self.point, self.polygon_type, self.edge_type, self.in_out, self.other_in_out, self.in_result, self.result_in_out, self.position, self.contour_id) = events_states[0] self.other_event, self.prev_in_result_event = None, None events = [self] + [ SweepEvent(event_state[0], event_state[1], None, event_state[2], event_state[3], event_state[4], event_state[5], event_state[6], event_state[7], event_state[8], event_state[9], None) for event_state in events_states[1:] ] for source, destination in left_links.items(): events[source].other_event = events[destination] for source, destination in right_links.items(): events[source].prev_in_result_event = events[destination] __repr__ = recursive_repr()(generate_repr(__init__)) def __eq__(self, other: 'SweepEvent') -> bool: if self is other: return True def are_equal(left: SweepEvent, right: SweepEvent) -> bool: left_left_links, left_right_links = {}, {} right_left_links, right_right_links = {}, {} left_events = self._traverse(left, left_left_links, left_right_links) right_events = self._traverse(right, right_left_links, right_right_links) return (left_left_links == right_left_links and left_right_links == right_right_links and len(left_events) == len(right_events) and all(map(are_fields_equal, left_events, right_events))) def are_fields_equal(left: SweepEvent, right: SweepEvent) -> bool: return (left.is_left is right.is_left and left.point == right.point and left.polygon_type is right.polygon_type and left.edge_type is right.edge_type and left.in_out is right.in_out and left.other_in_out is right.other_in_out and left.in_result is right.in_result and left.result_in_out is right.result_in_out and left.position == right.position and left.contour_id == right.contour_id) return (are_equal(self, other) if isinstance(other, SweepEvent) else NotImplemented) _traverse = staticmethod( partial(traverse, to_left=attrgetter('other_event'), to_right=attrgetter('prev_in_result_event'))) @property def is_vertical(self) -> bool: self.validate() return self.point.x == self.other_event.point.x @property def segment(self) -> Segment: self.validate() return Segment(self.point, self.other_event.point) def is_above(self, point: Point) -> bool: return not self.is_below(point) def is_below(self, point: Point) -> bool: self.validate() return (sign(self.point, self.other_event.point, point) == 1 if self.is_left else sign( self.other_event.point, self.point, point) == 1) def validate(self) -> None: if self.other_event is None: raise ValueError('No "other_event" found.')
class Node: __slots__ = ('_key', 'value', 'is_black', '_parent', '_left', '_right', '__weakref__') def __init__(self, key: Key, value: Value, is_black: bool, left: Union[NIL, 'Node'] = NIL, right: Union[NIL, 'Node'] = NIL, parent: Union[NIL, 'Node'] = NIL) -> None: self._key, self.value, self.is_black = key, value, is_black self.left, self.right, self._parent = left, right, parent __repr__ = recursive_repr()(generate_repr(__init__)) State = Tuple[Any, ...] def __getstate__(self) -> State: return (self._key, self.value, self.is_black, self.parent, self._left, self._right) def __setstate__(self, state: State) -> None: (self._key, self.value, self.is_black, self.parent, self._left, self._right) = state @classmethod def from_simple(cls, key: Key, *args: Any) -> 'Node': return cls(key, None, *args) @property def item(self) -> Item: return self._key, self.value @property def key(self) -> Key: return self._key @property def left(self) -> Union[NIL, 'Node']: return self._left @left.setter def left(self, node: Union[NIL, 'Node']) -> None: self._left = node _set_parent(node, self) @property def parent(self) -> Optional['Node']: return dereference_maybe(self._parent) @parent.setter def parent(self, node: Optional['Node']) -> None: self._parent = maybe_weakref(node) @property def right(self) -> Union[NIL, 'Node']: return self._right @right.setter def right(self, node: Union[NIL, 'Node']) -> None: self._right = node _set_parent(node, self)
def autorepr(*args, **kwargs): """Class decorator to construct :code:`__repr__` **automatically** based on the arguments to ``__init__``. :code:`_repr_pretty_` for :py:mod:`IPython.lib.pretty` is also constructed, unless `include_pretty=False`. :param positional: Mark arguments as positional by number, or a list of argument names. :param include_pretty: Add a ``_repr_pretty_`` to the class (defaults to True). Example: .. code-block:: python >>> @autorepr ... class A: ... def __init__(self, a, b): ... self.a = a ... self.b = b >>> print(A(1, 2)) A(a=1, b=2) .. code-block:: python >>> @autorepr(positional=1) ... class B: ... def __init__(self, a, b): ... self.a = a ... self.b = b >>> print(A(1, 2)) A(1, b=2) .. versionadded:: 1.5.0 """ cls = positional = None include_pretty = _DEFAULT_INCLUDE_PRETTY # We allow using @autorepr or @autorepr(positional=..., ...), so check # how we were called. if args and not kwargs: if len(args) != 1: raise TypeError('Class must be only positional argument.') cls, = args if not isinstance(cls, type): raise TypeError( "The sole positional argument must be a class. To use the " "'positional' argument, use a keyword.") elif not args and kwargs: valid_kwargs = {'positional', 'include_pretty'} invalid_kwargs = set(kwargs) - valid_kwargs if invalid_kwargs: error = 'Unexpected keyword arguments: {}'.format(invalid_kwargs) raise TypeError(error) positional = kwargs.get('positional') include_pretty = kwargs.get('include_pretty', include_pretty) elif (args and kwargs) or (not args and not kwargs): raise TypeError( 'Use bare @autorepr or @autorepr(...) with keyword args.') # Define the methods we'll add to the decorated class. def __repr__(self): return self.__class__._represent.fstr.format(self=self) if recursive_repr is not None: __repr__ = recursive_repr()(__repr__) _repr_pretty_ = None if include_pretty: _repr_pretty_ = _make_repr_pretty() if cls is not None: return _autorepr_decorate(cls, repr=__repr__, repr_pretty=_repr_pretty_) else: return partial( _autorepr_decorate, repr=__repr__, repr_pretty=_repr_pretty_, positional=positional, include_pretty=include_pretty)
class LeftEvent(Event): @classmethod def from_segment(cls, segment: Segment, segment_id: int) -> 'LeftEvent': start, end = to_sorted_pair(segment.start, segment.end) result = LeftEvent(start, None, start, {start: {end: {segment_id}}}) result.right = RightEvent(end, result, end) return result is_left = True @property def end(self) -> Point: return self.right.start @property def original_start(self) -> Point: return self._original_start @property def original_end(self) -> Point: return self.right.original_start @property def segments_ids(self) -> Set[int]: return self.parts_ids[self.start][self.end] @property def start(self) -> Point: return self._start @property def tangents(self) -> Sequence[Event]: return self._tangents __slots__ = ('parts_ids', 'right', '_original_start', '_relations_mask', '_start', '_tangents') def __init__(self, start: Point, right: Optional['RightEvent'], original_start: Point, parts_ids: Dict[Point, Dict[Point, Set[int]]]) -> None: self.right, self.parts_ids, self._original_start, self._start = ( right, parts_ids, original_start, start) self._relations_mask = 0 self._tangents = [] # type: List[Event] __repr__ = recursive_repr()(generate_repr(__init__)) def divide(self, break_point: Point) -> 'LeftEvent': """Divides the event at given break point and returns tail.""" segments_ids = self.segments_ids (self.parts_ids.setdefault(self.start, {}).setdefault(break_point, set()).update(segments_ids)) (self.parts_ids.setdefault(break_point, {}).setdefault(self.end, set()).update(segments_ids)) result = self.right.left = LeftEvent(break_point, self.right, self.original_start, self.parts_ids) self.right = RightEvent(break_point, self, self.original_end) return result def has_only_relations(self, *relations: Relation) -> bool: mask = self._relations_mask for relation in relations: mask &= ~(1 << relation) return not mask def merge_with(self, other: 'LeftEvent') -> None: assert self.start == other.start and self.end == other.end full_relation = classify_overlap(other.original_start, other.original_end, self.original_start, self.original_end) self.register_relation(full_relation) other.register_relation(full_relation.complement) start, end = self.start, self.end self.parts_ids[start][end] = other.parts_ids[start][end] = ( self.parts_ids[start][end] | other.parts_ids[start][end]) def register_tangent(self, tangent: Event) -> None: assert self.start == tangent.start self._tangents.append(tangent) def register_relation(self, relation: Relation) -> None: self._relations_mask |= 1 << relation