generated from saji/ecp5-template
rework geometry so displaystring position is always topleft screen coord
This commit is contained in:
parent
6b034b0176
commit
261dedc4dc
|
@ -110,17 +110,17 @@ class DisplayRotation(Enum):
|
|||
Generally, prefer LEFTRIGHT/UPDOWN over other rotations.
|
||||
"""
|
||||
|
||||
LEFTRIGHT = 0
|
||||
UPDOWN = 1
|
||||
DOWNUP = 2
|
||||
RIGHTLEFT = 3 # why are you like this.
|
||||
R0 = 0
|
||||
R90 = 1
|
||||
R180 = 2
|
||||
R270 = 3 # why are you like this.
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class DisplayString:
|
||||
"""Internal class to represent a string of HUB75 displays.
|
||||
|
||||
position: (X,Y) coordinates of the local top-left of the display
|
||||
position: (X,Y) screen coordinates of the top-left of the display.
|
||||
|
||||
dimensions: (length, height) local-coordinate dimensions of the display.
|
||||
|
||||
|
@ -129,8 +129,7 @@ class DisplayString:
|
|||
|
||||
position: Coord
|
||||
dimensions: DisplayDimensions
|
||||
rotation: DisplayRotation
|
||||
# TODO: encode muxing
|
||||
rotation: DisplayRotation = DisplayRotation.R0
|
||||
|
||||
@property
|
||||
def bbox(self) -> BBox:
|
||||
|
@ -140,14 +139,10 @@ class DisplayString:
|
|||
l = self.dimensions.length
|
||||
h = self.dimensions.height
|
||||
match self.rotation:
|
||||
case DisplayRotation.LEFTRIGHT:
|
||||
case DisplayRotation.R0 | DisplayRotation.R270:
|
||||
return BBox(Coord(x, y), Coord(x + l, y + h))
|
||||
case DisplayRotation.UPDOWN:
|
||||
return BBox(Coord(x - h, y), Coord(x, y + l))
|
||||
case DisplayRotation.DOWNUP:
|
||||
return BBox(Coord(x, y + l), Coord(x + h, y))
|
||||
case DisplayRotation.RIGHTLEFT:
|
||||
return BBox(Coord(x - l, y - h), Coord(x, y))
|
||||
case DisplayRotation.R90 | DisplayRotation.R180:
|
||||
return BBox(Coord(x, y), Coord(x + h, y + l))
|
||||
|
||||
def contains_pix(self, coord: Coord) -> bool:
|
||||
"""Checks if the given coordinate is inside this display."""
|
||||
|
@ -157,6 +152,38 @@ class DisplayString:
|
|||
"""Checks if the given BBox intersects with this display"""
|
||||
return self.bbox.intersects(box)
|
||||
|
||||
def translate_coord(self, pixnum, addr, mux):
|
||||
"""Helper function to translate string coordinates to screen coordinates"""
|
||||
|
||||
assert mux < self.dimensions.mux, "Mux must be within the mux of the display"
|
||||
|
||||
x = self.position.x
|
||||
y = self.position.y
|
||||
|
||||
addrshift = addr + (self.dimensions.height // self.dimensions.mux) * mux
|
||||
#
|
||||
match self.rotation:
|
||||
case DisplayRotation.R0:
|
||||
# x is linear
|
||||
return {
|
||||
"x": x + pixnum,
|
||||
"y": y + addrshift,
|
||||
}
|
||||
case DisplayRotation.R90:
|
||||
# x is height - addrshift
|
||||
return {
|
||||
"x": x + self.dimensions.height - addrshift - 1,
|
||||
"y": y + pixnum,
|
||||
}
|
||||
case DisplayRotation.R180:
|
||||
pass
|
||||
case DisplayRotation.R270:
|
||||
# x and y are both length - pixnum
|
||||
return {
|
||||
"x": x + self.dimensions.length - 1 - pixnum,
|
||||
"y": y + addrshift,
|
||||
}
|
||||
|
||||
|
||||
class DisplayGeometry:
|
||||
"""Represents a display based on several strings in different positions."""
|
||||
|
@ -185,7 +212,7 @@ class DisplayGeometry:
|
|||
return sum
|
||||
|
||||
def add_string(self, s: DisplayString):
|
||||
"""Add a new string to the display.
|
||||
"""Add a new string to the display.
|
||||
When in strict mode, this method will throw an exception if this new string
|
||||
will overlap with an existing string.
|
||||
"""
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from ..geom import Coord, BBox
|
||||
from ..geom import Coord, BBox, DisplayString, DisplayDimensions, DisplayRotation
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -37,3 +37,21 @@ def test_bbox():
|
|||
BBox(Coord(0, 0), Coord(1, 0))
|
||||
with pytest.raises(RuntimeError):
|
||||
BBox(Coord(1, 1), Coord(0, 0))
|
||||
|
||||
|
||||
ds_testdata = [
|
||||
(DisplayRotation.R0, (0, 0, 0), {"x": 3, "y": 0}),
|
||||
(DisplayRotation.R0, (40, 2, 0), {"x": 43, "y": 2}),
|
||||
(DisplayRotation.R0, (40, 2, 1), {"x": 43, "y": 34}),
|
||||
(DisplayRotation.R90, (40, 0, 0), {"x": 66, "y": 40}),
|
||||
(DisplayRotation.R90, (120, 2, 0), {"x": 64, "y": 120}),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("rot, inp, expected", ds_testdata)
|
||||
def test_displaystring(rot, inp, expected):
|
||||
ds = DisplayString(Coord(3, 0), DisplayDimensions(128, 64), rot)
|
||||
|
||||
res = ds.translate_coord(*inp)
|
||||
|
||||
assert res == expected
|
||||
|
|
Loading…
Reference in a new issue