Пример #1
0
class Point:
    __slots__ = 'x', 'y'

    def __init__(self, x: Coordinate, y: Coordinate) -> None:
        self.x = x
        self.y = y

    __repr__ = generate_repr(__init__)

    def __add__(self, other: 'Point') -> 'Point':
        return Point(self.x + other.x, self.y + other.y)

    def __eq__(self, other: 'Point') -> bool:
        return (self.x == other.x and self.y == other.y if isinstance(
            other, Point) else NotImplemented)

    def __mul__(self, scale: Coordinate) -> 'Point':
        return Point(self.x * scale, self.y * scale)

    def __sub__(self, other: 'Point') -> 'Point':
        return Point(self.x - other.x, self.y - other.y)

    def cross_z(self, other: 'Point') -> Coordinate:
        return self.x * other.y - self.y * other.x

    def is_right_of(self, other: 'Point') -> bool:
        return (self.x, self.y) > (other.x, other.y)
Пример #2
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
Пример #3
0
class Point:
    __slots__ = '_x', '_y'

    def __init__(self, x: Scalar, y: Scalar) -> None:
        self._x = x
        self._y = y

    __repr__ = generate_repr(__init__)

    def __eq__(self, other: 'Point') -> bool:
        return (self._x == other._x and self._y == other._y if isinstance(
            other, Point) else NotImplemented)

    @property
    def bounding_box(self) -> BoundingBox:
        return BoundingBox(self._x, self._y, self._x, self._y)

    @property
    def x(self) -> Scalar:
        return self._x

    @property
    def y(self) -> Scalar:
        return self._y

    def distance_to(self, other: 'Point') -> Scalar:
        return math.sqrt((self._x - other._x)**2 + (self._y - other._y)**2)
Пример #4
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
Пример #5
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
Пример #6
0
class RuneRange:
    __slots__ = '_low', '_high'

    def __new__(cls, low: Rune, high: Optional[Rune] = None) -> 'RuneRange':
        self = super().__new__(cls)
        self._low = low
        self._high = low if high is None else high
        return self

    __repr__ = generate_repr(__new__)

    @property
    def high(self) -> Rune:
        return self._high

    @property
    def low(self) -> Rune:
        return self._low

    def __eq__(self, other: 'RuneRange') -> bool:
        return (self.low == other.low and self.high == other.high
                if isinstance(other, RuneRange) else NotImplemented)

    def __lt__(self, other: 'RuneRange') -> bool:
        return (self.high < other.low
                if isinstance(other, RuneRange) else NotImplemented)
Пример #7
0
class Polygon:
    __slots__ = '_contours',

    def __init__(self, contours: List[Contour]) -> None:
        self._contours = contours

    __repr__ = generate_repr(__init__)

    @property
    def contours(self) -> List[Contour]:
        return self._contours

    def __eq__(self, other: 'Polygon') -> bool:
        return (self._contours == other._contours
                if isinstance(other, Polygon)
                else NotImplemented)

    def __iter__(self) -> Iterator[Contour]:
        return iter(self._contours)

    @property
    def bounding_box(self) -> BoundingBox:
        if self._contours:
            return reduce(add, [contour.bounding_box
                                for contour in self._contours])
        else:
            return BoundingBox(0, 0, 0, 0)

    def join(self, other: 'Polygon') -> None:
        contours_count = len(self._contours)
        self._contours.extend(Contour(contour.points,
                                      [hole + contours_count
                                       for hole in contour.holes],
                                      contour.is_external)
                              for contour in other._contours)
Пример #8
0
class NaryEventsQueueKey:
    __slots__ = 'event', 'orienteer'

    def __init__(self, orienteer: Orienteer, event: NaryEvent) -> None:
        self.orienteer, self.event = orienteer, event

    __repr__ = generate_repr(__init__)

    def __lt__(self, other: 'NaryEventsQueueKey') -> bool:
        event, other_event = self.event, other.event
        start, other_start = event.start, other_event.start
        if start.x != other_start.x:
            # different x-coordinate,
            # the event with lower x-coordinate is processed first
            return start.x < other_start.x
        elif start.y != other_start.y:
            # different points, but same x-coordinate,
            # the event with lower y-coordinate is processed first
            return start.y < other_start.y
        elif event.is_left is not other_event.is_left:
            # same start, but one is a left endpoint
            # and the other a right endpoint,
            # the right endpoint is processed first
            return not event.is_left
        # same start, both events are left endpoints
        # or both are right endpoints
        else:
            # the lowest segment is processed first
            return (self.orienteer(event.start, event.end, other_event.end)
                    is (Orientation.COUNTERCLOCKWISE
                        if event.is_left
                        else Orientation.CLOCKWISE))
Пример #9
0
class SweepLine:
    __slots__ = 'current_x', '_tree'

    def __init__(self, current_x: Optional[Coordinate] = None) -> None:
        self.current_x = current_x
        self._tree = red_black.tree(
            key=cast(Callable[[Event],
                              SweepLineKey], partial(SweepLineKey, self)))

    __repr__ = generate_repr(__init__)

    def __contains__(self, event: Event) -> bool:
        return event in self._tree

    def move_to(self, point: Point) -> None:
        self.current_x, _ = point

    def add(self, event: Event) -> None:
        self._tree.add(event)

    def remove(self, event: Event) -> None:
        self._tree.remove(event)

    def above(self, event: Event) -> Optional[Event]:
        try:
            return self._tree.next(event)
        except ValueError:
            return None

    def below(self, event: Event) -> Optional[Event]:
        try:
            return self._tree.prev(event)
        except ValueError:
            return None
Пример #10
0
class Polygon(abc.Sequence):
    __slots__ = 'linear_rings',

    def __init__(self, linear_rings: List[LinearRing]) -> None:
        self.linear_rings = linear_rings

    __repr__ = generate_repr(__init__)

    def __eq__(self, other: 'Polygon') -> bool:
        return (self.linear_rings == other.linear_rings if isinstance(
            other, Polygon) else NotImplemented)

    def __getitem__(self, index: int) -> LinearRing:
        return self.linear_rings[index]

    def __len__(self) -> int:
        return len(self.linear_rings)

    @classmethod
    def from_ring(cls, ring: Ring, reverse_output: bool) -> 'Polygon':
        return cls([point_node_to_linear_ring(ring.node, reverse_output)])

    def append(self, ring: Ring, reverse_output: bool) -> None:
        self.linear_rings.append(
            point_node_to_linear_ring(ring.node, reverse_output))
Пример #11
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
Пример #12
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)
Пример #13
0
class Factor:
    __slots__ = 'argument', 'degree', '_term'

    def __init__(self, argument: Expression, degree: int) -> None:
        self.argument, self.degree = argument, degree
        term = argument
        for _ in range(degree):
            term = Term(One, term)
        self._term = term

    def express(self) -> Term:
        return self._term

    def square(self) -> Expression:
        return self._term.argument

    def __eq__(self, other: 'Factor') -> bool:
        return self.degree == other.degree and self.argument == other.argument

    def __hash__(self) -> int:
        return hash((self.argument, self.degree))

    def __lt__(self, other: 'Factor') -> bool:
        return ((self.express().degree, self.express().argument) <
                (other.express().degree, other.express().argument))

    __repr__ = generate_repr(__init__)

    def __str__(self) -> str:
        return str(self.express())
Пример #14
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__))
Пример #15
0
class XNode(Node):
    __slots__ = 'point', 'left', 'right'

    def __init__(self, point: Point, left: Node, right: Node) -> None:
        super().__init__()
        self.point = point
        self.left = left
        self.right = right
        self.left._add_parent(self)
        self.right._add_parent(self)

    __repr__ = generate_repr(__init__)

    @property
    def height(self) -> int:
        return max(self.left.height, self.right.height) + 1

    def locate(self, point: Point) -> Location:
        return (self.left.locate(point)
                if point < self.point
                else (self.right.locate(point)
                      if self.point < point
                      else Location.BOUNDARY))

    def search_edge(self, edge: Edge) -> Trapezoid:
        return (self.right
                if self.point <= edge.left
                else self.left).search_edge(edge)

    def _replace_child(self, current: Node, replacement: Node) -> None:
        if self.left is current:
            self.left = replacement
        else:
            self.right = replacement
Пример #16
0
class YNode(Node):
    __slots__ = 'edge', 'above', 'below'

    def __init__(self, edge: Edge, below: Node, above: Node) -> None:
        super().__init__()
        self.edge = edge
        self.below = below
        self.above = above
        self.below._add_parent(self)
        self.above._add_parent(self)

    __repr__ = generate_repr(__init__)

    @property
    def height(self) -> int:
        return max(self.below.height, self.above.height) + 1

    def locate(self, point: Point) -> Location:
        point_orientation = self.edge.orientation_with(point)
        return (self.above.locate(point)
                if point_orientation is Orientation.COUNTERCLOCKWISE else
                (self.below.locate(point) if point_orientation is
                 Orientation.CLOCKWISE else Location.BOUNDARY))

    def search_edge(self, edge: Edge) -> Trapezoid:
        return (self.above
                if self.edge < edge else self.below).search_edge(edge)

    def _replace_child(self, current: Node, replacement: Node) -> None:
        if self.below is current:
            self.below = replacement
        else:
            self.above = replacement
Пример #17
0
class EventsQueue:
    __slots__ = 'context', 'key', '_queue'

    def __init__(self, context: Context) -> None:
        self.context = context
        key = self.key = partial(EventsQueueKey, context.angle_orientation)
        self._queue = PriorityQueue(key=key)

    __repr__ = generate_repr(__init__)

    def __bool__(self) -> bool:
        return bool(self._queue)

    def peek(self) -> Event:
        return self._queue.peek()

    @abstractmethod
    def register(self, segments_endpoints: Iterable[SegmentEndpoints], *,
                 from_test: bool) -> None:
        """
        Registers segments in the events queue.
        """

    @abstractmethod
    def sweep(self, stop_x: Scalar) -> Iterable[LeftEvent]:
        """
        Sweeps plane and emits processed segments' events.
        """

    def _divide_segment(self, event: LeftEvent, break_point: Point) -> None:
        self._queue.push(event.divide(break_point))
        self._queue.push(event.right)
Пример #18
0
def test_basic(method: Method, prefer_keyword: bool,
               with_module_name: bool) -> None:
    result = generate_repr(method,
                           prefer_keyword=prefer_keyword,
                           with_module_name=with_module_name)

    assert callable(result)
Пример #19
0
class Multipolygon(abc.Sequence):
    __slots__ = 'polygons',

    def __init__(self, polygons: List[Polygon]) -> None:
        self.polygons = polygons

    __repr__ = generate_repr(__init__)

    def __eq__(self, other: 'Multipolygon') -> bool:
        return (self.polygons == other.polygons if isinstance(
            other, Multipolygon) else NotImplemented)

    def __getitem__(self, index: int) -> Polygon:
        return self.polygons[index]

    def __len__(self) -> int:
        return len(self.polygons)

    @classmethod
    def from_rings(cls, rings: List[Optional[Ring]],
                   reverse_output: bool) -> 'Multipolygon':
        return cls(list(rings_to_polygons(rings, reverse_output)))

    def extend(self, rings: List[Optional[Ring]],
               reverse_output: bool) -> None:
        self.polygons.extend(rings_to_polygons(rings, reverse_output))
Пример #20
0
class SweepLine:
    __slots__ = '_tree',

    def __init__(self, context: Context) -> None:
        self._tree = red_black.set_(
            key=partial(SweepLineKey, context.angle_orientation))

    __repr__ = generate_repr(__init__)

    def __contains__(self, event: Event) -> bool:
        return event in self._tree

    def add(self, event: Event) -> None:
        self._tree.add(event)

    def remove(self, event: Event) -> None:
        self._tree.remove(event)

    def above(self, event: Event) -> Optional[Event]:
        try:
            return self._tree.next(event)
        except ValueError:
            return None

    def below(self, event: Event) -> Optional[Event]:
        try:
            return self._tree.prev(event)
        except ValueError:
            return None
Пример #21
0
class IntersectNode:
    __slots__ = 'first_bound', 'second_bound', 'point'

    def __init__(self, first_bound: Bound, second_bound: Bound,
                 point: Point) -> None:
        self.first_bound = first_bound
        self.second_bound = second_bound
        self.point = point

    __repr__ = generate_repr(__init__)

    def __eq__(self, other: 'IntersectNode') -> bool:
        return (self.first_bound == other.first_bound
                and self.second_bound == other.second_bound
                and self.point == other.point if isinstance(
                    other, IntersectNode) else NotImplemented)

    def __lt__(self, other: 'IntersectNode') -> bool:
        return (to_int32(self.first_bound.opposite_winding_count +
                         self.second_bound.opposite_winding_count) <
                to_int32(other.first_bound.opposite_winding_count +
                         other.second_bound.opposite_winding_count)
                if are_floats_almost_equal(float(self.point.y),
                                           float(other.point.y)) else
                other.point.y < self.point.y)

    def has_bound(self, bound: Bound) -> bool:
        return self.first_bound is bound or self.second_bound is bound
Пример #22
0
class Node:
    """Represents node of *kd*-tree."""
    __slots__ = ('index', 'is_y_axis', 'left', 'metric', 'point', 'projector',
                 'right')

    def __init__(self,
                 index: int,
                 point: Point,
                 is_y_axis: bool,
                 left: Union['Node', NIL],
                 right: Union['Node', NIL],
                 metric: Callable[[Point, Point], Scalar]) -> None:
        self.index, self.point = index, point
        self.is_y_axis, self.projector = is_y_axis, PROJECTORS[is_y_axis]
        self.left, self.right = left, right
        self.metric = metric

    __repr__ = generate_repr(__init__)

    @property
    def item(self) -> Item:
        return self.index, self.point

    @property
    def projection(self) -> Scalar:
        return self.projector(self.point)

    def distance_to_point(self, point: Point) -> Scalar:
        return self.metric(self.point, point)

    def distance_to_coordinate(self, coordinate: Scalar) -> Scalar:
        return (self.projection - coordinate) ** 2
Пример #23
0
class Edge:
    __slots__ = 'left', 'right'

    def __init__(self, left: Point, right: Point) -> None:
        assert right.is_right_of(left), 'Incorrect endpoints order'
        self.left = left
        self.right = right

    __repr__ = generate_repr(__init__)

    def __eq__(self, other: 'Edge') -> bool:
        return (self.left == other.left and self.right == other.right
                if isinstance(other, Edge) else NotImplemented)

    @property
    def slope(self) -> Coordinate:
        difference = self.right - self.left
        try:
            return difference.y / difference.x
        except ZeroDivisionError:
            return math.copysign(math.inf, difference.x * difference.y)

    def orientation_with(self, point: Point) -> int:
        cross_z = (point - self.left).cross_z(self.right - self.left)
        return (1 if cross_z > 0 else (-1 if cross_z < 0 else 0))
Пример #24
0
class Point:
    __slots__ = '_x', '_y'

    def __init__(self, x: hints.Scalar, y: hints.Scalar) -> None:
        self._x, self._y = x, y

    @property
    def x(self) -> hints.Scalar:
        return self._x

    @property
    def y(self) -> hints.Scalar:
        return self._y

    def __eq__(self, other: 'Point') -> bool:
        return (self.x == other.x and self.y == other.y if isinstance(
            other, Point) else NotImplemented)

    def __hash__(self) -> int:
        return hash((self.x, self.y))

    def __le__(self, other: 'Point') -> bool:
        return (self.x < other.x or self.x == other.x and self.y <= other.y
                if isinstance(other, Point) else NotImplemented)

    def __lt__(self, other: 'Point') -> bool:
        return (self.x < other.x or self.x == other.x and self.y < other.y
                if isinstance(other, Point) else NotImplemented)

    __repr__ = generate_repr(__init__)
Пример #25
0
class Mix:
    __slots__ = '_discrete', '_linear', '_shaped'

    def __init__(self, discrete: hints.Maybe[hints.Multipoint],
                 linear: hints.Maybe[hints.Linear],
                 shaped: hints.Maybe[hints.Shaped]) -> None:
        self._discrete, self._linear, self._shaped = discrete, linear, shaped

    @property
    def discrete(self) -> hints.Maybe[hints.Multipoint]:
        return self._discrete

    @property
    def linear(self) -> hints.Maybe[hints.Linear]:
        return self._linear

    @property
    def shaped(self) -> hints.Maybe[hints.Shaped]:
        return self._shaped

    def __eq__(self, other: 'Mix') -> bool:
        return (self.discrete == other.discrete and self.linear == other.linear
                and self.shaped == other.shaped
                if isinstance(other, Mix) else NotImplemented)

    __repr__ = generate_repr(__init__)
Пример #26
0
class Box:
    __slots__ = '_min_x', '_max_x', '_min_y', '_max_y'

    def __init__(self, min_x: hints.Scalar, max_x: hints.Scalar,
                 min_y: hints.Scalar, max_y: hints.Scalar) -> None:
        self._min_x, self._max_x, self._min_y, self._max_y = (min_x, max_x,
                                                              min_y, max_y)

    @property
    def max_x(self) -> hints.Scalar:
        return self._max_x

    @property
    def max_y(self) -> hints.Scalar:
        return self._max_y

    @property
    def min_x(self) -> hints.Scalar:
        return self._min_x

    @property
    def min_y(self) -> hints.Scalar:
        return self._min_y

    def __eq__(self, other: 'Box') -> bool:
        return (self.min_x == other.min_x and self.max_x == other.max_x
                and self.min_y == other.min_y and self.max_y == other.max_y
                if isinstance(other, Box) else NotImplemented)

    __repr__ = generate_repr(__init__)
Пример #27
0
class EventsQueueKey:
    __slots__ = 'event',

    def __init__(self, event: Event) -> None:
        self.event = event

    __repr__ = generate_repr(__init__)

    def __lt__(self, other: 'EventsQueueKey') -> bool:
        """
        Checks if the event should be processed before the other.
        """
        event, other_event = self.event, other.event
        start_x, start_y = event.start
        other_start_x, other_start_y = other_event.start
        if start_x != other_start_x:
            # different x-coordinate,
            # the event with lower x-coordinate is processed first
            return start_x < other_start_x
        elif start_y != other_start_y:
            # different starts, but same x-coordinate,
            # the event with lower y-coordinate is processed first
            return start_y < other_start_y
        elif event.is_left_endpoint is not other_event.is_left_endpoint:
            # same start, but one is a left endpoint
            # and the other is a right endpoint,
            # the right endpoint is processed first
            return not event.is_left_endpoint
        else:
            # same start,
            # both events are left endpoints or both are right endpoints
            return event.end < other_event.end
Пример #28
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
Пример #29
0
class BeachLineValue:
    def __init__(self,
                 edge: Optional[Edge],
                 circle_event: Optional[CircleEvent] = None) -> None:
        self.edge = edge
        self.circle_event = circle_event

    __repr__ = generate_repr(__init__)
Пример #30
0
class EmptySet(Set[Domain]):
    def __init__(self) -> None:
        pass

    def __bool__(self) -> bool:
        return False

    def __hash__(self) -> int:
        return 0

    __repr__ = generate_repr(__init__)

    def __str__(self) -> str:
        return EMPTY_SET_STRING

    def __and__(self, other: Set) -> Set:
        return self

    def __contains__(self, object_: Domain) -> bool:
        return False

    def __eq__(self, other: Set) -> bool:
        if not isinstance(other, Set):
            return NotImplemented
        return not other

    def __ge__(self, other: Set) -> bool:
        if not isinstance(other, Set):
            return NotImplemented
        return not other

    def __gt__(self, other: Set) -> bool:
        if not isinstance(other, Set):
            return NotImplemented
        return False

    def __le__(self, other: Set) -> bool:
        if not isinstance(other, Set):
            return NotImplemented
        return True

    def __lt__(self, other: Set) -> bool:
        if not isinstance(other, Set):
            return NotImplemented
        return bool(other)

    def __or__(self, other: Set) -> Set:
        if not isinstance(other, Set):
            return NotImplemented
        return other

    def __rsub__(self, other: Set) -> Set:
        return other

    def __sub__(self, other: Set) -> Set:
        return self