Manoj
Manoj

Reputation: 971

Rotate - TransformOriginPoint - PyQt4

I was trying to build a small UI using PyQt .

It has a window , a button(Rotate) , and a polygon(rectangle) in a QGraphicsView. One aim of the app is to allow the user to rotate the polygon. That is after the button is clicked and the user clicks at a point , the nearest vertex automatically shifts or tilts towards the user click. Ive also set the polygon to be movable before the click and not movable after the click.

The problem is if the user moves the polygon and then clicks , the polygon rotates in a weird manner. Could someone help me figure out the error? My guess is that it might be with the setTransformOriginPoint.

EDIT: I have two classes inherited from QtGui.QWidget and QtGui.QGraphicsScene.

class Window(QtGui.QWidget):
    def polychange(self , sender): //Called by the button , 
        if sender:
                self.view.polyrotate = 1 //self.view is an instance of QGraphicsScene class
                self.view.polyf.setFlag(QtGui.QGraphicsItem.ItemIsMovable , False)

        else:
                self.view.polyrotate = 0 
                self.view.degrees = 0
                self.view.polyf.setFlag(QtGui.QGraphicsItem.ItemIsMovable)

class Example(QtGui.QGraphicsView):
    def mousePressEvent(self , e):
        super(Example , self).mousePressEvent(e)
        self.x = e.x()
        self.y = e.y()
        if self.polyrotate == 1:
            self.Rotate()

    def Rotate(self):

        self.pverticesx = []
        self.pverticesy = []
        distances = []
        for i in range(4):
            self.pverticesx.append(self.polyf.mapToScene(self.polyf.polygon()[i]).x())
            self.pverticesy.append(self.polyf.mapToScene(self.polyf.polygon()[i]).y())

        x1 = self.x
        y1 = self.y      

        for i in range(4):
             distance = math.hypot(self.pverticesx[i] - x1 , self.pverticesy[i] - y1)
             distances.append(distance)
        midpointx = (self.pverticesx[0] +  self.pverticesx[2]) / 2
        midpointy = (self.pverticesy[0] +  self.pverticesy[2]) / 2
        index = distances.index(min(distances))          
        pointx = self.pverticesx[index]                
        pointy = self.pverticesy[index]
        vector1 = [x1 - midpointx , y1 - midpointy]
        vector2 = [pointx - midpointx , pointy - midpointy]
        num = 0

        for i in [0 , 1]:
            num = num + (vector1[i] * vector2[i])  
        den = math.sqrt(sum(map(lambda x : x * x , vector1))) *  math.sqrt(sum(map(lambda x : x * x , vector2)))

        degree = math.degrees(math.acos(num / den))
        self.degrees = degree + self.degrees
        if self.degrees > 360:
            rotation = self.degrees / 360
            self.degrees = self.degrees - (rotation * 360)

        self.polyf.setTransformOriginPoint(midpointx , midpointy)
        self.polyf.setRotation(self.degrees)

Here is a more exhaustive link to my code. RotateApp . Thanks in advance.

Upvotes: 1

Views: 2090

Answers (2)

Manoj
Manoj

Reputation: 971

I've found out the answer to my own question. Before rotating , midpointx and midpointy are in scene coordinates. So I had to map them back to QGraphicsItem coordinates system. This line before self.setRotation() would do the trick.

self.polyf.setTransformOriginPoint(self.polyf.mapFromScene(QtCore.QPointF(midpointx , midpointy)))

Now my polygon doesnt move randomnly.

Upvotes: 2

Max
Max

Reputation: 741

i am not so familiar with PyQt, but when rotating , most API's rotate around the point ( 0,0 ), so the correct behavior is to : 1 - translate the polygon to 0,0 2- rotate the polygon 3- translate the polygon back

hope that this helps,

regards.

Upvotes: 1

Related Questions