Skip to content

Commit d3568d3

Browse files
authored
get_anchor (#147)
* get_anchor * type
1 parent 288e1d7 commit d3568d3

File tree

2 files changed

+91
-3
lines changed

2 files changed

+91
-3
lines changed

pylabrobot/resources/resource.py

+69-3
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,79 @@ def __repr__(self) -> str:
119119
def __hash__(self) -> int:
120120
return hash(repr(self))
121121

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:
123181
""" 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+
125191
assert self.location is not None, "Resource has no location."
126192
if self.parent is None:
127193
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)
129195

130196
def get_size_x(self) -> float:
131197
if self.rotation in {90, 270}:

pylabrobot/resources/resource_tests.py

+22
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ def test_assign_name_taken(self):
6262
other_child = Resource("child", size_x=5, size_y=5, size_z=5)
6363
deck.assign_child_resource(other_child, location=Coordinate(5, 5, 5))
6464

65+
def test_get_anchor(self):
66+
resource = Resource("test", size_x=12, size_y=12, size_z=12)
67+
self.assertEqual(resource.get_anchor(x="left", y="back", z="bottom"), Coordinate(0, 12, 0))
68+
self.assertEqual(resource.get_anchor(x="right", y="front", z="top"), Coordinate(12, 0, 12))
69+
self.assertEqual(resource.get_anchor(x="center", y="center", z="center"), Coordinate(6, 6, 6))
70+
71+
self.assertEqual(resource.get_anchor(x="l", y="b", z="b"), Coordinate(0, 12, 0))
72+
self.assertEqual(resource.get_anchor(x="r", y="f", z="t"), Coordinate(12, 0, 12))
73+
self.assertEqual(resource.get_anchor(x="c", y="c", z="c"), Coordinate(6, 6, 6))
74+
6575
def test_absolute_location(self):
6676
deck = Deck()
6777
parent = Resource("parent", size_x=10, size_y=10, size_z=10)
@@ -72,6 +82,18 @@ def test_absolute_location(self):
7282
self.assertEqual(deck.get_resource("parent").get_absolute_location(), Coordinate(10, 10, 10))
7383
self.assertEqual(deck.get_resource("child").get_absolute_location(), Coordinate(15, 15, 15))
7484

85+
def test_get_absolute_location_with_anchor(self):
86+
deck = Deck()
87+
parent = Resource("parent", size_x=10, size_y=10, size_z=10)
88+
deck.assign_child_resource(parent, location=Coordinate(10, 10, 10))
89+
child = Resource("child", size_x=5, size_y=5, size_z=5)
90+
parent.assign_child_resource(child, location=Coordinate(5, 5, 5))
91+
92+
self.assertEqual(deck.get_resource("parent")\
93+
.get_absolute_location(x="right", y="front", z="top"), Coordinate(20, 10, 20))
94+
self.assertEqual(deck.get_resource("child")\
95+
.get_absolute_location(x="right", y="front", z="top"), Coordinate(20, 15, 20))
96+
7597
def test_unassign_child(self):
7698
deck = Deck()
7799
parent = Resource("parent", size_x=10, size_y=10, size_z=10)

0 commit comments

Comments
 (0)