def __init__(self, position, angle, arrow_size, value, unit): super(StressRepresentation, self).__init__() arrow_line = QLineF() arrow_line.setP1(position) arrow_line.setLength(arrow_size) arrow_line.setAngle(angle) arrow = QGraphicsLineItem() arrow.setLine(arrow_line) self.addToGroup(arrow) arrow_head1_line = QLineF() arrow_head1_line.setP1(arrow_line.p1()) arrow_head1_line.setLength(arrow_size / 4) arrow_head1_line.setAngle(arrow_line.angle() + 45) arrow_head1 = QGraphicsLineItem() arrow_head1.setLine(arrow_head1_line) self.addToGroup(arrow_head1) arrow_head2_line = QLineF() arrow_head2_line.setP1(arrow_line.p1()) arrow_head2_line.setLength(arrow_size / 4) arrow_head2_line.setAngle(arrow_line.angle() - 45) arrow_head2 = QGraphicsLineItem() arrow_head2.setLine(arrow_head2_line) self.addToGroup(arrow_head2) text = QGraphicsTextItem() text.setPlainText(f'{str(value)}{unit}') text.setPos(arrow_line.p2()) self.addToGroup(text) self._set_color()
def update(self, eventPos, fase, point=None): # If user is setting the final point if fase == 1: if fase == 1: path = QPainterPath() path.moveTo(self.initialPoint.position) path.lineTo(eventPos) self.setPath(path) if point: self.finalPoint = point # If user is finishing the path (setting centerPoint) elif fase == 2: path = QPainterPath() path.moveTo(self.initialPoint.position) r = ((eventPos.x() - self.initialPoint.position.x())**2 + (eventPos.y() - self.initialPoint.position.y())**2)**(1 / 2) x, y, w, h = eventPos.x() - r, eventPos.y() - r, 2 * r, 2 * r line1 = QLineF(eventPos, self.initialPoint.position) line2 = QLineF(eventPos, self.finalPoint.position) startAngle, arcLenghth = line1.angle(), -(line1.angle() - line2.angle()) if arcLenghth == 0: arcLenghth = 360 path.arcTo(x, y, w, h, startAngle, arcLenghth) self.setPath(path) if point: self.centerPoint = point
def self_intersects(self): ''' Algorithm to check for self intersections in a Bézier curve as explained in 'Calculating the Self-Intersction of Bézier Curves' by Dieter Lasser from Technische Hochschule Darmstadt Department of Mathematics, in West Germany. We're only interested in if there is a self intersection though ''' # Lines connecting initial point, control points and final point of curve # in that order line1 = QLineF(self.initialPoint.position, self.ctrlPoint1.position) line2 = QLineF(self.ctrlPoint1.position, self.ctrlPoint2.position) line3 = QLineF(self.ctrlPoint2.position, self.finalPoint.position) # Angles between the 3 lines angle1 = line1.angleTo( line2) # Positive angle between the first two lines # Fixing the sine for the first angle if line1.angle() < line2.angle(): angle1 *= -1 angle2 = line2.angleTo( line3) # Positive angle between the last two lines # Fixing the sine for the second angle if line2.angle() < line3.angle(): angle2 *= -1 # If the angles sum up to 180 degrees or greater, there is a self-intersection if abs(angle1 + angle2) > 180: return True # Othewise, there is no self intersection return False
def _is_clockwise_general(self): # Find the point belonging to the zone with the lower x and y values half_edge = self.initialHalfEdge bottom_left_point = self.initialHalfEdge.init_point while half_edge.next is not self.initialHalfEdge: half_edge = half_edge.next if half_edge.init_point.position.y() < bottom_left_point.position.y() or\ (half_edge.init_point.position.y() == bottom_left_point.position.y() and half_edge.init_point.position.x() < bottom_left_point.position.x()): bottom_left_point = half_edge.init_point # If it is the tip of a crack, just go to the next one if len(bottom_left_point.connectivity) == 1: bottom_left_point = half_edge.twin.init_point half_edge = self.initialHalfEdge # Find the first half edge which has this point as its destiny while half_edge.twin.init_point is not bottom_left_point: half_edge = half_edge.next # When reaching this half edge during traversal, it is needed to make a # right turn to reach the next point half_edge_simplified1 = QLineF(half_edge.init_point.position, half_edge.twin.init_point.position) half_edge_simplified2 = QLineF(half_edge.next.init_point.position, half_edge.next.twin.init_point.position) # line1 = QLineF.fromPolar(1, half_edge.angleAtPercent(1.)) # line2 = QLineF.fromPolar(1, half_edge.next.angleAtPercent(0.)) line1 = QLineF.fromPolar(1, half_edge_simplified1.angle()) line2 = QLineF.fromPolar(1, half_edge_simplified2.angle()) # Equation to get the direction of turn is as follows direction_of_turn = line1.x2() * line2.y2() - line2.x2() * line1.y2() if direction_of_turn > 0: return True return False
def joystick_direction(self): if not self.grab_center: return 0 norm_vector = QLineF(self._center(), self.moving_offset) current_distance = norm_vector.length() angle = norm_vector.angle() distance = min(current_distance / self.__max_distance, 1.0) if current_distance > 30: if 22.5 <= angle < 67.5: self.calc_pwm(1, 1) return (Direction.RightUp, distance) elif 67.5 <= angle < 112.5: self.calc_pwm(0, 1) return (Direction.Up, distance) elif 112.5 <= angle < 157.5: self.calc_pwm(-1, 1) return (Direction.LeftUp, distance) elif 157.5 <= angle < 202.5: self.calc_pwm(-1, 0) return (Direction.Left, distance) elif 202.5 <= angle < 247.5: self.calc_pwm(-1, -1) return (Direction.LeftDown, distance) elif 247.5 <= angle < 292.5: self.calc_pwm(0, -1) return (Direction.Down, distance) elif 292.5 <= angle < 337.5: self.calc_pwm(1, -1) return (Direction.RightDown, distance) else: self.calc_pwm(1, 0) return (Direction.Right, distance) else: return (Direction.Neutral, 0)
def image(cls, **kwargs): """ Returns an image suitable for the palette. :rtype: QPixmap """ # INITIALIZATION pixmap = QPixmap(kwargs['w'], kwargs['h']) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) # INITIALIZE EDGE LINE pp1 = QPointF(((kwargs['w'] - 52) / 2), kwargs['h'] / 2) pp2 = QPointF(((kwargs['w'] - 52) / 2) + 52 - 2, kwargs['h'] / 2) line = QLineF(pp1, pp2) # CALCULATE HEAD COORDINATES angle = radians(line.angle()) p1 = QPointF(line.p2().x() + 2, line.p2().y()) p2 = p1 - QPointF(sin(angle + M_PI / 3.0) * 8, cos(angle + M_PI / 3.0) * 8) p3 = p1 - QPointF(sin(angle + M_PI - M_PI / 3.0) * 8, cos(angle + M_PI - M_PI / 3.0) * 8) # INITIALIZE EDGE HEAD head = QPolygonF([p1, p2, p3]) # DRAW THE POLYGON painter.setRenderHint(QPainter.Antialiasing) painter.setPen(QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(line) # DRAW HEAD painter.setPen(QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.setBrush(QColor(0, 0, 0)) painter.drawPolygon(head) # DRAW THE TEXT ON TOP OF THE EDGE space = 2 if Platform.identify() is Platform.Darwin else 0 painter.setFont(Font('Arial', 9, Font.Light)) painter.drawText(pp1.x() + space, (kwargs['h'] / 2) - 4, 'instanceOf') return pixmap
def image(cls, **kwargs): """ Returns an image suitable for the palette. :rtype: QPixmap """ # INITIALIZATION pixmap = QPixmap(kwargs['w'], kwargs['h']) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) # INIT THE LINE p1 = QPointF(((kwargs['w'] - 54) / 2), kwargs['h'] / 2) p2 = QPointF(((kwargs['w'] - 54) / 2) + 54 - 2, kwargs['h'] / 2) line = QLineF(p1, p2) # CLACULATE HEAD COORDS angle = line.angle() p1 = QPointF(line.p2().x() + 2, line.p2().y()) p2 = p1 - QPointF(sin(angle + M_PI / 3.0) * 8, cos(angle + M_PI / 3.0) * 8) p3 = p1 - QPointF(sin(angle + M_PI - M_PI / 3.0) * 8, cos(angle + M_PI - M_PI / 3.0) * 8) # INITIALIZE HEAD head = QPolygonF([p1, p2, p3]) # DRAW EDGE LINE painter.setRenderHint(QPainter.Antialiasing) painter.setPen(QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(line) # DRAW EDGE HEAD painter.setPen(QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.setBrush(QColor(0, 0, 0)) painter.drawPolygon(head) return pixmap
def setWedgeGizmo(self, neighbor_virtual_helix, neighbor_virtual_helix_item): """Adds a WedgeGizmo to oriented toward the specified neighbor vhi. Called by NucleicAcidPartItem _refreshVirtualHelixItemGizmos, in between with beginAddWedgeGizmos and endAddWedgeGizmos. Args: neighbor_virtual_helix (int): the id_num of neighboring virtual helix neighbor_virtual_helix_item (cadnano.views.sliceview.virtualhelixitem.VirtualHelixItem): the neighboring virtual helix item """ wg_dict = self.wedge_gizmos nvhi = neighbor_virtual_helix_item pos = self.scenePos() line = QLineF(pos, nvhi.scenePos()) line.translate(_RADIUS, _RADIUS) if line.length() > (_RADIUS * 1.99): color = '#5a8bff' else: color = '#cc0000' line.setLength(_RADIUS) if neighbor_virtual_helix in wg_dict: wedge_item = wg_dict[neighbor_virtual_helix] else: wedge_item = WedgeGizmo(_RADIUS, WEDGE_RECT, self) wg_dict[neighbor_virtual_helix] = wedge_item wedge_item.showWedge(line.angle(), color, outline_only=False) self._added_wedge_gizmos.add(neighbor_virtual_helix)
def setWedgeGizmo(self, neighbor_virtual_helix: int, neighbor_virtual_helix_item: GridVirtualHelixItemT): """Adds a WedgeGizmo to oriented toward the specified neighbor vhi. Called by NucleicAcidPartItem _refreshVirtualHelixItemGizmos, in between with beginAddWedgeGizmos and endAddWedgeGizmos. Args: neighbor_virtual_helix: the id_num of neighboring virtual helix neighbor_virtual_helix_item: the neighboring virtual helix item """ wg_dict = self.wedge_gizmos nvhi = neighbor_virtual_helix_item nvhi_name = nvhi.getProperty('name') pos = self.scenePos() line = QLineF(pos, nvhi.scenePos()) line.translate(_RADIUS, _RADIUS) if line.length() > (_RADIUS*1.99): color = '#5a8bff' else: color = '#cc0000' nvhi_name = nvhi_name + '*' # mark as invalid line.setLength(_RADIUS) if neighbor_virtual_helix in wg_dict: wedge_item = wg_dict[neighbor_virtual_helix] else: wedge_item = WedgeGizmo(_RADIUS, WEDGE_RECT, self) wg_dict[neighbor_virtual_helix] = wedge_item wedge_item.showWedge(line.angle(), color, outline_only=False) self._added_wedge_gizmos.add(neighbor_virtual_helix)
def setWedgeGizmo(self, neighbor_virtual_helix: int, neighbor_virtual_helix_item: SliceVirtualHelixItemT): """Adds a :class:`WedgeGizmo` to oriented toward the specified neighbor vhi. Called by :meth:`SliceNucleicAcidPartItem._refreshVirtualHelixItemGizmos`, before :meth:`setWedgeGizmo` and :meth:`endAddWedgeGizmos`. Args: neighbor_virtual_helix: the id_num of neighboring virtual helix neighbor_virtual_helix_item: the neighboring virtual helix item """ wg_dict = self.wedge_gizmos nvhi = neighbor_virtual_helix_item pos = self.scenePos() line = QLineF(pos, nvhi.scenePos()) line.translate(_RADIUS, _RADIUS) if line.length() > (_RADIUS * 1.99): color = '#5a8bff' else: color = '#cc0000' line.setLength(_RADIUS) if neighbor_virtual_helix in wg_dict: wedge_item = wg_dict[neighbor_virtual_helix] else: wedge_item = WedgeGizmo(_RADIUS, WEDGE_RECT, self) wg_dict[neighbor_virtual_helix] = wedge_item wedge_item.showWedge(line.angle(), color, outline_only=False) self._added_wedge_gizmos.add(neighbor_virtual_helix)
def joystickDirection(self): if not self.grabCenter: return 0 normVector = QLineF(self._center(), self.movingOffset) currentDistance = normVector.length() angle = int(normVector.angle()) distance = int(currentDistance / self.__maxDistance * 0) setPID(angle, distance) return (Direction.Right, distance)
def draw(self, painter): rect = QRectF(self.center.x() - self.radius, self.center.y() - self.radius, self.radius * 2, self.radius * 2) lineA = QLineF(self.center, self.A) lineB = QLineF(self.center, self.B) sweepAngle = lineA.angleTo(lineB) if (sweepAngle > 180): sweepAngle -= 360 painter.drawArc(rect, 16 * lineA.angle(), 16 * sweepAngle)
def fire(self): arrow = Arrow() arrow.setPos(self.x(), self.y()) attack_line = QLineF(QPointF(self.x() + 25, self.y() + 25), self.attack_destination) line = QGraphicsLineItem(attack_line) line.setPen(QPen(Qt.blue)) # self.scene().addItem(line) attack_angle = -1 * attack_line.angle( ) # Multiplied by -1 because the angle is given in counter clockwise direction arrow.setRotation(attack_angle) self.scene().addItem(arrow)
def fire(self): if not self.scene(): return bullet = Bullet(self) bullet.setPos(self.x() + 40, self.y() + 40) # set the angle to be paralel to the line that connects the # tower and target ln = QLineF(QPointF(self.x() + 40, self.y() + 40), self.attack_dest) angle = -1 * ln.angle() # -1 to make it clock wise bullet.setRotation(angle) self.scene().addItem(bullet)
def shape(self): # print(2) if self.centerPoint: r = ((self.centerPoint.x() - self.initialPoint.position.x())**2 + (self.centerPoint.y() - self.initialPoint.position.y())**2)**( 1 / 2) w, h = 2 * r, 2 * r pf = self.path().pointAtPercent(1 - 4 / self.path().length()) pi = self.path().pointAtPercent(4 / self.path().length()) line1 = QLineF(self.centerPoint.position, pi) line2 = QLineF(self.centerPoint.position, pf) startAngle, arcLength = line1.angle(), -(line1.angle() - line2.angle()) if arcLength == 0: arcLength = 360 path = QPainterPath() path.moveTo(pi) path.arcTo(self.path().boundingRect(), startAngle, arcLength) path.arcTo(self.path().boundingRect(), line2.angle(), -arcLength) return path else: return super(arcEdge, self).shape()
def joystickDirection(self): if not self.grabCenter: return 0 normVector = QLineF(self._center(), self.movingOffset) currentDistance = normVector.length() angle = normVector.angle() distance = min(currentDistance / self.__maxDistance, 1.0) if 45 <= angle < 135: return (Direction.Up, distance) elif 135 <= angle < 225: return (Direction.Left, distance) elif 225 <= angle < 315: return (Direction.Down, distance) return (Direction.Right, distance)
def getSelectionPolygon(self): line = QLineF(self.source_point, self.dest_point) angle = line.angle() * np.pi / 180 dx = self.selection_offset * np.sin(angle) dy = self.selection_offset * np.cos(angle) offset1 = QPointF(dx, dy) offset2 = QPointF(-dx, -dy) points = [ line.p1() + offset1, line.p1() + offset2, line.p2() + offset2, line.p2() + offset1 ] polygon = QPolygonF(points) return polygon
def arrow_path_concave(line, width): """ Return a :class:`QPainterPath` of a pretty looking arrow. """ path = QPainterPath() p1, p2 = line.p1(), line.p2() if p1 == p2: return path baseline = QLineF(line) # Require some minimum length. baseline.setLength(max(line.length() - width * 3, width * 3)) start, end = baseline.p1(), baseline.p2() mid = (start + end) / 2.0 normal = QLineF.fromPolar(1.0, baseline.angle() + 90).p2() path.moveTo(start) path.lineTo(start + (normal * width / 4.0)) path.quadTo(mid + (normal * width / 4.0), end + (normal * width / 1.5)) path.lineTo(end - (normal * width / 1.5)) path.quadTo(mid - (normal * width / 4.0), start - (normal * width / 4.0)) path.closeSubpath() arrow_head_len = width * 4 arrow_head_angle = 50 line_angle = line.angle() - 180 angle_1 = line_angle - arrow_head_angle / 2.0 angle_2 = line_angle + arrow_head_angle / 2.0 points = [ p2, p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), baseline.p2(), p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), p2 ] poly = QPolygonF(points) path_head = QPainterPath() path_head.addPolygon(poly) path = path.united(path_head) return path
def image(cls, **kwargs): """ Returns an image suitable for the palette. :rtype: QPixmap """ # INITIALIZATION pixmap = QPixmap(kwargs['w'], kwargs['h']) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) # INITIALIZE EDGE LINE p1 = QPointF(((kwargs['w'] - 54) / 2), kwargs['h'] / 2) p2 = QPointF(((kwargs['w'] - 54) / 2) + 54 - 2, kwargs['h'] / 2) line = QLineF(p1, p2) # CALCULATE HEAD COORDS angle = radians(line.angle()) p1 = QPointF(line.p2().x() + 2, line.p2().y()) p2 = p1 - QPointF( sin(angle + M_PI / 4.0) * 8, cos(angle + M_PI / 4.0) * 8) p3 = p2 - QPointF( sin(angle + 3.0 / 4.0 * M_PI) * 8, cos(angle + 3.0 / 4.0 * M_PI) * 8) p4 = p3 - QPointF( sin(angle - 3.0 / 4.0 * M_PI) * 8, cos(angle - 3.0 / 4.0 * M_PI) * 8) # INITIALIZE HEAD head = QPolygonF([p1, p2, p3, p4]) # INITIALIZE EDGE PEN linePen = QPen(QColor(0, 0, 0), 1.1, Qt.CustomDashLine, Qt.RoundCap, Qt.RoundJoin) linePen.setDashPattern([3, 3]) # DRAW EDGE POLYGON painter.setRenderHint(QPainter.Antialiasing) painter.setPen(linePen) painter.drawLine(line) # DRAW EDGE HEAD painter.setPen( QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.setBrush(QColor(252, 252, 252)) painter.drawPolygon(head) return pixmap
def image(cls, **kwargs): """ Returns an image suitable for the palette. :rtype: QPixmap """ # INITIALIZATION pixmap = QPixmap(kwargs['w'], kwargs['h']) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) # INIT THE LINE p1 = QPointF(((kwargs['w'] - 54) / 2), kwargs['h'] / 2) p2 = QPointF(((kwargs['w'] - 54) / 2) + 54 - 2, kwargs['h'] / 2) line = QLineF(p1, p2) # CLACULATE HEAD COORDS angle = line.angle() p1 = QPointF(line.p2().x() + 2, line.p2().y()) p2 = p1 - QPointF( sin(angle + M_PI / 3.0) * 8, cos(angle + M_PI / 3.0) * 8) p3 = p1 - QPointF( sin(angle + M_PI - M_PI / 3.0) * 8, cos(angle + M_PI - M_PI / 3.0) * 8) # INITIALIZE HEAD head = QPolygonF([p1, p2, p3]) # DRAW EDGE LINE painter.setRenderHint(QPainter.Antialiasing) painter.setPen( QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(line) # DRAW EDGE HEAD painter.setPen( QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.setBrush(QColor(0, 0, 0)) painter.drawPolygon(head) return pixmap
def mouseMoveEvent(self, event): path, text = self._rulerObject baseElem = path.elementAt(0) canvasPos = event.localPos() if event.modifiers() & Qt.ShiftModifier: basePos = QPointF(baseElem.x, baseElem.y) canvasPos = self.clampToOrigin(canvasPos, basePos) canvasPos = self.magnetPos(canvasPos) x, y = canvasPos.x(), canvasPos.y() path.setElementPositionAt(1, x, baseElem.y) path.setElementPositionAt(2, x, y) path.setElementPositionAt(3, baseElem.x, baseElem.y) line = QLineF(baseElem.x, baseElem.y, x, y) l = line.length() # angle() doesnt go by trigonometric direction. Weird. # TODO: maybe split in positive/negative 180s (ff) a = 360 - line.angle() line.setP2(QPointF(x, baseElem.y)) h = line.length() line.setP1(QPointF(x, y)) v = line.length() text = "%d\n↔ %d\n↕ %d\nα %dº" % (l, h, v, a) self._rulerObject = (path, text) self.parent().update()
def drawArrows(self, painter): """Draws arrows on the board.""" for highlight in self.highlights: if highlight.Type == self.Arrow.Type: lineWidth = 10 sqSize = self.squareSize painter.setPen( QPen(highlight.color, lineWidth, Qt.SolidLine, Qt.RoundCap)) origin = highlight.origin target = highlight.target dx = target.x() - origin.x() dy = target.y() - origin.y() # Knight jumps if dx == sqSize.width() and dy == -2 * sqSize.height(): corner = QPoint(origin.x(), origin.y() - 2 * sqSize.height()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == 2 * sqSize.width() and dy == -sqSize.height(): corner = QPoint(origin.x() + 2 * sqSize.width(), origin.y()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == 2 * sqSize.width() and dy == sqSize.height(): corner = QPoint(origin.x() + 2 * sqSize.width(), origin.y()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == sqSize.width() and dy == 2 * sqSize.height(): corner = QPoint(origin.x(), origin.y() + 2 * sqSize.height()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == -sqSize.width() and dy == 2 * sqSize.height(): corner = QPoint(origin.x(), origin.y() + 2 * sqSize.height()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == -2 * sqSize.width() and dy == sqSize.height(): corner = QPoint(origin.x() - 2 * sqSize.width(), origin.y()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == -2 * sqSize.width() and dy == -sqSize.height(): corner = QPoint(origin.x() - 2 * sqSize.width(), origin.y()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == -sqSize.width() and dy == -2 * sqSize.height(): corner = QPoint(origin.x(), origin.y() - 2 * sqSize.height()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner # Other moves (and second part of knight jump) line = QLineF(origin, target) angle = line.angle() tip = line.p2() line.setLength(line.length() - 2 * lineWidth) painter.drawLine(line) tipOffset = line.p2() leftBase = QLineF() leftBase.setP1(tipOffset) leftBase.setLength(lineWidth) leftBase.setAngle(angle - 90) left = leftBase.p2() rightBase = QLineF() rightBase.setP1(tipOffset) rightBase.setLength(lineWidth) rightBase.setAngle(angle + 90) right = rightBase.p2() arrowHead = QPolygonF([left, right, tip]) path = QPainterPath() path.addPolygon(arrowHead) painter.fillPath(path, QBrush(highlight.color))
def paint(self, painter, option, widget=None): super(L1CircuitItem, self).paint(painter, option, widget) painter.save() n1_p = Vector(*self.source_node.get_position()) n2_p = Vector(*self.link.target.get_position()) uv = (n2_p - n1_p).unit() start = n1_p + uv * self.source_node.get_radius() end = n2_p - uv * self.link.target.get_radius() #if multiple links ( always ) if self.link.link_num % 2 == 0: targetDistance = self.link.link_num * 2 else: targetDistance = (-self.link.link_num + 1) * 2 start = start.rotated_new(self.arrow_separation * targetDistance, n1_p) end = end.rotated_new(-self.arrow_separation * targetDistance, n2_p) if self.link._failed: link_color = Qt.red else: link_color = Qt.green painter.setPen(QPen(link_color, Qt.SolidLine)) painter.drawLine(QPointF(*start), QPointF(*end)) painter.setPen(QPen(Qt.black, Qt.SolidLine)) painter.setBrush(QBrush( Qt.black, Qt.SolidPattern, )) #rect calculation r = self.weight_rectangle_size mid = (start + end) / 2 w_len = len(str(self.link.label)) * 4 weight_v = Vector(r if w_len <= r else w_len, r) weight_rectangle = QRectF(*(mid - weight_v), *(2 * weight_v)) if end.unit()[0] - start.unit()[0] > 0: link_paint = QLineF(QPointF(*start), QPointF(*end)) else: link_paint = QLineF(QPointF(*end), QPointF(*start)) center_of_rec_x = weight_rectangle.center().x() center_of_rec_y = weight_rectangle.center().y() painter.translate(center_of_rec_x, center_of_rec_y) rx = -(weight_v[0] * 0.5) ry = -(weight_v[1]) painter.rotate(-link_paint.angle()) new_rec = QRect(rx, ry, weight_v[0], 2 * weight_v[1]) painter.drawRect(QRect(rx, ry, weight_v[0], 2 * weight_v[1])) painter.setFont(QFont(self.font_family, self.font_size / 4)) painter.setPen(QPen(Qt.white, Qt.SolidLine)) painter.drawText(new_rec, Qt.AlignCenter, str(self.link.label)) painter.restore() painter.setPen(QPen(Qt.black, Qt.SolidLine)) painter.setFont(QFont(self.font_family, self.font_size / 3))
def rotateToPoint(self, point): track_line = QLineF(self.pos(), point) self.setRotation(-1 * track_line.angle())
def generate_grid_pts(self, tl_x=None, tl_y=None, br_x=None, br_y=None, angle=None): """ Return grid point coordinates of a grid with top left corner `(tl_x, tl_y)` and bottom right corner `(br_x, br_y)`, angled `angle` (`angle` follows same notation of `self.phi`). Default parameters are current grid coordinates. grid_pts has shape (rows+1, cols+1, 2) and is read as (n-th, m-th, (x, y)). Refer to the attached PDF for the notation used in the code. Parameters ---------- tl_x: float x-coordinate of top left corner tl_y: float y-coordinate of top left corner br_x: float x-coordinate of bottom right corner br_y: float y-coordinate of bottom right corner angle: float phi angle Returns ------- """ """If no arguments are given use current grid position""" r = AdjustableGrid.disk_radius tl_x = self.tl_disk.x() + r if tl_x is None else tl_x tl_y = self.tl_disk.y() + r if tl_y is None else tl_y br_x = self.br_disk.x() + r if br_x is None else br_x br_y = self.br_disk.y() + r if br_y is None else br_y angle = self.phi if angle is None else angle """Compute angles and edge lengths""" tl_br_line = QLineF(tl_x, tl_y, br_x, br_y) tl_br_length = tl_br_line.length() tl_br_angle_deg = 360 - tl_br_line.angle() # angle() is CCW in deg tl_br_angle_rad = tl_br_angle_deg * 2 * np.pi / 360 # convert to rad theta = tl_br_angle_rad - angle cos_angle = np.cos(angle) sin_angle = np.sin(angle) l1 = tl_br_length * np.cos(theta) l2 = tl_br_length * np.sin(theta) """Generate grid points""" xs = np.array([[ n * l1 * cos_angle / self.num_cols - m * l2 * sin_angle / self.num_rows + tl_x for m in range(self.num_rows + 1) ] for n in range(self.num_cols + 1)]) # TODO rewrite clearly ys = np.array([[ n * l1 * sin_angle / self.num_cols + m * l2 * cos_angle / self.num_rows + tl_y for m in range(self.num_rows + 1) ] for n in range(self.num_cols + 1)]) # TODO rewrite clearly grid_pts = np.dstack((xs, ys)) return grid_pts
def paint(self, painter, option, widget=None): super(Link, self).paint(painter, option, widget) util = self.link.utilization() orangeColor = QColor(255, 165, 0) colour_values = { self.blue_threshold: QtCore.Qt.blue, self.green_threshold: QtCore.Qt.green, self.yellow_threshold: QtCore.Qt.yellow, self.orange_threshold: orangeColor, } colour_values_list = sorted(colour_values) link_color_index = bisect_left(colour_values_list, util) if self.link._failed: link_color = QtCore.Qt.red elif util == 0: link_color = QtCore.Qt.black elif util > int(orange_threshold): link_color = QtCore.Qt.magenta else: try: link_color_key = colour_values_list[link_color_index] link_color = colour_values[link_color_key] # print(util, link_color, link_color_index, link_color_key) except: # guard agains <100% thresholds value link_color = QtCore.Qt.magenta painter.save() painter.setFont(QFont(self.font_family, self.font_size / 3)) if self.link.link_num % 2 == 0: targetDistance = self.link.link_num * 5 else: targetDistance = (-self.link.link_num + 1) * 5 # hours of calculation and still can't figure out where it's wrong n1_p = Vector(*self.source_node.get_position()) n2_p = Vector(*self.link.target.get_position()) x1_x0 = n2_p[0] - n1_p[0] y1_y0 = n2_p[1] - n1_p[1] if y1_y0 == 0: x2_x0 = 0 y2_y0 = targetDistance else: angle = math.atan((x1_x0) / (y1_y0)) x2_x0 = -targetDistance * math.cos(angle) y2_y0 = targetDistance * math.sin(angle) d0x = n1_p[0] + (1 * x2_x0) d0y = n1_p[1] + (1 * y2_y0) d1x = n2_p[0] + (1 * x2_x0) d1y = n2_p[1] + (1 * y2_y0) dx = (d1x - d0x,) dy = (d1y - d0y,) dr = math.sqrt(dx[0] * dx[0] + dy[0] * dy[0]) endX = (d1x + d0x) / 2 endY = (d1y + d0y) / 2 len1 = dr - ((dr / 2) * math.sqrt(3)) endX = endX + (len1 / dr) endY = endY + (len1 / dr) n1_p = Vector(d0x, d0y) n2_p = Vector(endX, endY) uv = (n2_p - n1_p).unit() d = distance(n1_p, n2_p) r = self.link.target.get_radius() arrow_head_pos = n2_p d = distance(n1_p, arrow_head_pos) uv_arrow = (arrow_head_pos - n1_p).unit() arrow_base_pos = n1_p + uv_arrow * (d - 2 * 2) nv_arrow = uv_arrow.rotated(math.pi / 2) painter.setRenderHints( QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing | QtGui.QPainter.SmoothPixmapTransform | QtGui.QPainter.HighQualityAntialiasing, True, ) if self.link.highlight: painter.setPen(QPen(link_color, 3, 3)) elif option.state & QtWidgets.QStyle.State_Selected: painter.setPen(QPen(link_color, 2, 4)) else: painter.setPen(QPen(link_color, Qt.SolidLine)) painter.setBrush(QBrush(link_color, Qt.SolidPattern)) painter.drawPolygon( QPointF(*arrow_head_pos), QPointF(*(arrow_base_pos + nv_arrow * 2)), QPointF(*(arrow_base_pos - nv_arrow * 2)), ) painter.drawLine(QPointF(d0x, d0y), QPointF(endX, endY)) painter.setPen(QtGui.QPen(link_color, 1)) # text if endX - d0x > 0: link_paint = QLineF(QPointF(d0x, d0y), QPointF(endX, endY)) else: link_paint = QLineF(QPointF(endX, endY), QPointF(d0x, d0y)) mid = (arrow_base_pos + n1_p) / 2 if self.show_latency: w_len = ( len(str(self.link.metric) + str(self.link.latency) + "------") / 3 * r + r / 3 ) else: w_len = len(str(self.link.metric)) / 3 * r + r / 3 weight_v = Vector(w_len, 2) weight_rectangle = QRectF(*(mid - weight_v), *(2 * weight_v)) painter.save() center_of_rec_x = weight_rectangle.center().x() center_of_rec_y = weight_rectangle.center().y() painter.translate(center_of_rec_x, center_of_rec_y) rx = -(weight_v[0] * 0.5) ry = -(weight_v[1]) painter.rotate(-link_paint.angle()) new_rec = QRect(rx, ry, weight_v[0], 2 * weight_v[1]) if self.link._failed: painter.setBrush(QBrush(Qt.red, Qt.SolidPattern)) elif option.state & QtWidgets.QStyle.State_Selected: pass painter.setBrush(QBrush(Qt.black, Qt.SolidPattern)) painter.setPen(QtGui.QPen(Qt.black, Qt.SolidLine)) painter.drawRect(QRect(rx, ry, weight_v[0], 2 * weight_v[1])) painter.setFont(QFont(self.font_family, self.font_size / 3.3)) painter.setPen(QPen(Qt.white, Qt.SolidLine)) if self.show_latency: painter.drawText( new_rec, Qt.AlignCenter, str(self.link.metric) + " -- " + str(self.link.latency) + "/ms", ) else: painter.drawText(new_rec, Qt.AlignCenter, str(self.link.metric)) painter.restore() painter.restore()
def rotate_to_point(self, point): '''point: QPointF''' ln = QLineF(self.pos(), point) # that 90 is because sprite sheet is pointing north self.setRotation(-1 * ln.angle() + 90)
def calcArrow(srcdes_list, itemignoreZooming, iconScale): ''' if PoolItem then boundingrect should be background rather than graphicsobject ''' src = srcdes_list[0] des = srcdes_list[1] endtype = srcdes_list[2] order = srcdes_list[3] # print("Source => ", src) compartment = src.parentItem() srcobj = src.gobj desobj = des.gobj if isinstance(src, PoolItem): srcobj = src.bg if isinstance(des, PoolItem): desobj = des.bg # if itemignoreZooming: # srcRect = self.recalcSceneBoundingRect(srcobj) # desRect = self.recalcSceneBoundingRect(desobj) # else: srcRect = compartment.mapFromScene( srcobj.sceneBoundingRect()).boundingRect() desRect = compartment.mapFromScene( desobj.sceneBoundingRect()).boundingRect() arrow = QPolygonF() if srcRect.intersects(desRect): ''' This is created for getting a emptyline reference \ because 'lineCord' function keeps a reference between qgraphicsline and its src and des ''' arrow.append(QPointF(0, 0)) arrow.append(QPointF(0, 0)) return arrow if (order == 0): tmpLine = QLineF(srcRect.center().x(), srcRect.center().y(), desRect.center().x(), desRect.center().y()) elif (order > 0): dx = desRect.center().x() - srcRect.center().x() dy = desRect.center().y() - srcRect.center().y() dx0 = dy dy0 = -dx tetha1 = (atan2(dy0, dx0)) a0 = 4 * (cos(tetha1)) b0 = 4 * (sin(tetha1)) ''' Higher order ( > 4) connectivity will not be done''' if ((order == 3) or (order == 4)): a0 = a0 * 2 b0 = b0 * 2 if (order % 2 == 0): srcCentera0 = srcRect.center().x() - a0 srcCenterb0 = srcRect.center().y() - b0 desCentera0 = desRect.center().x() - a0 desCenterb0 = desRect.center().y() - b0 else: srcCentera0 = srcRect.center().x() + a0 srcCenterb0 = srcRect.center().y() + b0 desCentera0 = desRect.center().x() + a0 desCenterb0 = desRect.center().y() + b0 pointa = QPointF(srcCentera0, srcCenterb0) pointb = QPointF(desCentera0, desCenterb0) tmpLine = QLineF(srcCentera0, srcCenterb0, desCentera0, desCenterb0) srcIntersects, lineSrcPoint = calcLineRectIntersection(srcRect, tmpLine) destIntersects, lineDestPoint = calcLineRectIntersection(desRect, tmpLine) if not srcIntersects: print 'Source does not intersect line. Arrow points:', lineSrcPoint, src.mobj.name, src.mobj.className if not destIntersects: print 'Dest does not intersect line. Arrow points:', lineDestPoint, des.mobj.name, des.mobj.className '''src and des are connected with line co-ordinates Arrow head is drawned if the distance between src and des line is >8 just for clean appeareance ''' if (abs(lineSrcPoint.x() - lineDestPoint.x()) > 8 or abs(lineSrcPoint.y() - lineDestPoint.y()) > 8): srcAngle = tmpLine.angle() if endtype == 'p' or endtype == 'stp': ''' Arrow head for Destination is calculated''' arrow.append(lineSrcPoint) arrow.append(lineDestPoint) degree = -60 srcXArr1, srcYArr1 = arrowHead(srcAngle, degree, lineDestPoint, iconScale) arrow.append(QPointF(srcXArr1, srcYArr1)) arrow.append(QPointF(lineDestPoint.x(), lineDestPoint.y())) degree = -120 srcXArr2, srcYArr2 = arrowHead(srcAngle, degree, lineDestPoint, iconScale) arrow.append(QPointF(srcXArr2, srcYArr2)) arrow.append(QPointF(lineDestPoint.x(), lineDestPoint.y())) elif endtype == 'st': ''' Arrow head for Source is calculated''' arrow.append(lineDestPoint) arrow.append(lineSrcPoint) degree = 60 srcXArr2, srcYArr2 = arrowHead(srcAngle, degree, lineSrcPoint, iconScale) arrow.append(QPointF(srcXArr2, srcYArr2)) arrow.append(QPointF(lineSrcPoint.x(), lineSrcPoint.y())) degree = 120 srcXArr1, srcYArr1 = arrowHead(srcAngle, degree, lineSrcPoint, iconScale) arrow.append(QPointF(srcXArr1, srcYArr1)) arrow.append(QPointF(lineSrcPoint.x(), lineSrcPoint.y())) elif endtype == 's' or endtype == 'sts': arrow.append(lineDestPoint) arrow.append(lineSrcPoint) degree = 60 srcXArr2, srcYArr2 = arrowHead(srcAngle, degree, lineSrcPoint, iconScale) arrow.append(QPointF(srcXArr2, srcYArr2)) arrow.append(QPointF(lineSrcPoint.x(), lineSrcPoint.y())) degree = 120 srcXArr1, srcYArr1 = arrowHead(srcAngle, degree, lineSrcPoint, iconScale) arrow.append(QPointF(srcXArr1, srcYArr1)) arrow.append(QPointF(lineSrcPoint.x(), lineSrcPoint.y())) else: arrow.append(lineSrcPoint) arrow.append(lineDestPoint) return arrow