@@ -119,13 +119,79 @@ def __repr__(self) -> str:
119
119
def __hash__ (self ) -> int :
120
120
return hash (repr (self ))
121
121
122
- def get_absolute_location (self ) -> Coordinate :
122
+ def get_anchor (self , x : str , y : str , z : str ) -> Coordinate :
123
+ """ Get a relative location within the resource.
124
+
125
+ Args:
126
+ x: `"l"`/`"left"`, `"c"`/`"center"`, or `"r"`/`"right"`
127
+ y: `"b"`/`"back"`, `"c"`/`"center"`, or `"f"`/`"front"`
128
+ z: `"t"`/`"top"`, `"c"`/`"center"`, or `"b"`/`"bottom"`
129
+
130
+ Returns:
131
+ A relative location within the resource, the anchor point wrt the left front bottom corner.
132
+
133
+ Examples:
134
+ >>> r = Resource("resource", size_x=12, size_y=12, size_z=12)
135
+ >>> r.get_anchor("l", "b", "t")
136
+
137
+ Coordinate(x=0.0, y=12.0, z=12.0)
138
+
139
+ >>> r.get_anchor("c", "c", "c")
140
+
141
+ Coordinate(x=6.0, y=6.0, z=6.0)
142
+
143
+ >>> r.get_anchor("r", "f", "b")
144
+
145
+ Coordinate(x=12.0, y=0.0, z=0.0)
146
+ """
147
+
148
+ x_ : float
149
+ if x .lower () in {"l" , "left" }:
150
+ x_ = 0
151
+ elif x .lower () in {"c" , "center" }:
152
+ x_ = self .get_size_x () / 2
153
+ elif x .lower () in {"r" , "right" }:
154
+ x_ = self .get_size_x ()
155
+ else :
156
+ raise ValueError (f"Invalid x value: { x } " )
157
+
158
+ y_ : float
159
+ if y .lower () in {"b" , "back" }:
160
+ y_ = self .get_size_y ()
161
+ elif y .lower () in {"c" , "center" }:
162
+ y_ = self .get_size_y () / 2
163
+ elif y .lower () in {"f" , "front" }:
164
+ y_ = 0
165
+ else :
166
+ raise ValueError (f"Invalid y value: { y } " )
167
+
168
+ z_ : float
169
+ if z .lower () in {"t" , "top" }:
170
+ z_ = self .get_size_z ()
171
+ elif z .lower () in {"c" , "center" }:
172
+ z_ = self .get_size_z () / 2
173
+ elif z .lower () in {"b" , "bottom" }:
174
+ z_ = 0
175
+ else :
176
+ raise ValueError (f"Invalid z value: { z } " )
177
+
178
+ return Coordinate (x_ , y_ , z_ )
179
+
180
+ def get_absolute_location (self , x : str = "l" , y : str = "f" , z : str = "b" ) -> Coordinate :
123
181
""" Get the absolute location of this resource, probably within the
124
- :class:`pylabrobot.resources.Deck`. """
182
+ :class:`pylabrobot.resources.Deck`. The `x`, `y`, and `z` arguments specify the anchor point
183
+ within the resource. The default is the left front bottom corner.
184
+
185
+ Args:
186
+ x: `"l"`/`"left"`, `"c"`/`"center"`, or `"r"`/`"right"`
187
+ y: `"b"`/`"back"`, `"c"`/`"center"`, or `"f"`/`"front"`
188
+ z: `"t"`/`"top"`, `"c"`/`"center"`, or `"b"`/`"bottom"`
189
+ """
190
+
125
191
assert self .location is not None , "Resource has no location."
126
192
if self .parent is None :
127
193
return self .location
128
- return self .parent .get_absolute_location () + self .location
194
+ return self .parent .get_absolute_location () + self .location + self . get_anchor ( x = x , y = y , z = z )
129
195
130
196
def get_size_x (self ) -> float :
131
197
if self .rotation in {90 , 270 }:
0 commit comments