Forum Archive

Understanding ui.Transform.rotation

Phuket2

Sorry, I am sure this is just such a stupid question. But I don't get how ui.Transform.rotate works. I put an example below. Naively, I thought that the rotation would just pivot around the center point of the rect. But it clearly does not.
Any help appreciated

import ui

class MyClass(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def draw(self):
        s = ui.Path.rect(100, 100, 200, 200)
        with ui.GState():
            ui.set_color('deeppink')
            s.fill()

        with ui.GState():
            ui.concat_ctm(ui.Transform.rotation(.45))
            ui.set_color('red')
            s.fill()


if __name__ == '__main__':
    w = 600
    h = 800
    f = (0, 0, w, h)
    mc = MyClass(frame = f, bg_color = 'white')
    mc.present('sheet')
Phuket2

Should have attached a pic before 😱
But you can see the rotation is not Center based.

omz

Rotation is around the origin (0, 0) by default. To rotate your drawing around an arbitrary point, you have to combine the rotation with a translation, like this:

import ui

class MyClass(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def draw(self):
        s = ui.Path.rect(100, 100, 200, 200)
        with ui.GState():
            ui.set_color('deeppink')
            s.fill()

        with ui.GState():
            # Move the origin (0, 0) to the center of the rectangle:
            ui.concat_ctm(ui.Transform.translation(200, 200))
            # Rotate the coordinate system:
            ui.concat_ctm(ui.Transform.rotation(.45))
            # Move the origin back, so that the rectangle's coordinates are valid:
            ui.concat_ctm(ui.Transform.translation(-200, -200))
            ui.set_color('red')
            s.fill()

if __name__ == '__main__':
    w = 600
    h = 800
    f = (0, 0, w, h)
    mc = MyClass(frame = f, bg_color = 'white')
    mc.present('sheet')
Phuket2

@omz, thanks a lot.
I did the below, I could not apply a unary operator - to the unpacking. Not sure it's possible or not. Would have been nicer 😱

import ui

class MyClass(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def draw(self):
        rect = ui.Rect(100, 100, 300, 400)
        s = ui.Path.rect(*rect)
        with ui.GState():
            ui.set_color('deeppink')
            s.fill()

        with ui.GState():
            # Move the origin (0, 0) to the center of the rectangle:
            ui.concat_ctm(ui.Transform.translation(*rect.center()))
            #ui.concat_ctm(ui.Transform.translation(200, 200))
            # Rotate the coordinate system:
            ui.concat_ctm(ui.Transform.rotation(.45))
            # Move the origin back, so that the rectangle's coordinates are valid:
            #ui.concat_ctm(ui.Transform.translation(*rect.center()))
            ui.concat_ctm(ui.Transform.translation(-rect.center()[0], -rect.center()[1]))
            ui.set_color('red')
            s.fill()

if __name__ == '__main__':
    w = 600
    h = 800
    f = (0, 0, w, h)
    mc = MyClass(frame = f, bg_color = 'white')
    mc.present('sheet')
omz

@Phuket2 While you cannot use the unary minus operator with points or tuples, this should work, and is a bit more concise: ui.Transform.translation(*(rect.center() * -1))

Phuket2

@omz, thanks. Simple, but you have to understand better than I do how the values are unpacked. In a few more years it will come to me, hopefully 😱