def draw_node(self, node: Node, painter): """Draw the specified node.""" painter.setBrush( QBrush( self.selected_color if node is self.selected_node else self.regular_node_color, Qt.SolidPattern, )) node_position = node.get_position() node_radius = Vector(node.get_radius()).repeat(2) painter.drawEllipse(QPointF(*node_position), *node_radius) if self.labels_checkbox.isChecked(): label = node.get_label() # scale font down, depending on the length of the label of the node painter.setFont( QFont(self.font_family, self.font_size / len(label))) # draw the node label within the node dimensions painter.drawText( QRectF(*(node_position - node_radius), *(2 * node_radius)), Qt.AlignCenter, label, )
def get_vertex_position(self, n1: Node, n2: Node) -> Tuple[Vector, Vector]: """Return the position of the vertex on the screen.""" # positions of the nodes n1_p = Vector(*n1.get_position()) n2_p = Vector(*n2.get_position()) # unit vector from n1 to n2 uv = (n2_p - n1_p).unit() # start and end of the vertex to be drawn start = n1_p + uv * n1.get_radius() end = n2_p - uv * n2.get_radius() if self.graph.is_directed(): # if the graph is directed and a vertex exists that goes the other way, we # have to move the start end end so the vertexes don't overlap if self.graph.does_vertex_exist(n2, n1): start = start.rotated(self.arrow_separation, n1_p) end = end.rotated(-self.arrow_separation, n2_p) return start, end
def get_vertex_weight_rect(self, n1: Node, n2: Node, weight: float): """Get a RectF surrounding the weight of the node.""" r = self.weight_rectangle_size # width adjusted to number of chars in weight label adjusted_width = len(str(weight)) / 3 * r + r / 3 weight_vector = Vector(r if adjusted_width <= r else adjusted_width, r) if n1 is n2: # special case for a vertex pointing to itself mid = n1.get_position() - Vector(r * 3, r * 4) else: start, end = self.get_vertex_position(n1, n2) mid = (start + end) / 2 return QRectF(*(mid - weight_vector), *(2 * weight_vector))
def draw_vertex(self, n1: Node, n2: Node, weight: float, painter): """Draw the specified vertex.""" # special case for a node pointing to itself if n1 is n2: r = n1.get_radius() x, y = n1.get_position() painter.setPen(QPen(Qt.black, Qt.SolidLine)) painter.setBrush(QBrush(Qt.black, Qt.NoBrush)) painter.drawEllipse(QPointF(x - r / 2, y - r), r / 2, r / 2) head = Vector(x, y) - Vector(0, r) uv = Vector(0, 1) painter.setBrush(QBrush(Qt.black, Qt.SolidPattern)) painter.drawPolygon( QPointF(*head), QPointF(*(head + (-uv).rotated(radians(10)) * self.arrowhead_size)), QPointF(*(head + (-uv).rotated(radians(-50)) * self.arrowhead_size)), ) else: start, end = self.get_vertex_position(n1, n2) # draw the head of a directed arrow, which is an equilateral triangle if self.graph.is_directed(): uv = (end - start).unit() painter.setBrush(QBrush(Qt.black, Qt.SolidPattern)) painter.drawPolygon( QPointF(*end), QPointF( *(end + (-uv).rotated(radians(30)) * self.arrowhead_size)), QPointF( *(end + (-uv).rotated(radians(-30)) * self.arrowhead_size)), ) painter.setPen(QPen(Qt.black, Qt.SolidLine)) painter.drawLine(QPointF(*start), QPointF(*end)) if self.graph.is_weighted(): # set color according to whether the vertex is selected or not painter.setBrush( QBrush( self.selected_color if self.selected_vertex is not None and ((n1 is self.selected_vertex[0] and n2 is self.selected_vertex[1]) or (not self.graph.is_directed() and n2 is self.selected_vertex[0] and n1 is self.selected_vertex[1])) else self.regular_vertex_weight_color, Qt.SolidPattern, )) weight_rectangle = self.get_vertex_weight_rect(n1, n2, weight) painter.drawRect(weight_rectangle) painter.setFont(QFont(self.font_family, int(self.font_size / 4))) painter.setPen(QPen(Qt.white, Qt.SolidLine)) painter.drawText(weight_rectangle, Qt.AlignCenter, str(weight)) painter.setPen(QPen(Qt.black, Qt.SolidLine))