Przeglądaj źródła

Attract line to starting point

This approach seems much cleaner and more intuitive than the previous
one.

Take the opportunity to refactor the code.
Michael Pitidis 13 lat temu
rodzic
commit
57cf61b1a1
2 zmienionych plików z 58 dodań i 50 usunięć
  1. 40 37
      canvas.py
  2. 18 13
      shape.py

+ 40 - 37
canvas.py

@@ -7,32 +7,58 @@ from PyQt4.QtCore import *
 from shape import Shape
 from shape import Shape
 
 
 class Canvas(QLabel):
 class Canvas(QLabel):
-    done = pyqtSignal()
-    epsilon = 7.0 # TODO: Tune value
+    epsilon = 9.0 # TODO: Tune value
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         super(Canvas, self).__init__(*args, **kwargs)
         super(Canvas, self).__init__(*args, **kwargs)
         self.shapes = []
         self.shapes = []
         self.current = None
         self.current = None
-        self.line = Shape(line_color=QColor(0, 0, 255))
+        self.line_color = QColor(0, 0, 255)
+        self.line = Shape(line_color=self.line_color)
+
+    def mouseMoveEvent(self, ev):
+        """Update line with last point and current coordinates."""
+        if self.current:
+            if len(self.current) > 1 and self.closeEnough(ev.pos(), self.current[0]):
+                self.line[1] = self.current[0]
+                self.line.line_color = self.current.line_color
+            else:
+                self.line[1] = ev.pos()
+                self.line.line_color = self.line_color
+            self.repaint()
 
 
     def mousePressEvent(self, ev):
     def mousePressEvent(self, ev):
         if ev.button() == 1:
         if ev.button() == 1:
             if self.current:
             if self.current:
-                self.current.vertices.append(ev.pos())
-                if self.isClosed():
+                self.current.addPoint(self.line[1])
+                self.line[0] = self.current[-1]
+                if self.current.isClosed():
                     self.finalise()
                     self.finalise()
                 self.repaint()
                 self.repaint()
             else:
             else:
                 self.current = Shape()
                 self.current = Shape()
-                self.current.vertices.append(ev.pos())
+                self.line.points = [ev.pos(), ev.pos()]
+                self.current.addPoint(ev.pos())
                 self.setMouseTracking(True)
                 self.setMouseTracking(True)
 
 
     def mouseDoubleClickEvent(self, ev):
     def mouseDoubleClickEvent(self, ev):
         if self.current:
         if self.current:
-            self.current.vertices.append(self.current[0])
+            self.current.addPoint(self.current[0])
             self.finalise()
             self.finalise()
 
 
+    def paintEvent(self, event):
+        super(Canvas, self).paintEvent(event)
+        qp = QPainter()
+        qp.begin(self)
+        qp.setRenderHint(QPainter.Antialiasing)
+        for shape in self.shapes:
+            shape.paint(qp)
+        if self.current:
+            self.current.paint(qp)
+            self.line.paint(qp)
+        qp.end()
+
+
     def finalise(self):
     def finalise(self):
         assert self.current
         assert self.current
         self.current.fill = True
         self.current.fill = True
@@ -41,38 +67,15 @@ class Canvas(QLabel):
         # TODO: Mouse tracking is still useful for selecting shapes!
         # TODO: Mouse tracking is still useful for selecting shapes!
         self.setMouseTracking(False)
         self.setMouseTracking(False)
         self.repaint()
         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 closeEnough(self, p1, p2):
+        #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 mouseMoveEvent(self, ev):
-        """Update line with last point and current coordinates."""
-        if self.current:
-            self.line.vertices = (self.current[-1], ev.pos())
-            self.repaint()
 
 
-    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:
-            shape.paint(qp)
-        if self.current:
-            self.current.paint(qp)
-            self.line.paint(qp)
-        qp.end()
+def distance(p):
+    return sqrt(p.x() * p.x() + p.y() * p.y())
 
 

+ 18 - 13
shape.py

@@ -14,34 +14,39 @@ class Shape(object):
         self.line_color = line_color
         self.line_color = line_color
         self.fill_color = fill_color
         self.fill_color = fill_color
 
 
-        self.vertices = []
+        self.points = []
         self.fill = False
         self.fill = False
 
 
-    def addVertex(self, vertex):
-        self.vertices.append(vertex)
+    def addPoint(self, point):
+        self.points.append(point)
 
 
-    def popVertex(self):
-        if self.vertices:
-            return self.vertices.pop()
+    def popPoint(self):
+        if self.points:
+            return self.points.pop()
         return None
         return None
 
 
+    def isClosed(self):
+        return len(self.points) > 1 and self[0] == self[-1]
+
     def paint(self, painter):
     def paint(self, painter):
-        if self.vertices:
+        if self.points:
             pen = QPen(self.line_color)
             pen = QPen(self.line_color)
             painter.setPen(pen)
             painter.setPen(pen)
             path = QPainterPath()
             path = QPainterPath()
-            p0 = self.vertices[0]
-            path.moveTo(p0.x(), p0.y())
-            for v in self.vertices[1:]:
-                path.lineTo(v.x(), v.y())
+            path.moveTo(self.points[0].x(), self.points[0].y())
+            for p in self.points[1:]:
+                path.lineTo(p.x(), p.y())
             painter.drawPath(path)
             painter.drawPath(path)
 
 
             if self.fill:
             if self.fill:
                 painter.fillPath(path, self.fill_color)
                 painter.fillPath(path, self.fill_color)
 
 
     def __len__(self):
     def __len__(self):
-        return len(self.vertices)
+        return len(self.points)
 
 
     def __getitem__(self, key):
     def __getitem__(self, key):
-        return self.vertices[key]
+        return self.points[key]
+
+    def __setitem__(self, key, value):
+        self.points[key] = value