File: port.py

package info (click to toggle)
python-gaphas 5.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,560 kB
  • sloc: python: 5,839; makefile: 17; sh: 2
file content (104 lines) | stat: -rw-r--r-- 3,582 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"""Basic connectors such as Ports and Handles."""

from __future__ import annotations

from typing import TYPE_CHECKING

from gaphas.constraint import Constraint, LineConstraint, PositionConstraint
from gaphas.geometry import distance_line_point, distance_point_point
from gaphas.handle import Handle
from gaphas.position import MatrixProjection, Position
from gaphas.solver import MultiConstraint
from gaphas.types import Pos, SupportsFloatPos

if TYPE_CHECKING:
    from gaphas.item import Item


class Port:
    """Port connectable part of an item.

    The Item's handle connects to a port.
    """

    def __init__(self) -> None:
        super().__init__()

        self._connectable = True

    def _set_connectable(self, connectable: bool) -> None:
        self._connectable = connectable

    connectable = property(lambda s: s._connectable, _set_connectable)

    def glue(self, pos: SupportsFloatPos) -> tuple[Pos, float]:
        """Get glue point on the port and distance to the port."""
        raise NotImplementedError("Glue method not implemented")

    def constraint(self, item: Item, handle: Handle, glue_item: Item) -> Constraint:
        """Create connection constraint between item's handle and glue item."""
        raise NotImplementedError("Constraint method not implemented")


class LinePort(Port):
    """Port defined as a line between two handles."""

    def __init__(self, start: Position, end: Position) -> None:
        super().__init__()

        self.start = start
        self.end = end

    def glue(self, pos: SupportsFloatPos) -> tuple[Pos, float]:
        """Get glue point on the port and distance to the port.

        >>> p1, p2 = (0.0, 0.0), (100.0, 100.0)
        >>> port = LinePort(p1, p2)
        >>> port.glue((50, 50))
        ((50.0, 50.0), 0.0)
        >>> port.glue((0, 10))
        ((5.0, 5.0), 7.0710678118654755)
        """
        d, pl = distance_line_point(
            self.start.tuple(), self.end.tuple(), (float(pos[0]), float(pos[1]))
        )
        return pl, d

    def constraint(self, item: Item, handle: Handle, glue_item: Item) -> Constraint:
        """Create connection line constraint between item's handle and the
        port."""
        start = MatrixProjection(self.start, glue_item.matrix_i2c)
        end = MatrixProjection(self.end, glue_item.matrix_i2c)
        point = MatrixProjection(handle.pos, item.matrix_i2c)
        line = LineConstraint((start.pos, end.pos), point.pos)
        return MultiConstraint(start, end, point, line)


class PointPort(Port):
    """Port defined as a point."""

    def __init__(self, point: Position) -> None:
        super().__init__()
        self.point = point

    def glue(self, pos: SupportsFloatPos) -> tuple[Pos, float]:
        """Get glue point on the port and distance to the port.

        >>> h = Handle((10, 10))
        >>> port = PointPort(h.pos)
        >>> port.glue((10, 0))
        (<Position object on (10, 10)>, 10.0)
        """
        point: tuple[float, float] = self.point.pos  # type: ignore[assignment]
        d = distance_point_point(point, (float(pos[0]), float(pos[1])))
        return point, d

    def constraint(
        self, item: Item, handle: Handle, glue_item: Item
    ) -> MultiConstraint:
        """Return connection position constraint between item's handle and the
        port."""
        origin = MatrixProjection(self.point, glue_item.matrix_i2c)
        point = MatrixProjection(handle.pos, item.matrix_i2c)
        c = PositionConstraint(origin.pos, point.pos)
        return MultiConstraint(origin, point, c)