Ejemplo n.º 1
0
    def button_at(self, mouse_pos):
        white_button = QPainterPath()
        white_button.addEllipse(
            QPointF(self.contentsRect().width() - 50,
                    self.contentsRect().height() - 50), 35, 35)
        if white_button.contains(mouse_pos):
            return True, "W"

        black_button = QPainterPath()
        black_button.addEllipse(QPointF(self.contentsRect().width() - 50, 50),
                                35, 35)
        if black_button.contains(mouse_pos):
            return True, "B"

        return False, ""
Ejemplo n.º 2
0
 def _write(self, shapes, svg_file, width, height, stroke_colour = None, stroke_width = None, background_colour = None):
 
     svg_file.write('<?xml version="1.0" standalone="no"?>\n'
                         '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"\n'
                         '  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n')
     
     svg_file.write('<svg width="%.6fcm" height="%.6fcm" ' % (width, height))
     svg_file.write('viewBox="%.6f %.6f %.6f %.6f" '
                         'xmlns="http://www.w3.org/2000/svg" '
                         'version="1.1">\n' % (0.0, 0.0, width, height))
     
     if stroke_width is None:
         stroke_width = "0.1%"
     
     if background_colour is not None:
     
         svg_file.write('<polygon fill="%s" ' % background_colour)
         svg_file.write('points="%.6f,%.6f %.6f,%.6f %.6f,%.6f %.6f,%.6f" />\n' % (
             0.0, 0.0, width, 0.0, width, height, 0.0, height))
     
     path = QPainterPath()
     shapes.reverse()
     
     new_shapes = {}
     
     for points, polygon in shapes:
     
         rgb = self.parts.colours.get(polygon.colour, "#ffffff")
         
         new_points = []
         for x, y in points:
             new_points.append(QPointF(x + width/2.0, height/2.0 - y))
         
         new_polygon = QPolygonF(new_points)
         new_path = QPainterPath()
         new_path.addPolygon(new_polygon)
         
         if path.contains(new_path):
             continue
         
         inter = path.intersected(new_path)
         remaining = new_path.subtracted(inter)
         
         # Combine the new path with the accumulated path and simplify
         # the result.
         path = path.united(new_path)
         path = path.simplified()
         
         piece_dict = new_shapes.setdefault(polygon.piece, {})
         colour_path = piece_dict.get(polygon.colour, QPainterPath())
         piece_dict[polygon.colour] = colour_path.united(remaining)
     
     for piece, piece_dict in new_shapes.items():
     
         svg_file.write('<g>\n')
         
         for colour, colour_path in piece_dict.items():
         
             if colour_path.isEmpty():
                 continue
             
             rgb = self.parts.colours.get(colour, "#ffffff")
             
             shape = '<path style="fill:%s; opacity:%f" d="' % (
                 rgb, self._opacity_from_colour(colour))
             
             i = 0
             in_path = False
             while i < colour_path.elementCount():
                 p = colour_path.elementAt(i)
                 if p.type == QPainterPath.MoveToElement:
                     if in_path:
                         shape += 'Z '
                     shape += 'M %.6f %.6f ' % (p.x, p.y)
                     in_path = True
                 elif p.type == QPainterPath.LineToElement:
                     shape += 'L %.6f %.6f ' % (p.x, p.y)
                 i += 1
             
             if in_path:
                 shape += 'Z'
             shape += '" />\n'
             
             svg_file.write(shape)
         
         svg_file.write('</g>\n')
     
     svg_file.write("</svg>\n")
     svg_file.close()
Ejemplo n.º 3
0
class CellItem(QGraphicsItem):
    """
    Class representing a cell on the screen.

    :IVariables:
        cell_id : int
            Identifier of the cell
        hover : bool
            True if the cell is being hovered over
        hover_contour : bool
            True if the contour of the cell is being hovered over
        hover_side : int|None
            Number of the side being hovered over
        sides : list of `QPainterPath`
            shape of each side
        polygon_id : list of int
            list of point ids for the polygon
        walls : `TimedWallShapes`
            Ref to the structure defining the shape of the walls at the current time
        points : dict of int * QPointF
            Ref to the structure holding the position of all the points at the current time
        current : bool
            True if the cell is the currently selected one
        drag_line : bool
            True if one of the side is being dragged
        p1 : int
            Start of a division line
        p2 : int
            End of a division line
    """
    def __init__(self,
                 scale,
                 glob_scale,
                 cell_id,
                 polygon,
                 points,
                 walls,
                 parent=None):
        QGraphicsItem.__init__(self, parent)
        self.cell_id = cell_id
        self.setZValue(2.5)
        self.setAcceptsHoverEvents(True)
        self.setSelectable(False)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
        self.hover = False
        self.hover_contour = False
        self.hover_side = None
        self.scale = scale
        self.glob_scale = glob_scale
        self.setToolTip(unicode(cell_id))
        self.polygon_id = polygon
        self.walls = walls
        self.sides = []
        self.points = points
        self.current = False
        self.drag_line = False
        self.dragging_line = False
        self.editable = False
        self.p1 = None
        self.p2 = None
        self.setGeometry()

    def __del__(self):
        cleanQObject(self)

    def setCurrent(self, value=True):
        """
        Set this cell as the current one (i.e. on top and different color)
        """
        if value:
            self.setZValue(2.8)
        else:
            self.setZValue(2.5)
        self.current = value
        self.update()

    def setDivisionLine(self, p1, p2):
        """
        Set the line from p1 to p2 to be a division line (i.e. different representation)
        """
        self.p1 = p1
        self.p2 = p2
        self.setGeometry()

    def setGeometry(self):
        """
        Read the parameters that define the geometry of the point
        """
        params = parameters.instance
        self.setEditable(params.is_cell_editable)
        points = self.points
        polygon_id = self.polygon_id
        polygon = [
            points[pt].pos() if pt in points else None for pt in polygon_id
        ]
        non_none_cnt = len([p for p in polygon if p is not None])
        if non_none_cnt == 0:
            self.rect = QRectF()
            self.bounding_rect = QRectF()
            self.setVisible(False)
            return
        self.setVisible(True)
        # First, check if this is a "simple" cell
        walls = self.walls
        real_polygon = [pid for pid in polygon_id if pid in points]
        #sides = [ walls[real_polygon[i], real_polygon[(i+1)%len(real_polygon)]] for i in range(len(real_polygon)) ]
        sides = [None] * len(polygon)
        self.sides = sides
        real_scale_x = self.scale[0] / self.glob_scale
        real_scale_y = self.scale[1] / self.glob_scale
        for i in range(len(polygon)):
            if polygon[i] is not None:  # Find the next
                j = (i + 1) % len(polygon)
                while polygon[j] is None:
                    j = (j + 1) % len(polygon)
                w = [
                    QPointF(p.x() * real_scale_x,
                            p.y() * real_scale_y)
                    for p in walls[polygon_id[i], polygon_id[j]]
                ]
                sides[i] = [polygon[i]] + w + [polygon[j]]
        prev = real_polygon[-1]
        polygon_shape = []
        for i in range(len(polygon)):
            if polygon[i]:
                polygon_shape.append(polygon[i])
                polygon_shape.extend(sides[i])
# Now add the dummy points .. starts at the first non-None point
        if non_none_cnt > 2:
            start = None
            for i in range(len(polygon)):
                if polygon[i] is not None:
                    start = i
                    break
            prev = start
            cur = start + 1 if start + 1 < len(polygon) else 0
            log_debug("Polygon before: [%s]" %
                      ",".join("(%f,%f)" %
                               (p.x(), p.y()) if p is not None else "None"
                               for p in polygon))
            while cur != start:
                if polygon[cur] is None:
                    cnt = 1
                    next = cur + 1 if cur + 1 < len(polygon) else 0
                    while True:
                        if polygon[next] is None:
                            cnt += 1
                        else:
                            break
                        next += 1
                        if next == len(polygon):
                            next = 0
                    #print "%d points missing" % cnt
                    # First, find total length of wall
                    length = 0.0
                    side = sides[prev]
                    for i in range(len(side) - 1):
                        length += dist(side[i], side[i + 1])
                    diff = length / (cnt + 1)  # Distance between two points
                    i = cur
                    p = side[0]
                    for j in range(cnt):
                        l = 0.0
                        found = False
                        for k in range(len(side) - 1):
                            dl = dist(side[k], side[k + 1])
                            l += dl
                            if l > diff * (
                                    1 + 1e-5
                            ):  # Account for accumulation of small errors
                                c = (i + j) % len(polygon)
                                delta = diff - l + dl
                                p = side[k] + (side[k + 1] -
                                               side[k]) * delta / dl
                                s1 = side[:k + 1] + [p]
                                s2 = [p] + side[k + 1:]
                                sides[c - 1] = s1
                                sides[c] = s2
                                side = s2
                                polygon[c] = p
                                found = True
                                break
                        assert found, "Could not find point in polygon for position %d" % (
                            j + i, )
                        #p = p + diff
                        #c = (i+j)%len(polygon)
                        #polygon[c] = QPointF(p)
                    cur = next
                else:
                    prev = cur
                    cur += 1
                if cur >= len(polygon):
                    cur = 0
            assert None not in polygon, "Error, some dummy points were not added"
        else:
            polygon = [p for p in polygon if p is not None]
        center = sum(polygon, QPointF(0, 0)) / float(len(polygon))
        self.center = center
        if len(polygon) > 2:
            polygon = QPolygonF(polygon + [polygon[0]])
            polygon.translate(-center)
            polygon_shape = QPolygonF(polygon_shape + [polygon_shape[0]])
            self.polygon_shape = polygon_shape
            polygon_shape.translate(-center)
            # Translate the sides too
            sides = [[p - center for p in s] for s in sides]
            self.sides = sides
            assert len(sides) == len(polygon) - 1
        elif len(polygon) == 2:
            polygon = QLineF(polygon[0], polygon[1])
            polygon.translate(-center)
        else:
            polygon = None
        self.polygon = polygon
        self.setPos(center)
        params = parameters.instance
        self.prepareGeometryChange()
        size = params.cell_size
        scale = self.scale
        height = size * cos(pi / 6) * scale[1]
        width = size * scale[0]
        pos_x = size * cos(pi / 3) * scale[0]
        self.sel_rect = QRectF(-width, -height, 2 * width, 2 * height)
        if isinstance(polygon, QPolygonF):
            self.rect = self.polygon_shape.boundingRect() | self.sel_rect
        elif isinstance(polygon, QLineF):
            self.rect = QRectF(polygon.p1(),
                               polygon.p2()).normalized() | self.sel_rect
        else:
            self.rect = self.sel_rect
        self.bounding_rect = QRectF(self.rect)
        if self.p1 in points and self.p2 in points:
            self.division_line = QLineF(points[self.p1].pos() - center,
                                        points[self.p2].pos() - center)
        else:
            self.division_line = None
        self.hexagon = QPolygonF([
            QPointF(-width, 0),
            QPointF(-pos_x, height),
            QPointF(pos_x, height),
            QPointF(width, 0),
            QPointF(pos_x, -height),
            QPointF(-pos_x, -height)
        ])
        self.hexagon_path = QPainterPath()
        self.hexagon_path.addPolygon(self.hexagon)
        s1 = QPainterPath()
        if isinstance(self.polygon, QPolygonF):
            s1.addPolygon(polygon_shape)
        elif isinstance(self.polygon, QLineF):
            s1.moveTo(self.polygon.p1())
            s1.lineTo(self.polygon.p2())
        stroke = QPainterPathStroker()
        sel_thick = 3 * params.cell_thickness
        if sel_thick == 0:
            sel_thick = 3
        stroke.setWidth(sel_thick)
        self.stroke = stroke.createStroke(s1)

    def changePoints(self, polygon):
        self.polygon_id = polygon
        self.setGeometry()

    def paint(self, painter, option, widget):
        params = parameters.instance
        pen = QPen(QColor(Qt.black))
        scale = self.scale
        ms = min(scale)
        pen.setWidth(params.cell_thickness)
        sel_thick = 2 * params.cell_thickness
        if sel_thick == 0:
            sel_thick = 2 * ms
        col = None
        if self.current:
            col = QColor(params.selected_cell_color)
        elif self.hover:
            col = QColor(params.cell_hover_color)
        else:
            col = QColor(params.cell_color)
        painter.setBrush(col)
        if self.hover_contour:
            pen1 = QPen(QColor(Qt.white))
            pen1.setWidth(sel_thick)
            painter.setPen(pen1)
        else:
            painter.setPen(pen)
        if isinstance(self.polygon, QPolygonF):
            painter.drawPolygon(self.polygon_shape)
        elif isinstance(self.polygon, QLineF):
            painter.drawLine(self.polygon)
        pen.setWidth(0)
        painter.setPen(pen)
        painter.drawPolygon(self.hexagon)
        if self.hover_side is not None:
            pen = QPen(QColor(Qt.red))
            pen.setWidth(sel_thick)
            side = self.sides[self.hover_side]
            painter.setPen(pen)
            pp = QPainterPath()
            pp.moveTo(side[0])
            for p in side[1:]:
                pp.lineTo(p)
            painter.drawPath(pp)
        elif self.division_line is not None:
            pen = QPen(params.division_wall_color)
            pen.setWidth(sel_thick)
            painter.setPen(pen)
            painter.drawLine(self.division_line)
        elif self.dragging_line:
            pen = QPen(QColor(Qt.red))
            pen.setWidth(sel_thick)
            painter.setPen(pen)
            polygon = self.polygon
            dg = self.drag_side
            p1 = polygon[dg]
            p2 = polygon[dg + 1]
            painter.drawLine(p1, self.moving_point)
            painter.drawLine(self.moving_point, p2)

    def setEditable(self, value):
        self.editable = value

    def boundingRect(self):
        return self.bounding_rect

    def shape(self):
        """
        Returns the shape used for selection
        """
        s = QPainterPath()
        s.addPath(self.hexagon_path)
        if self.editable:
            s.addPath(self.stroke)
        return s

    def setSelectable(self, value=True):
        self.setFlag(QGraphicsItem.ItemIsSelectable, value)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)

    def findClosestSide(self, pos):
        """
        Find the side of the polygon closest to pos
        """
        polygon = self.polygon
        min_dist = inf
        min_side = None
        if isinstance(polygon, QLineF):
            min_side = 0
            min_dist = 0
        else:
            #pos = pos + self.center
            sides = self.sides
            assert len(sides) == len(polygon) - 1
            for i in range(len(polygon) - 1):
                side = sides[i]
                d = distToPolyLine(pos, side)
                if d < min_dist:
                    min_dist = d
                    min_side = i
        #print "Closest side found = %d, with distance = %f"%(min_side,  min_dist)
        return min_side, min_dist

    def findHover(self, pos):
        """
        Find which side is being hovered over
        """
        if self.editable:
            if self.drag_line:
                self.hover = False
                self.hover_side = None
                self.hover_contour = False
            elif self.hexagon_path.contains(pos):
                self.hover = True
                self.hover_side = None
                self.hover_contour = False
            else:
                params = parameters.instance
                sel_thick = 3 * params.cell_thickness
                if sel_thick == 0:
                    sel_thick = 3
                self.hover_contour = True
                self.hover = False
                polygon = self.polygon
                if isinstance(polygon, QPolygonF):
                    min_side, min_dist = self.findClosestSide(pos)
                    #print "Closest side = %d"%min_side
                    if min_dist < sel_thick and min_side is not None:
                        self.hover_side = min_side
                    else:
                        self.hover_side = None
                        self.hover_contour = False
                        self.hover = True
        else:
            self.hover = True
            self.hover_side = None
            self.hover_contour = False

    def hoverEnterEvent(self, event):
        self.findHover(event.pos())
        self.update()

    def hoverMoveEvent(self, event):
        self.findHover(event.pos())
        self.update()

    def hoverLeaveEvent(self, event):
        self.hover = False
        self.hover_contour = False
        self.hover_side = None
        self.update()

    def mousePressEvent(self, event):
        if self.hover_side is not None:
            moving_point = QPointF(event.pos())
            self.drag_side = self.hover_side
            #self.polygon.insert(self.hover_side+1, moving_point)
            #self.sides[self.hover_side] = [self.polygon[self.hover_side], self.polygon[self.hover_side+1]]
            #self.sides.insert(self.hover_side+1, [self.polygon[self.hover_side+1], self.polygon[self.hover_side+2]])
            self.moving_point = moving_point
            self.start_drag = event.screenPos()
            self.hover_contour = False
            self.hover_side = None
            self.drag_line = True
            self.dragging_line = False
            self.update()
            event.accept()
        else:
            event.ignore()
            QGraphicsItem.mousePressEvent(self, event)

    def mouseMoveEvent(self, event):
        if not self.dragging_line and self.drag_line and (
                self.start_drag - event.screenPos()).manhattanLength() > 5:
            self.dragging_line = True
        if self.dragging_line:
            params = parameters.instance
            ms = min(self.scale)
            sel_thick = 2 * params.cell_thickness
            if sel_thick == 0:
                sel_thick = 2 * ms
            self.prepareGeometryChange()
            mp = self.moving_point
            mp.setX(event.pos().x())
            mp.setY(event.pos().y())
            self.bounding_rect = self.rect | QRectF(
                mp.x() - sel_thick,
                mp.y() - sel_thick, 2 * sel_thick, 2 * sel_thick)
            self.update()

    def mouseReleaseEvent(self, event):
        if self.dragging_line:
            log_debug("Adding point to cell")
            self.setGeometry()
            drag_side = (self.drag_side + 1) % (len(self.polygon) - 1)
            self.scene().addPointToCell(self.cell_id, drag_side,
                                        self.mapToScene(event.pos()))
        else:
            event.ignore()
            QGraphicsItem.mouseReleaseEvent(self, event)
        self.drag_line = False
        self.dragging_line = False
Ejemplo n.º 4
0
class CellItem(QGraphicsItem):
    """
    Class representing a cell on the screen.

    :IVariables:
        cell_id : int
            Identifier of the cell
        hover : bool
            True if the cell is being hovered over
        hover_contour : bool
            True if the contour of the cell is being hovered over
        hover_side : int|None
            Number of the side being hovered over
        sides : list of `QPainterPath`
            shape of each side
        polygon_id : list of int
            list of point ids for the polygon
        walls : `TimedWallShapes`
            Ref to the structure defining the shape of the walls at the current time
        points : dict of int * QPointF
            Ref to the structure holding the position of all the points at the current time
        current : bool
            True if the cell is the currently selected one
        drag_line : bool
            True if one of the side is being dragged
        p1 : int
            Start of a division line
        p2 : int
            End of a division line
    """

    def __init__(self, scale, glob_scale, cell_id, polygon, points, walls, parent=None):
        QGraphicsItem.__init__(self, parent)
        self.cell_id = cell_id
        self.setZValue(2.5)
        self.setAcceptsHoverEvents(True)
        self.setSelectable(False)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
        self.hover = False
        self.hover_contour = False
        self.hover_side = None
        self.scale = scale
        self.glob_scale = glob_scale
        self.setToolTip(unicode(cell_id))
        self.polygon_id = polygon
        self.walls = walls
        self.sides = []
        self.points = points
        self.current = False
        self.drag_line = False
        self.dragging_line = False
        self.editable = False
        self.p1 = None
        self.p2 = None
        self.setGeometry()

    def __del__(self):
        cleanQObject(self)

    def setCurrent(self, value=True):
        """
        Set this cell as the current one (i.e. on top and different color)
        """
        if value:
            self.setZValue(2.8)
        else:
            self.setZValue(2.5)
        self.current = value
        self.update()

    def setDivisionLine(self, p1, p2):
        """
        Set the line from p1 to p2 to be a division line (i.e. different representation)
        """
        self.p1 = p1
        self.p2 = p2
        self.setGeometry()

    def setGeometry(self):
        """
        Read the parameters that define the geometry of the point
        """
        params = parameters.instance
        self.setEditable(params.is_cell_editable)
        points = self.points
        polygon_id = self.polygon_id
        polygon = [points[pt].pos() if pt in points else None for pt in polygon_id]
        non_none_cnt = len([p for p in polygon if p is not None])
        if non_none_cnt == 0:
            self.rect = QRectF()
            self.bounding_rect = QRectF()
            self.setVisible(False)
            return
        self.setVisible(True)
# First, check if this is a "simple" cell
        walls = self.walls
        real_polygon = [pid for pid in polygon_id if pid in points]
        #sides = [ walls[real_polygon[i], real_polygon[(i+1)%len(real_polygon)]] for i in range(len(real_polygon)) ]
        sides = [None] * len(polygon)
        self.sides = sides
        real_scale_x = self.scale[0]/self.glob_scale
        real_scale_y = self.scale[1]/self.glob_scale
        for i in range(len(polygon)):
            if polygon[i] is not None:  # Find the next
                j = (i+1) % len(polygon)
                while polygon[j] is None:
                    j = (j+1) % len(polygon)
                w = [QPointF(p.x()*real_scale_x, p.y()*real_scale_y) for p in walls[polygon_id[i], polygon_id[j]]]
                sides[i] = [polygon[i]] + w + [polygon[j]]
        prev = real_polygon[-1]
        polygon_shape = []
        for i in range(len(polygon)):
            if polygon[i]:
                polygon_shape.append(polygon[i])
                polygon_shape.extend(sides[i])
# Now add the dummy points .. starts at the first non-None point
        if non_none_cnt > 2:
            start = None
            for i in range(len(polygon)):
                if polygon[i] is not None:
                    start = i
                    break
            prev = start
            cur = start+1 if start+1 < len(polygon) else 0
            log_debug("Polygon before: [%s]" % ",".join("(%f,%f)" % (p.x(), p.y()) if p is not None else "None"
                                                        for p in polygon))
            while cur != start:
                if polygon[cur] is None:
                    cnt = 1
                    next = cur+1 if cur+1 < len(polygon) else 0
                    while True:
                        if polygon[next] is None:
                            cnt += 1
                        else:
                            break
                        next += 1
                        if next == len(polygon):
                            next = 0
                    #print "%d points missing" % cnt
                    # First, find total length of wall
                    length = 0.0
                    side = sides[prev]
                    for i in range(len(side)-1):
                        length += dist(side[i], side[i+1])
                    diff = length/(cnt+1)  # Distance between two points
                    i = cur
                    p = side[0]
                    for j in range(cnt):
                        l = 0.0
                        found = False
                        for k in range(len(side)-1):
                            dl = dist(side[k], side[k+1])
                            l += dl
                            if l > diff*(1+1e-5):  # Account for accumulation of small errors
                                c = (i + j) % len(polygon)
                                delta = diff-l+dl
                                p = side[k] + (side[k+1]-side[k])*delta/dl
                                s1 = side[:k+1] + [p]
                                s2 = [p] + side[k+1:]
                                sides[c-1] = s1
                                sides[c] = s2
                                side = s2
                                polygon[c] = p
                                found = True
                                break
                        assert found, "Could not find point in polygon for position %d" % (j+i,)
                        #p = p + diff
                        #c = (i+j)%len(polygon)
                        #polygon[c] = QPointF(p)
                    cur = next
                else:
                    prev = cur
                    cur += 1
                if cur >= len(polygon):
                    cur = 0
            assert None not in polygon, "Error, some dummy points were not added"
        else:
            polygon = [p for p in polygon if p is not None]
        center = sum(polygon, QPointF(0, 0)) / float(len(polygon))
        self.center = center
        if len(polygon) > 2:
            polygon = QPolygonF(polygon+[polygon[0]])
            polygon.translate(-center)
            polygon_shape = QPolygonF(polygon_shape + [polygon_shape[0]])
            self.polygon_shape = polygon_shape
            polygon_shape.translate(-center)
            # Translate the sides too
            sides = [[p-center for p in s] for s in sides]
            self.sides = sides
            assert len(sides) == len(polygon)-1
        elif len(polygon) == 2:
            polygon = QLineF(polygon[0], polygon[1])
            polygon.translate(-center)
        else:
            polygon = None
        self.polygon = polygon
        self.setPos(center)
        params = parameters.instance
        self.prepareGeometryChange()
        size = params.cell_size
        scale = self.scale
        height = size*cos(pi/6)*scale[1]
        width = size*scale[0]
        pos_x = size*cos(pi/3)*scale[0]
        self.sel_rect = QRectF(-width, -height, 2*width, 2*height)
        if isinstance(polygon, QPolygonF):
            self.rect = self.polygon_shape.boundingRect() | self.sel_rect
        elif isinstance(polygon, QLineF):
            self.rect = QRectF(polygon.p1(), polygon.p2()).normalized() | self.sel_rect
        else:
            self.rect = self.sel_rect
        self.bounding_rect = QRectF(self.rect)
        if self.p1 in points and self.p2 in points:
            self.division_line = QLineF(points[self.p1].pos()-center, points[self.p2].pos()-center)
        else:
            self.division_line = None
        self.hexagon = QPolygonF([QPointF(-width, 0), QPointF(-pos_x, height), QPointF(pos_x, height),
                                  QPointF(width, 0), QPointF(pos_x, -height), QPointF(-pos_x, -height)])
        self.hexagon_path = QPainterPath()
        self.hexagon_path.addPolygon(self.hexagon)
        s1 = QPainterPath()
        if isinstance(self.polygon, QPolygonF):
            s1.addPolygon(polygon_shape)
        elif isinstance(self.polygon, QLineF):
            s1.moveTo(self.polygon.p1())
            s1.lineTo(self.polygon.p2())
        stroke = QPainterPathStroker()
        sel_thick = 3*params.cell_thickness
        if sel_thick == 0:
            sel_thick = 3
        stroke.setWidth(sel_thick)
        self.stroke = stroke.createStroke(s1)

    def changePoints(self, polygon):
        self.polygon_id = polygon
        self.setGeometry()

    def paint(self, painter, option, widget):
        params = parameters.instance
        pen = QPen(QColor(Qt.black))
        scale = self.scale
        ms = min(scale)
        pen.setWidth(params.cell_thickness)
        sel_thick = 2*params.cell_thickness
        if sel_thick == 0:
            sel_thick = 2*ms
        col = None
        if self.current:
            col = QColor(params.selected_cell_color)
        elif self.hover:
            col = QColor(params.cell_hover_color)
        else:
            col = QColor(params.cell_color)
        painter.setBrush(col)
        if self.hover_contour:
            pen1 = QPen(QColor(Qt.white))
            pen1.setWidth(sel_thick)
            painter.setPen(pen1)
        else:
            painter.setPen(pen)
        if isinstance(self.polygon, QPolygonF):
            painter.drawPolygon(self.polygon_shape)
        elif isinstance(self.polygon, QLineF):
            painter.drawLine(self.polygon)
        pen.setWidth(0)
        painter.setPen(pen)
        painter.drawPolygon(self.hexagon)
        if self.hover_side is not None:
            pen = QPen(QColor(Qt.red))
            pen.setWidth(sel_thick)
            side = self.sides[self.hover_side]
            painter.setPen(pen)
            pp = QPainterPath()
            pp.moveTo(side[0])
            for p in side[1:]:
                pp.lineTo(p)
            painter.drawPath(pp)
        elif self.division_line is not None:
            pen = QPen(params.division_wall_color)
            pen.setWidth(sel_thick)
            painter.setPen(pen)
            painter.drawLine(self.division_line)
        elif self.dragging_line:
            pen = QPen(QColor(Qt.red))
            pen.setWidth(sel_thick)
            painter.setPen(pen)
            polygon = self.polygon
            dg = self.drag_side
            p1 = polygon[dg]
            p2 = polygon[dg+1]
            painter.drawLine(p1, self.moving_point)
            painter.drawLine(self.moving_point, p2)

    def setEditable(self, value):
        self.editable = value

    def boundingRect(self):
        return self.bounding_rect

    def shape(self):
        """
        Returns the shape used for selection
        """
        s = QPainterPath()
        s.addPath(self.hexagon_path)
        if self.editable:
            s.addPath(self.stroke)
        return s

    def setSelectable(self, value=True):
        self.setFlag(QGraphicsItem.ItemIsSelectable, value)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)

    def findClosestSide(self, pos):
        """
        Find the side of the polygon closest to pos
        """
        polygon = self.polygon
        min_dist = inf
        min_side = None
        if isinstance(polygon, QLineF):
            min_side = 0
            min_dist = 0
        else:
            #pos = pos + self.center
            sides = self.sides
            assert len(sides) == len(polygon)-1
            for i in range(len(polygon)-1):
                side = sides[i]
                d = distToPolyLine(pos,  side)
                if d < min_dist:
                    min_dist = d
                    min_side = i
        #print "Closest side found = %d, with distance = %f"%(min_side,  min_dist)
        return min_side, min_dist

    def findHover(self, pos):
        """
        Find which side is being hovered over
        """
        if self.editable:
            if self.drag_line:
                self.hover = False
                self.hover_side = None
                self.hover_contour = False
            elif self.hexagon_path.contains(pos):
                self.hover = True
                self.hover_side = None
                self.hover_contour = False
            else:
                params = parameters.instance
                sel_thick = 3*params.cell_thickness
                if sel_thick == 0:
                    sel_thick = 3
                self.hover_contour = True
                self.hover = False
                polygon = self.polygon
                if isinstance(polygon, QPolygonF):
                    min_side, min_dist = self.findClosestSide(pos)
                    #print "Closest side = %d"%min_side
                    if min_dist < sel_thick and min_side is not None:
                        self.hover_side = min_side
                    else:
                        self.hover_side = None
                        self.hover_contour = False
                        self.hover = True
        else:
            self.hover = True
            self.hover_side = None
            self.hover_contour = False

    def hoverEnterEvent(self, event):
        self.findHover(event.pos())
        self.update()

    def hoverMoveEvent(self, event):
        self.findHover(event.pos())
        self.update()

    def hoverLeaveEvent(self, event):
        self.hover = False
        self.hover_contour = False
        self.hover_side = None
        self.update()

    def mousePressEvent(self, event):
        if self.hover_side is not None:
            moving_point = QPointF(event.pos())
            self.drag_side = self.hover_side
            #self.polygon.insert(self.hover_side+1, moving_point)
            #self.sides[self.hover_side] = [self.polygon[self.hover_side], self.polygon[self.hover_side+1]]
            #self.sides.insert(self.hover_side+1, [self.polygon[self.hover_side+1], self.polygon[self.hover_side+2]])
            self.moving_point = moving_point
            self.start_drag = event.screenPos()
            self.hover_contour = False
            self.hover_side = None
            self.drag_line = True
            self.dragging_line = False
            self.update()
            event.accept()
        else:
            event.ignore()
            QGraphicsItem.mousePressEvent(self, event)

    def mouseMoveEvent(self, event):
        if not self.dragging_line and self.drag_line and (self.start_drag - event.screenPos()).manhattanLength() > 5:
            self.dragging_line = True
        if self.dragging_line:
            params = parameters.instance
            ms = min(self.scale)
            sel_thick = 2*params.cell_thickness
            if sel_thick == 0:
                sel_thick = 2*ms
            self.prepareGeometryChange()
            mp = self.moving_point
            mp.setX(event.pos().x())
            mp.setY(event.pos().y())
            self.bounding_rect = self.rect | QRectF(mp.x()-sel_thick,
                                                    mp.y()-sel_thick,
                                                    2*sel_thick,
                                                    2*sel_thick)
            self.update()

    def mouseReleaseEvent(self, event):
        if self.dragging_line:
            log_debug("Adding point to cell")
            self.setGeometry()
            drag_side = (self.drag_side+1) % (len(self.polygon)-1)
            self.scene().addPointToCell(self.cell_id, drag_side, self.mapToScene(event.pos()))
        else:
            event.ignore()
            QGraphicsItem.mouseReleaseEvent(self, event)
        self.drag_line = False
        self.dragging_line = False