def BezierEllipse(points, center=None): assert len(self.points) == 4 p1, p2, p3, p4 = self.points a, b = distancetopoint(p1, p2), distancetopoint(p3, p4) if b > a: a, b = b, a p1, p2, p3, p4 = p3, p4, p1, p2 if center is not None: center = self.getCenter() if center is None: return None path = QPainterPath() path.moveTo(p1.x(), p1.y()) for pt1, pt2 in zip([p1, p3, p2, p4], [p3, p2, p4, p1]): d1 = pt1 - center d2 = pt2 - center # 关键是bezierCurveTo中两个控制点的设置 # 0.5和0.6是两个关键系数(在本函数中为试验而得) if distance(d2) > distance(d1): path.cubicTo(0.5 * d2.x() + pt1.x(), 0.5 * d2.y() + pt1.y(), 0.6 * d1.x() + pt2.x(), 0.6 * d1.y() + pt2.y(), pt2.x(), pt2.y()) else: path.cubicTo(0.6 * d2.x() + pt1.x(), 0.6 * d2.y() + pt1.y(), 0.5 * d1.x() + pt2.x(), 0.5 * d1.y() + pt2.y(), pt2.x(), pt2.y()) return path
def intersectingEdges(self, x1y1, x2y2, points): """For each edge formed by `points', yield the intersection with the line segment `(x1,y1) - (x2,y2)`, if it exists. Also return the distance of `(x2,y2)' to the middle of the edge along with its index, so that the one closest can be chosen.""" x1, y1 = x1y1 x2, y2 = x2y2 for i in range(4): x3, y3 = points[i] x4, y4 = points[(i + 1) % 4] denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1) nua = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3) nub = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3) if denom == 0: # This covers two cases: # nua == nub == 0: Coincident # otherwise: Parallel continue ua, ub = nua / denom, nub / denom if 0 <= ua <= 1 and 0 <= ub <= 1: x = x1 + ua * (x2 - x1) y = y1 + ua * (y2 - y1) m = QPointF((x3 + x4) / 2, (y3 + y4) / 2) d = distance(m - QPointF(x2, y2)) yield d, i, (x, y)
def nearestVertex(self, point, epsilon): # TODO: perhaps convert latlonPoints to points for i, p in enumerate(self.points): if distance(p - point) <= epsilon: return i return None
def nearestVertex(self, point, epsilon): if not self.active: return None for i, p in enumerate(self.points): #print(distance(p - point), epsilon) if distance(p - point) <= epsilon: return i return None
def nearestVertex(self, point, epsilon): for i, p in enumerate(self.points): if distance(p - point) <= epsilon: return (i, None) keypointIndex = self.keypoint.nearestVertex(point, epsilon) if keypointIndex is not None: return (None, keypointIndex) return None
def nearestVertex(self, point, epsilon): min_distance = float('inf') min_i = None for i, p in enumerate(self.points): dist = distance(p - point) if (dist <= epsilon and dist < min_distance): min_distance = dist min_i = i return min_i
def closeEnough(self, p1, p2): """ Returns the distance between a point and epsilon. This helps the user select a point of shape even if they're a few pixels off, which improves responsiveness. :param p1: Point 1. :param p2: Point 2. :return: True if the distance between p1 and p2 is less that epsilon. False otherwise. """ return distance(p1 - p2) < self.epsilon
def nearestVertex(self, point, epsilon): """ :param point: The point to compare with all vertices. :param epsilon: The epsilon value. :return: Return the point that is nearest the the given point. """ for i, p in enumerate(self.points): if distance(p - point) <= epsilon: return i return None
def mouseReleaseEvent(self, ev): if ev.button() == Qt.LeftButton: self.endPoint = ev.pos() self.update() self.isDrawing = False p = QPoint(abs(self.endPoint.x() - self.lastPoint.x()), abs(self.endPoint.y() - self.lastPoint.y())) if distance(p) > 10: category = LabelDialog(parent=None, listItem=self.labelList) category.exec_() if category.current_text is not '': self.lastPoint_list.append(self.lastPoint) self.endPoint_list.append(self.endPoint) self.category_list.append(category.current_text)
def onBoundary(self, point, epsilon): if not self.active: return None if len(self.points) <= 1: return None for i, p_1 in enumerate(self.points[:-1]): p_2 = self.points[i + 1] if distance(p_1 - point) + distance(p_2 - point) <= distance( p_1 - p_2) + epsilon: #print('on boundary') return i continue if self.isClosed(): p_1 = self.points[-1] p_2 = self.points[0] if distance(p_1 - point) + distance(p_2 - point) <= distance( p_1 - p_2) + epsilon: #print('on boundary') return len(self.points) - 1 pass return None
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 closeEnough(self, p1, p2): return distance(p1 - p2) < self.epsilon
def nearestVertex(self, point, epsilon): for i, p in enumerate(self.points): if distance(p - point) <= epsilon: return i return None
def overRotationPoint(self, point, epsilon): if distance(self.rotationPoint - point) <= epsilon: return True return False
def mousePressEvent(self, ev): mods = ev.modifiers() pos = self.transformPos(ev.pos()) task_mode = self.task_mode if self.start == True and task_mode == 0: self.started = True self.xuxian = None if ev.button() == Qt.LeftButton: if self.drawing(): # if self.shape_type == self.POLYGON_SHAPE and self.current: self.current.addPoint(self.line[1]) self.line[0] = self.current[-1] if self.current.isClosed(): self.finalise() elif self.shape_type == self.RECT_SHAPE and self.current and self.current.reachMaxPoints( ) is False: if self.task_mode == 5 and len(self.shapes) >= 3: self.current = None self.xuxian = None self.start = False self.started = False QMessageBox.about( self, "About", self.tr('<p><b>%s</b></p>%s <p>%s</p>' % ('注意标注已经为', str(3) + '个', '只可修改'))) return # self.repaint() initPos = self.current[0] minX = initPos.x() minY = initPos.y() targetPos = self.line[1] maxX = targetPos.x() maxY = targetPos.y() self.current.addPoint(QPointF(minX, maxY)) self.current.addPoint(targetPos) self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(initPos) self.line[0] = self.current[-1] if self.current.isClosed(): self.finalise() elif not self.outOfPixmap(pos): self.current = Shape(shape_type=self.shape_type) self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update() elif self.task_mode == 4: self.point_changed = True if self.point_modified: self.point_point_list[self.point_modified - 1] = pos self.point_modified = False self.repaint() else: distances = [] self.point_point_list.append(pos) # if not len(self.point_point_list)>self.point_num : if Qt.LeftButton & ev.buttons(): # 左鼠标点击 if self.outOfPixmap(pos): # 超出图像范围 return elif len(self.point_point_list) > 1: if self.point_point_list[ -1] and self.point_point_list[-2]: if distance(self.point_point_list[-1] - self.point_point_list[-2]) <= 5: self.point_move = True del self.point_point_list[-1] for i, p in enumerate(self.point_point_list[:-2]): if p: distances.append(distance(p - pos)) distances.sort() print('distances') if len(distances) >= 1: if distances[0] <= 5: #注意 一次只能删除一个点 if distances[0] <= 5: self.point_move = True #这里给出可移动的指令 del self.point_point_list[-1] if self.point_move: self.point_point = pos self.overrideCursor(Qt.CrossCursor) self.repaint() return else: self.selectShapePoint(pos) self.prevPoint = pos self.repaint() elif ev.button() == Qt.RightButton and self.editing(): self.selectShapePoint(pos) self.prevPoint = pos self.repaint() #这里只是传点吧
def mouseMoveEvent(self, ev): #这个函数是最重要的函数 """Update line with last point and current coordinates.""" pos = self.transformPos(ev.pos()) #点一下return一个pos self.restoreCursor() #鼠标图标 if not self.outOfPixmap(pos) and self.start and not self.started and ( self.task_mode == 0 or self.task_mode == 5): self.xuxian = pos self.repaint() if self.task_mode == 3: self.brush_point = pos if Qt.LeftButton & ev.buttons(): #左鼠标点击 if self.outOfPixmap(pos): #超出图像范围 return if not self.current_brush_path: self.current_brush_path = QPainterPath() self.current_brush_path.moveTo(pos) else: self.current_brush_path.lineTo(pos) self.repaint() return if self.task_mode == 4: self.point_point = pos if len(self.point_rects) == 1: self.draw_point_single_img(self.point_point_list, 0) else: if self.point_rects_index > 0: self.draw_point_single_img(self.point_point_list, self.point_rects_index) # else: # self.draw_point_single_img(self.point_point_list, self.point_rects_index) for i, p in enumerate(self.point_point_list): if p and distance(p - pos) <= 5: self.point_dex = i + 1 #这里加一的目的是为了绘制的时候 不会出现id=0的情况,因此self.point_dex最小为1 而不是0 self.Point_Change.emit(i, True, []) # point change 发射信号 self.repaint() return # Polygon drawing. if self.drawing(): self.start = True self.overrideCursor(CURSOR_DRAW) if self.current: color = self.lineColor if self.outOfPixmap(pos): # Don't allow the user to draw outside the pixmap. # Project the point to the pixmap's edges. pos = self.intersectionPoint(self.current[-1], pos) elif len(self.current) > 1 and self.closeEnough( pos, self.current[0]): # Attract line to starting point and colorise to alert the # user: pos = self.current[0] color = self.current.line_color self.overrideCursor(CURSOR_POINT) self.current.highlightVertex(0, Shape.NEAR_VERTEX) #add xu xian # self.line[1] = pos self.line.line_color = color self.repaint() self.current.highlightClear() return # Polygon copy moving. if Qt.RightButton & ev.buttons(): if self.selectedShapeCopy and self.prevPoint: self.overrideCursor(CURSOR_MOVE) self.boundedMoveShape(self.selectedShapeCopy, pos) self.repaint() elif self.selectedShape: self.selectedShapeCopy = self.selectedShape.copy() self.repaint() return # Polygon/Vertex moving. if Qt.LeftButton & ev.buttons(): if self.selectedVertex(): self.boundedMoveVertex(pos) self.shapeMoved.emit() self.repaint() elif self.selectedShape and self.prevPoint: self.overrideCursor(CURSOR_MOVE) self.boundedMoveShape(self.selectedShape, pos) self.shapeMoved.emit() self.repaint() return # Just hovering over the canvas, 2 posibilities: # - Highlight shapes # - Highlight vertex # Update shape/vertex fill and tooltip value accordingly. self.setToolTip("Image") for shape in reversed([s for s in self.shapes if self.isVisible(s)]): # Look for a nearby vertex to highlight. If that fails, # check if we happen to be inside a shape. index = shape.nearestVertex(pos, self.epsilon) if index is not None: if self.selectedVertex(): self.hShape.highlightClear() self.hVertex, self.hShape = index, shape shape.highlightVertex(index, shape.MOVE_VERTEX) self.overrideCursor(CURSOR_POINT) self.setToolTip("Click & drag to move point") #移动点 self.setStatusTip(self.toolTip()) self.update() break elif shape.containsPoint(pos): if self.selectedVertex(): self.hShape.highlightClear() self.hVertex, self.hShape = None, shape self.setToolTip("Click & drag to move shape '%s'" % shape.label) self.setStatusTip(self.toolTip()) self.overrideCursor(CURSOR_GRAB) self.update() break else: # Nothing found, clear highlights, reset state. if self.hShape: self.hShape.highlightClear() self.update() self.hVertex, self.hShape = None, None
def closeEnough(self, p1, p2): return distance(p1 - p2) < const.TOLERENCE
def lengthBetween2Points(self, pointA, pointB): return distance(pointA - pointB)
def mousePressEvent(self, ev): mods = ev.modifiers() pos = self.transformPos(ev.pos()) if ev.button() == Qt.LeftButton: if self.drawing(): # if self.shape_type == self.POLYGON_SHAPE and self.current: self.current.addPoint(self.line[1]) self.line[0] = self.current[-1] if self.current.isClosed(): self.finalise() elif self.shape_type == self.RECT_SHAPE and self.current and self.current.reachMaxPoints( ) is False: initPos = self.current[0] minX = initPos.x() minY = initPos.y() targetPos = self.line[1] maxX = targetPos.x() maxY = targetPos.y() self.current.addPoint(QPointF(minX, maxY)) self.current.addPoint(targetPos) self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(initPos) self.line[0] = self.current[-1] if self.current.isClosed(): self.finalise() elif not self.outOfPixmap(pos): self.current = Shape(shape_type=self.shape_type) self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update() elif self.task_mode == 4: distances = [] self.point_point_list.append(pos) if Qt.LeftButton & ev.buttons(): # 左鼠标点击 if self.outOfPixmap(pos): # 超出图像范围 return elif len(self.point_point_list) > 1: if distance(self.point_point_list[-1] - self.point_point_list[-2]) <= 5: self.point_move = True del self.point_point_list[-1] for i, p in enumerate(self.point_point_list[:-2]): distances.append(distance(p - pos)) distances.sort() print('distances', distances) if len(distances) >= 1: if distances[0] <= 5: #注意 一次只能删除一个点 print(self.point_point_list[-1]) if distances[0] <= 2: self.point_move = True #这里给出可移动的指令 del self.point_point_list[-1] if self.point_move: self.point_point = pos # elif Qt.RightButton & ev.buttons(): # print('dede') # for i, p in enumerate(self.point_point_list[:-2]): # if distance(p-pos)<=5: # print('delete point') self.overrideCursor(Qt.CrossCursor) self.repaint() return else: self.selectShapePoint(pos) self.prevPoint = pos self.repaint() elif ev.button() == Qt.RightButton and self.editing(): self.selectShapePoint(pos) self.prevPoint = pos self.repaint() #这里只是传点吧