Beispiel #1
0
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__))
Beispiel #2
0
class MyContainer3:
    def __repr__(self):
        'Test document content'
        pass

    wrapped = __repr__
    wrapper = recursive_repr()(wrapped)
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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)
Beispiel #7
0
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
Beispiel #8
0
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)
Beispiel #9
0
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
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
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
Beispiel #16
0
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)
Beispiel #17
0
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
Beispiel #18
0
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
Beispiel #19
0
 def update_event(self, inp=-1):
     self.set_output_val(0, reprlib.recursive_repr(self.input(0)))
Beispiel #20
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)
Beispiel #21
0
    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_)
Beispiel #22
0
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
Beispiel #23
0
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
Beispiel #24
0
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.')
Beispiel #25
0
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)
Beispiel #26
0
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)
Beispiel #27
0
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