コード例 #1
0
    def rotateBackPoints(self, xmin, ymin, xmax, ymax, angle):
        center=QPointF((xmin+xmax)/2,(ymin+ymax)/2)

        k0=Shape.rotatePoint(self,center,QPointF(xmin,ymin),-angle)
        k2=Shape.rotatePoint(self,center,QPointF(xmax,ymax),-angle)
        rotatedPoints=[k0,k2]
        points= [(int(point.x()),int(point.y())) for point in rotatedPoints]
        return points
コード例 #2
0
ファイル: canvas.py プロジェクト: walldas/labelImg_last_one
 def boundedMoveVertex(self, pos):
     index, shape = self.hVertex, self.hShape
     if self.shapeOutOfPixmap(shape.points):
         #this is pre fix. For bug when shape reach Picmap edge.
         return
     if shape.shape3D:
         # 3D editing OFF
         return
     rotatedAxis = False
     if shape.deg > 0 and not shape.tetragon:
         rotatedAxis = True
         shape.points = self.getRotatedShape(shape, -shape.deg)
         pos = Shape.rotatePoint(self, shape.centerPoint, pos, -shape.deg)
     point = shape[index]
     if self.outOfPixmap(pos):
         if self.shapeOutOfPixmap(shape.points) == False:
             pos = self.intersectionPoint(point, pos)
     shiftPos = pos - point
     shape.moveVertexBy(index, shiftPos)
     lindex = (index + 1) % 4
     rindex = (index + 3) % 4
     lshift = None
     rshift = None
     if index % 2 == 0:
         #lyginiai index
         if shape.tetragon == True:
             rshift = QPointF(0, 0)
             lshift = QPointF(0, 0)
         elif shape.tetragon == False:
             rshift = QPointF(shiftPos.x(), 0)
             lshift = QPointF(0, shiftPos.y())
     else:
         #nelyginiai index
         if shape.tetragon == True:
             lshift = QPointF(0, 0)
             rshift = QPointF(0, 0)
         elif shape.tetragon == False:
             lshift = QPointF(shiftPos.x(), 0)
             rshift = QPointF(0, shiftPos.y())
     shape.moveVertexBy(rindex, rshift)
     shape.moveVertexBy(lindex, lshift)
     if rotatedAxis:
         shape.points = self.getRotatedShape(shape, shape.deg)
         pos = Shape.rotatePoint(self, shape.centerPoint, pos, shape.deg)
コード例 #3
0
ファイル: canvas.py プロジェクト: juliusHuelsmann/labelImg
    def resizeShape(self, pos, index, shape):
        """
        Resize shape of rectangle, enforcing rectangular form in the original 
        coordinates


        """

        dot = lambda x, y: x.x() * y.x() + x.y() * y.y()
        eucl = lambda a: 1. * a.x()**2 + 1. * a.y()**2
        rot = lambda p, a: Shape.rotatePoint(p, QPointF(0, 0), a)
        rotShapeLine = lambda i, ia, s: rot(
            s.pointsWithoutRotation[ia] - s.pointsWithoutRotation[i], s.
            currentAngle)

        if shape.points[index] != pos:

            # give reasonable names to the vectices that are affected ('left'
            # and 'right' and to the vertex that remains unaffected 'other')
            rindex, lindex, oindex = [(index + o) % 4 for o in [1, 3, 2]]

            # A) compute the offset defining the movement to be applied in this
            #    step at the vertex in question.
            pos = self.getClosestValid(pos)
            offset_rotated = shape.points[index] - pos
            shape.points[index] = pos

            # B) Find new location of affected points (lindex and rindex)
            #    1) w,h = rotate back vector from dragged vertex (=: i) to other
            #       vertex (=: o)
            #    2) cos(w or h), sin(w or h) -> vector from i to lindex (=:l)
            #       or rindex (=: r)
            vec_involved = shape.points[oindex] - shape.points[index]

            size = -rot(vec_involved, -shape.currentAngle)
            w, h = size.x(), size.y()

            vec_il = QPointF(
                cos(shape.currentAngle) * w,
                sin(shape.currentAngle) * w)
            vec_ir = QPointF(-sin(shape.currentAngle) * h,
                             cos(shape.currentAngle) * h)

            # C) Correct locations accordingly
            #    1) compute  position 1, 3
            #    2) compute intersection in rotated space, such that it is
            #       ensured that the resulting values are rounded inside the
            #       coordinates.
            #       Subtract the resulting value directly from i and 1 or 3
            #    3) Use the projection vector to move both the currently
            #       dragged point and the point that is out of bounds to the
            #       last valid location.
            if index % 2 == 0:
                rind = vec_ir
                vec_ir = vec_il
                vec_il = rind
            shape.points[rindex] = shape.points[index] - vec_ir
            shape.points[lindex] = shape.points[index] - vec_il

            # apply the rotation angle to the data that is uk
            shape_center = shape.getCenter(rotated=True)
            shifts = self.checkBorders(shape, index, lindex, vec_ir),  \
                    self.checkBorders(shape, index, rindex, vec_il)
            for shift in shifts:
                if shift is not None:
                    shape.points[index] += shift

            # apply the new coordinates to the latent (unrotated) array
            shape.applyRotationAngle(shape.currentAngle, shape_center, False)
コード例 #4
0
ファイル: canvas.py プロジェクト: walldas/labelImg_last_one
 def getRotatedShape(self, shape, angle):
     return [
         Shape.rotatePoint(self, shape.centerPoint, point, angle)
         for point in shape.points
     ]
コード例 #5
0
ファイル: canvas.py プロジェクト: juliusHuelsmann/labelImg
    def rotateShape(self, pos, shape, debug=True):
        """
        Rotates a shape by dragging the shape-rotation-button to the position 
        `pos`.

        Checks if the resulting shape is completely inside the image in the 
        image. If not, rotate by an angle that is closest to the desired angle
        but still yielding a shape inside the image.
        """

        # Case 1: Rotate the shape
        vertex_not_rotated = shape.getShapeRotationVertex(False)
        if vertex_not_rotated is not None:
            eucl_sq = lambda a: a.x()**2 + a.y()**2

            # Fetch the original (=not rotated) vertex-position for movement
            # and the center of mass of the shape (once again according to
            # the coordinates that are not rotated)
            vertex_point = vertex_not_rotated[0]
            vertex_mirrored = vertex_not_rotated[2]
            shape_center = shape.getCenter(False)

            # Compute the vector and distance between both aforementioned points
            vec_old_center = vertex_point - shape_center  # - vertex_point
            dist_old_center_square = eucl_sq(vec_old_center)

            # Compute the vector and distance between the new position and the center
            vec_new_center = pos - shape_center  # - pos
            dist_new_center_square = eucl_sq(vec_new_center)

            # Now compute the angle between both the vector pointing to the new
            # position of the rotation vertex and the one pointing to its
            # original position.
            # Make completely sure that no rounding errors can cause
            # mathematical errors for the input value by checking bounds.
            val = QPointF.dotProduct(vec_new_center, vec_old_center) / \
                (dist_new_center_square * dist_old_center_square) **.5
            val = min(max(val, -1), 1)
            angle = acos(val)

            # The direction of movement has to be adapted depending on the
            # current state of the vertex.
            # First condition:  vertex is 'mirrored':
            #                   the initially topmost line is dragged under line
            #                   at the bottom; In this case the sign must be
            #                   swapped.
            # Second condition: as the shape-move vertex is always
            #                   directly above or beneath the shape's center
            #                   it is succicent to check the x coordinate for
            #                   checking if the rotation is 'in the second
            #                   half'. In that case, rotate by 2pi -angle
            transform_angle = lambda a, posx :  \
                    (-1 if vertex_mirrored else 1)  \
                    * (a if (posx >= vertex_point.x()) else 2. * pi - a)
            angle = transform_angle(angle, pos.x())

            # XXX: this checking mechanism does not work entirely (the
            #      distinction of valid angles sometimes does not recognize the
            #      fact that two edges are outside the valid area).
            #      and contains debug code (that inserts vertices to some
            #      positions for debugging) and thus should only be commented
            #      in for finishing the implementation of that feature (in case
            #      it is required)).
            #      If it is not required it should be removed.
            performCheckOfIntervals = False
            if performCheckOfIntervals:
                # Not all angles are valid. Find out which angles are leading to
                # coordiantes outside the image:
                # Step 1)       find (x,y) with \|(x,y) - c \| = \|x_1 - x_3\|
                #               and (x,y) on image's borders
                # Step 2)       find the associated rotation angles and store them
                #               in a sorted way
                width, height = self.pixmap.width(), self.pixmap.height()
                # get the radius of the circle
                p_c = shape.pointsWithoutRotation[0] - shape_center
                len_p_c = eucl_sq(p_c)
                # list all the support vectors indicating image border alongside
                # with their directions
                support_direction = [
                    [QPointF(0, 0), QPointF(width - 1, 0)],
                    [QPointF(0, 0), QPointF(0, height - 1)],
                    [QPointF(width - 1, 0),
                     QPointF(0, height - 1)],
                    [QPointF(0, height - 1),
                     QPointF(width - 1, 0)]
                ]
                forbiddenAngleIntervals = []
                for s, d in support_direction:
                    # find intersections between the circle (defined by the center
                    # and its radius) and the currently considered image border.
                    #
                    # In case there is only one (or none) intersection,
                    # no conditions are imposed in this step on the anlge as the
                    # image borders are selected to be the last line of pixels
                    # inside the image.
                    #
                    # If there are two intersections, the space in between them is
                    # forbidden
                    intersects = Canvas.intersectionLineCircle(
                        s - shape_center, d, sqrt(len_p_c))
                    if intersects is not None:

                        # In case debugging is enabled, add new shapes that show
                        # the intersections with the borders in the image.
                        # Attention: debugging cannot be used in a productive mode.
                        # Results in a bunch of new vertices.
                        if debug:
                            deb = Shape()
                            deb.addPoint(intersects[0] + shape_center)
                            deb.addPoint(intersects[1] + shape_center)
                            deb.close()
                            self.shapes.append(deb)

                            deb = Shape()
                            deb.addPoint(p_c + shape_center)
                            deb.close()
                            self.shapes.append(deb)

                        # the corresponding angle is the angle between the
                        # intersection point and the  vertex_point (shifted by
                        # center)
                        if len(intersects) == 2:

                            angles = [[
                                transform_angle(
                                    acos(
                                        QPointF.dotProduct(
                                            spwr - shape_center, a) /
                                        (len_p_c * eucl_sq(a))**.5), spwr.x())
                                for a in intersects
                            ] for spwr in shape.pointsWithoutRotation]

                            for i, (a, b) in enumerate(angles):
                                # find the min and max value and compute the
                                # min and max value that are still allowed.
                                # if the angle might be affected by them
                                t = 0
                                if a < 0: a += 2 * pi
                                if b < 0: b += 2 * pi
                                mx, mi = max(a, b), min(a, b)
                                if mx - mi > pi:
                                    forbiddenAngleIntervals.append(
                                        [mx, 2 * pi])
                                    forbiddenAngleIntervals.append([0, mi])
                                else:
                                    forbiddenAngleIntervals.append([mi, mx])

                                #if a < b:
                                #    forbiddenAngleIntervals.append([a, b])
                                #elif b < a:
                                #    forbiddenAngleIntervals.append([a, 2*pi])
                                #    forbiddenAngleIntervals.append([0, b])

                                # paint vector (forbidden area) based on the
                                # computed angle
                                if debug:
                                    p1 = Shape.rotatePoint(
                                        shape.pointsWithoutRotation[i],
                                        shape_center, a)
                                    p2 = Shape.rotatePoint(
                                        shape.pointsWithoutRotation[i],
                                        shape_center, b)

                                    deb = Shape()
                                    deb.addPoint(p1)
                                    deb.addPoint(p2)
                                    deb.close()
                                    self.shapes.append(deb)

                # XXX: There most likely is a better solution to this.
                #      The code below is supposed to unite all forbidden intervals.
                #      This is necessary for being able to pick the closest point
                #      to the forbidden area.
                if len(forbiddenAngleIntervals):
                    unionInterval = [forbiddenAngleIntervals[0]]
                    uiid = 0
                    # starts before other.end and stops after other.start
                    checkIntersect = lambda a, b: a[1] >= b[0] and a[0] <= b[1]
                    checkIntersectMutual = lambda a, b: checkIntersect(a, b) \
                            or checkIntersect(b, a)
                    # need to check multiple times as there might be an array that
                    # unites two other arrays.
                    for k in range(len(forbiddenAngleIntervals) - 1):
                        for i in range(1, len(forbiddenAngleIntervals)):
                            # check if there is already is an interval comprising me
                            inters = False
                            for ui in range(len(unionInterval)):
                                # end union > start this
                                if (checkIntersectMutual(
                                        unionInterval[ui],
                                        forbiddenAngleIntervals[i])):
                                    unionInterval[ui][0] = min(
                                        unionInterval[ui][0],
                                        forbiddenAngleIntervals[i][0])
                                    unionInterval[ui][1] = max(
                                        unionInterval[ui][1],
                                        forbiddenAngleIntervals[i][1])
                                    inters = True
                                    break
                            if not inters:
                                unionInterval.append(
                                    forbiddenAngleIntervals[i])

                    print(forbiddenAngleIntervals, unionInterval)

                    # Check if there is some intersection and use the closest point
                    # as corrected angle.
                    if angle < 0: angle += 2 * pi
                    for i in unionInterval:
                        if i[0] < angle and angle < i[1]:
                            angle = i[0] if angle - i[0] < i[1] - angle else i[
                                1]
                            break

            # Apply the rotation for the shape (computes new location of rotated
            # values and stores the current angle for future reference):
            shape.applyRotationAngle(angle, shape_center)