def closestBoundaryPos(self, pos): rect = self.boundingRect() #s = self._boundScale #T = QTransform.fromScale(1/s[0], 1/s[1]) #rect = T.mapRect(rect) if pos.x() < rect.left(): x = rect.left() elif pos.x() > rect.right(): x = rect.right() else: x = pos.x() if pos.y() < rect.top(): y = rect.top() elif pos.y() > rect.bottom(): y = rect.bottom() else: y = pos.y() rect_point = QPointF(x, y) r = self.cornerRadius() poly = None if mag2D(rect_point - rect.bottomRight()) <= r: poly = polygonFromArc(rect.bottomRight() + QPointF(-r, -r), r, 0, 90, seg=30) elif mag2D(rect_point - rect.topRight()) <= r: poly = polygonFromArc(rect.topRight() + QPointF(-r, r), r, 270, 360, seg=30) elif mag2D(rect_point - rect.topLeft()) <= r: poly = polygonFromArc(rect.topLeft() + QPointF(r, r), r, 180, 270, seg=30) elif mag2D(rect_point - rect.bottomLeft()) <= r: poly = polygonFromArc(rect.bottomLeft() + QPointF(r, -r), r, 90, 180, seg=30) if poly is None: return rect_point else: return closestPolyPoint(poly, pos)[0]
def tailPath(self): path = QPainterPath() path.moveTo(self._points[-1].pos()) line = self.tailLine() u = line.p2() - line.p1() v = QPointF(u.y(), -u.x()) mag_u = mag2D(u) if abs(mag_u) != 0: if self._firstTimeNonzero: self._firstTimeNonzero = False label = self.label(-1) if label: label.setPos(self.pointCenter()) u /= mag_u v /= mag_u r = self.arrowHeadSize() if self._mono: line_end = line.p1() + u * r else: line_end = line.p1() if not self.isBezier(): path.lineTo(line_end) else: path.cubicTo(self._points[-2].pos(), self._points[-3].pos(), line_end) if self._mono: perp_end = 1.5 * r * v path.cubicTo(line.p1(), line.p1() + perp_end, line_end + perp_end) return path
def updateArrowHead(self): line = self.line() if not self.isBezier(): if self._reversed: u = line.p1() - line.p2() else: u = line.p2() - line.p1() else: if self._reversed: u = self._points[0].pos() - self._points[1].pos() else: u = self._points[-1].pos() - self._points[-2].pos() mag_u = mag2D(u) if mag_u == 0.0: self._arrowHead = QPainterPath() return u /= mag_u v = QPointF(-u.y(), u.x()) # perp vector path = QPainterPath() if self._reversed: tip = line.p1() else: tip = line.p2() size = self.arrowHeadSize() p = tip - (u + v) * size q = tip + (v - u) * size r = tip - u * size path.moveTo(p) path.quadTo((p + tip + r) / 3, tip) path.quadTo((q + tip + r) / 3, q) self._arrowHead = path
def closestBoundaryPos(self, pos): rect = self.boundingRect() radius = rect.width() / 2 v = pos - rect.center() mag = mag2D(v) if abs(mag) == 0: return rect.topLeft() return v / mag * radius
def _paintEpiHead(self, painter): path = QPainterPath() path.moveTo(QPointF(0, 0)) path.addPath(self._arrowHead) line = self.headLine() u = line.p1() - line.p2() mag_u = mag2D(u) if mag_u != 0: u /= mag_u path.addPath(self._arrowHead.translated(u * self.arrowHeadSize())) painter.drawPath(path)
def setLinePoints(self, pos0, pos1): u = pos1 - pos0 mag_u = mag2D(u) if mag_u == 0.0: for k in range(0, len(self._points)): self._points[k].setPos(pos0) return u /= mag_u u *= mag_u / (len(self._points) - 1) for k in range(0, len(self._points)): self._points[k].setPos(pos0 + k * u) self.updateArrowHead() self.update()
def saveTextPosition(self, k=None): line = self.line() u = line.p2() - line.p1() mag_u = mag2D(u) if mag_u != 0: u /= mag_u v = QPointF(-u.y(), u.x()) if k is not None: label = self._labels[k] a = label.pos() - line.p1() self._textPos[k] = (dot2D(a, u), dot2D(a, v), mag_u) else: for k in range(len(self._labels)): label = self._labels[k] a = label.pos() - line.p1() a_proj_u = dot2D(a, u) a_proj_v = dot2D(a, v) self._textPos[k] = (a_proj_u, a_proj_v, mag_u)
def updateTextPosition(self): line = self.line() u = line.p2() - line.p1() mag_u1 = mag2D(u) u /= mag_u1 v = QPointF(-u.y(), u.x()) for k in range(len(self._labels)): pos = self._textPos[k] label = self._labels[k] a_proj_u = pos[0] a_proj_v = pos[1] mag_u = pos[2] if mag_u == 0.0: f = 1.0 else: f = mag_u1 / mag_u a_proj_u *= f v_a = v * a_proj_v u_a = u * a_proj_u a = line.p1() + u_a + v_a label.setPos(a) self.saveTextPosition()
def shape(self): if len(self._points) == 2: path = QPainterPath() u = self.line().p2() - self.line().p1() u /= mag2D(u) v = QPointF(-u.y(), u.x()) # perp vector v *= self.arrowHeadSize() p1 = self.line().p1() p2 = self.line().p2() size = self.arrowHeadSize() poly = QPolygonF([p1 + v, p1 - v, p2 - v, p2 + v, p1 + v]) path.addPolygon(poly) return path else: path = QPainterPath() path.moveTo(self._points[0].pos()) path.cubicTo(self._points[1].pos(), self._points[2].pos(), self._points[3].pos()) stroker = QPainterPathStroker( QPen(Qt.black, self.arrowHeadSize() * 2)) return stroker.createStroke(path)
def sceneEventFilter(self, watched, event): if event.type() == QEvent.GraphicsSceneMouseMove and mag2D( event.scenePos() - event.lastScenePos()) > 1: self.updateArrows() self.scene().update() return False