|  | @@ -1,4 +1,6 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +from math import sqrt
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  from PyQt4.QtGui import *
 | 
	
		
			
				|  |  |  from PyQt4.QtCore import *
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -6,54 +8,71 @@ from shape import Shape
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class Canvas(QLabel):
 | 
	
		
			
				|  |  |      done = pyqtSignal()
 | 
	
		
			
				|  |  | -    epsilon = 7**2 # TODO: Tune value
 | 
	
		
			
				|  |  | +    epsilon = 7.0 # TODO: Tune value
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def __init__(self, *args, **kwargs):
 | 
	
		
			
				|  |  |          super(Canvas, self).__init__(*args, **kwargs)
 | 
	
		
			
				|  |  | -        self.points = []
 | 
	
		
			
				|  |  | -        self.shapes = [Shape('one', QColor(0, 255, 0))]
 | 
	
		
			
				|  |  | -        self.current_line = Shape('line', QColor(255, 0, 0))
 | 
	
		
			
				|  |  | +        self.shapes = []
 | 
	
		
			
				|  |  | +        self.current = None
 | 
	
		
			
				|  |  | +        self.line = Shape(line_color=QColor(0, 0, 255))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def mousePressEvent(self, ev):
 | 
	
		
			
				|  |  | -        if ev.button() != 1:
 | 
	
		
			
				|  |  | -            return
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        if not self.points:
 | 
	
		
			
				|  |  | -            self.setMouseTracking(True)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        self.points.append(ev.pos())
 | 
	
		
			
				|  |  | -        self.shapes[0].addPoint(ev.pos())
 | 
	
		
			
				|  |  | -        if self.isClosed():
 | 
	
		
			
				|  |  | -            self.done.emit()
 | 
	
		
			
				|  |  | -            print "Points:", self.points
 | 
	
		
			
				|  |  | -            self.points = []
 | 
	
		
			
				|  |  | -            self.shapes[0].setFill(True)
 | 
	
		
			
				|  |  | -            self.setMouseTracking(False)
 | 
	
		
			
				|  |  | +        if ev.button() == 1:
 | 
	
		
			
				|  |  | +            if self.current:
 | 
	
		
			
				|  |  | +                self.current.vertices.append(ev.pos())
 | 
	
		
			
				|  |  | +                if self.isClosed():
 | 
	
		
			
				|  |  | +                    self.finalise()
 | 
	
		
			
				|  |  | +                self.repaint()
 | 
	
		
			
				|  |  | +            else:
 | 
	
		
			
				|  |  | +                self.current = Shape()
 | 
	
		
			
				|  |  | +                self.current.vertices.append(ev.pos())
 | 
	
		
			
				|  |  | +                self.setMouseTracking(True)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def mouseDoubleClickEvent(self, ev):
 | 
	
		
			
				|  |  | +        if self.current:
 | 
	
		
			
				|  |  | +            self.current.vertices.append(self.current[0])
 | 
	
		
			
				|  |  | +            self.finalise()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def finalise(self):
 | 
	
		
			
				|  |  | +        assert self.current
 | 
	
		
			
				|  |  | +        self.current.fill = True
 | 
	
		
			
				|  |  | +        self.shapes.append(self.current)
 | 
	
		
			
				|  |  | +        self.current = None
 | 
	
		
			
				|  |  | +        # TODO: Mouse tracking is still useful for selecting shapes!
 | 
	
		
			
				|  |  | +        self.setMouseTracking(False)
 | 
	
		
			
				|  |  |          self.repaint()
 | 
	
		
			
				|  |  | +        self.done.emit()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def isClosed(self):
 | 
	
		
			
				|  |  | +        assert self.current
 | 
	
		
			
				|  |  | +        return len(self.current) > 1\
 | 
	
		
			
				|  |  | +           and self.closeEnough()
 | 
	
		
			
				|  |  |          return len(self.points) > 1 and self.closeEnough(self.points[0], self.points[-1])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def mouseMoveEvent(self, ev):
 | 
	
		
			
				|  |  | -        self.current_line.points = [self.points[-1], self.pos()]
 | 
	
		
			
				|  |  | -        self.repaint()
 | 
	
		
			
				|  |  | -       #print "moving", ev.pos()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        """Update line with last point and current coordinates."""
 | 
	
		
			
				|  |  | +        if self.current:
 | 
	
		
			
				|  |  | +            self.line.vertices = (self.current[-1], ev.pos())
 | 
	
		
			
				|  |  | +            self.repaint()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    def closeEnough(self, p1, p2):
 | 
	
		
			
				|  |  | -        def dist(p):
 | 
	
		
			
				|  |  | -            return p.x() * p.x() + p.y() * p.y()
 | 
	
		
			
				|  |  | -        print p1, p2
 | 
	
		
			
				|  |  | -        print abs(dist(p1) - dist(p2)), self.epsilon
 | 
	
		
			
				|  |  | -        return abs(dist(p1) - dist(p2)) < self.epsilon
 | 
	
		
			
				|  |  | +    def closeEnough(self):
 | 
	
		
			
				|  |  | +        assert self.current
 | 
	
		
			
				|  |  | +        def distance(p):
 | 
	
		
			
				|  |  | +            return sqrt(p.x() * p.x() + p.y() * p.y())
 | 
	
		
			
				|  |  | +        p1, p2 = self.current.vertices[0], self.current.vertices[-1]
 | 
	
		
			
				|  |  | +        d = distance(p1 - p2)
 | 
	
		
			
				|  |  | +        m = (p1-p2).manhattanLength()
 | 
	
		
			
				|  |  | +        print "d %.2f, m %d, %.2f" % (d, m, d - m)
 | 
	
		
			
				|  |  | +        return distance(p1 - p2) < self.epsilon
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def paintEvent(self, event):
 | 
	
		
			
				|  |  |          super(Canvas, self).paintEvent(event)
 | 
	
		
			
				|  |  | +        qp = QPainter()
 | 
	
		
			
				|  |  | +        qp.begin(self)
 | 
	
		
			
				|  |  |          for shape in self.shapes:
 | 
	
		
			
				|  |  | -            qp = QPainter()
 | 
	
		
			
				|  |  | -            qp.begin(self)
 | 
	
		
			
				|  |  | -            shape.drawShape(qp)
 | 
	
		
			
				|  |  | -            self.current_line.drawShape(qp)
 | 
	
		
			
				|  |  | -            qp.end()
 | 
	
		
			
				|  |  | +            shape.paint(qp)
 | 
	
		
			
				|  |  | +        if self.current:
 | 
	
		
			
				|  |  | +            self.current.paint(qp)
 | 
	
		
			
				|  |  | +            self.line.paint(qp)
 | 
	
		
			
				|  |  | +        qp.end()
 | 
	
		
			
				|  |  |  
 |