File: arrow.py

package info (click to toggle)
python-mcstasscript 0.0.46%2Bgit20250402111921.bfa5a26-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,440 kB
  • sloc: python: 13,421; makefile: 14
file content (191 lines) | stat: -rw-r--r-- 6,976 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
class Arrow:
    """
    Helper class for creating arrows with connections
    """
    def __init__(self, origin, target, lane=None, kind=None, description=None):
        """
        Arrow object with origin Component_box and target component_box
        """
        self.origin = origin
        self.target = target
        self.kind = kind
        self.description=description

        self.lane = lane
        self.sub_lane = 0
        self.lane_width = None
        self.lane_offset = 0

        self.box_offset_origin = 0
        self.box_offset_target = 0

        self.origin_linestyle = "-"
        self.color = "blue"
        self.alpha = 1.0
        self.arrow_width = 0.003
        self.arrow_length = 0.01
        self.connection = False

        self.origin_congested = False
        self.target_congested = False

    def set_lane(self, lane):
        self.lane = lane

    def set_sub_lane(self, lane):
        self.sub_lane = lane

    def set_lane_width(self, lane_width):
        self.lane_width = lane_width

    def set_lane_offset(self, offset):
        self.lane_offset = offset

    def get_lane_value(self):
        return self.lane_width * (self.lane + self.sub_lane * self.lane_offset)

    def set_connection(self, value):
        self.connection = value

    def set_origin_congested(self, value):
        self.origin_congested = value

    def set_target_congested(self, value):
        self.target_congested = value

    def set_box_offset_origin(self, value):
        """
        In units of box height
        """
        self.box_offset_origin = value

    def get_box_offset_origin(self):
        return self.origin.box_height * self.box_offset_origin

    def set_box_offset_target(self, value):
        """
        In units of box height
        """
        self.box_offset_target = value

    def get_box_offset_target(self):
        return self.target.box_height * self.box_offset_target

    def set_arrow_width(self, value):
        self.arrow_width = value

    def set_arrow_length(self, value):
        self.arrow_length = value

    def set_linestyle(self, value):
        self.origin_linestyle = value

    def set_alpha(self, value):
        self.alpha = value

    def plot_left_side(self, ax):
        # stop a bit before the lane and make a little triangle
        triangle_leg_x = 0.25 * self.arrow_length
        triangle_leg_y = 2.0 * self.arrow_width

        # box to lane
        origin_x = self.origin.get_text_start()
        origin_y = self.origin.position_y + self.get_box_offset_origin()

        origin_lane_x = origin_x - self.get_lane_value()
        origin_lane_y = origin_y

        entry_point_x = origin_lane_x + triangle_leg_x

        x_points = [origin_x, entry_point_x]
        y_points = [origin_y, origin_lane_y]

        # lane
        target_x = self.target.get_text_start()
        target_y = self.target.position_y + self.get_box_offset_target()

        target_lane_x = target_x - self.get_lane_value()
        target_lane_y = target_y

        exit_point_x = target_lane_x + triangle_leg_x

        # Plot lane but ease in and out of the lane with a small triangle
        x_points += [entry_point_x, origin_lane_x, origin_lane_x, target_lane_x, origin_lane_x, exit_point_x]
        y_points += [origin_lane_y, origin_lane_y + triangle_leg_y, origin_lane_y + triangle_leg_y,
                     target_lane_y - triangle_leg_y, target_lane_y - triangle_leg_y, target_lane_y]
        ax.plot(x_points, y_points, color=self.color, linestyle=self.origin_linestyle)

        # lane to box
        arrow_length = self.target.get_text_start() - target_lane_x - triangle_leg_x
        ax.arrow(x=target_lane_x + triangle_leg_x, y=target_lane_y,
                 dx=arrow_length, dy=0,
                 color=self.color, length_includes_head=True,
                 width=self.arrow_width, head_width=5.0*self.arrow_width,
                 head_length=self.arrow_length)

    def plot_right_side(self, ax, text_end):
        # stop a bit before the lane and make a little triangle
        triangle_leg_x = 0.25 * self.arrow_length
        triangle_leg_y = 2.0 * self.arrow_width

        # origin to lane
        origin_x = self.origin.get_text_end()
        origin_y = self.origin.position_y + self.get_box_offset_origin()

        origin_lane_x = text_end + self.get_lane_value()
        origin_lane_y = origin_y

        entry_point_x = origin_lane_x - triangle_leg_x

        x_points = [origin_x, entry_point_x]
        y_points = [origin_y, origin_lane_y]

        """
        ax.plot([origin_x, entry_point_x], [origin_y, origin_lane_y],
                color=self.color, linestyle=self.origin_linestyle, alpha=self.alpha)
        """

        if self.description is not None and not self.origin_congested:
            bbox = dict(boxstyle="round", facecolor="white", edgecolor="white", alpha=0.85)
            ax.text(0.5*(origin_x + origin_lane_x), origin_lane_y,
                    self.description, ha="center", va="center", bbox=bbox)

        # lane
        target_y = self.target.position_y + self.get_box_offset_target()

        target_lane_x = text_end + self.get_lane_value()
        target_lane_y = target_y

        exit_point_x = target_lane_x - triangle_leg_x

        if target_lane_y < origin_lane_y:
            leg_dir = 1
        else:
            leg_dir = -1

        triangle_leg_y_dir = leg_dir * triangle_leg_y

        # Plot lane but ease in and out of it with a small triangle
        x_points += [entry_point_x, target_lane_x, origin_lane_x, target_lane_x, origin_lane_x, exit_point_x]
        y_points += [origin_lane_y, origin_lane_y - triangle_leg_y_dir, origin_lane_y - triangle_leg_y_dir,
                     target_lane_y + triangle_leg_y_dir, target_lane_y + triangle_leg_y_dir, target_lane_y]
        ax.plot(x_points, y_points, color=self.color, alpha=self.alpha, linestyle=self.origin_linestyle)

        # target
        if self.connection:
            mid_point = 0.5*(target_lane_x + self.target.get_text_end())
            ax.plot([target_lane_x - triangle_leg_x, self.target.get_text_end()],
                    [target_lane_y, target_lane_y], color=self.color, alpha=self.alpha)
        else:
            arrow_length = target_lane_x - self.target.get_text_end() - triangle_leg_x
            mid_point = target_lane_x - 0.5*arrow_length
            ax.arrow(x=target_lane_x - triangle_leg_x, y=target_lane_y,
                     dx=-arrow_length, dy=0,
                     color=self.color, length_includes_head=True,
                     width=self.arrow_width, head_width=5.0*self.arrow_width,
                     head_length=self.arrow_length, alpha=self.alpha)

        if self.description is not None and not self.target_congested:
            bbox = dict(boxstyle="round", facecolor="white", edgecolor="white", alpha=0.85)
            ax.text(mid_point, target_lane_y,
                    self.description, ha="center", va="center", bbox=bbox)