def paint(self, painter, option, widget=None): color, _ = Edge.Color.SELECTED if self.selected else Edge.Color.DEFAULT pen = self.pen() pen.setColor(color) pen.setBrush(QBrush(color)) pen.setWidth(np.clip(2 * self.weight(), .5, 4)) painter.setPen(pen) self.setPen(pen) if self.source == self.dest: return self.paintArc(painter, option, widget) if self.source.collidesWithItem(self.dest): return have_two_edges = len([ edge for edge in self.source.edges if self.source in edge and self.dest in edge and edge is not self ]) source_pos = self.source.pos() dest_pos = self.dest.pos() color = self.pen().color() painter.setBrush(color) point = shape_line_intersection(self.dest.shape(), dest_pos, QLineF(source_pos, dest_pos)) line = QLineF(source_pos, point) if have_two_edges: normal = line.normalVector() normal.setLength(15) line = QLineF(normal.p2(), point) self.label.setPos(line.pointAt(.5)) self.squares.placeBelow(self.label) self.setLine(line) painter.drawLine(line) # Draw arrow head self.arrowHead.clear() for point in self._arrowhead_points(line): self.arrowHead.append(point) painter.drawPolygon(self.arrowHead)
def paint(self, painter, option, widget=None): color, _ = Edge.Color.SELECTED if self.selected else Edge.Color.DEFAULT pen = self.pen() pen.setColor(color) pen.setBrush(QBrush(color)) pen.setWidth(np.clip(2 * self.weight(), .5, 4)) painter.setPen(pen) self.setPen(pen) if self.source == self.dest: return self.paintArc(painter, option, widget) if self.source.collidesWithItem(self.dest): return have_two_edges = len([edge for edge in self.source.edges if self.source in edge and self.dest in edge and edge is not self]) source_pos = self.source.pos() dest_pos = self.dest.pos() color = self.pen().color() painter.setBrush(color) point = shape_line_intersection(self.dest.shape(), dest_pos, QLineF(source_pos, dest_pos)) line = QLineF(source_pos, point) if have_two_edges: normal = line.normalVector() normal.setLength(15) line = QLineF(normal.p2(), point) self.label.setPos(line.pointAt(.5)) self.squares.placeBelow(self.label) self.setLine(line) painter.drawLine(line) # Draw arrow head self.arrowHead.clear() for point in self._arrowhead_points(line): self.arrowHead.append(point) painter.drawPolygon(self.arrowHead)
def render(o): path = QPainterPath() # unit_x gives offset and direction of the x base vector. Start and end should be the grid points. # move the endpoints inwards an unnoticable bit, so that the intersection detector # won't trip on the common endpoint. u_x = QLineF(o.unit_x.pointAt(0.0001), o.unit_x.pointAt(0.9999)) path.moveTo(u_x.p1()) if o.is_straight: path.lineTo(u_x.p2()) return path if o.flipped: u_x = QLineF(u_x.p2(), u_x.p1()) u_y = u_x.normalVector() # move y unit to start at (0,0). u_y.translate(-u_y.p1()) scaling = o.length_base / u_x.length() * o.size_correction if o.basewidth * scaling > 0.8: # Plug is too large for the edge length. Make it smaller. scaling = 0.8 / o.basewidth # some magic numbers here... carefully fine-tuned, better leave them as they are. ends_ctldist = 0.4 #base_lcdist = 0.1 * scaling base_ucdist = 0.05 * scaling knob_lcdist = 0.6 * o.knobsize * scaling knob_ucdist = 0.8 * o.knobsize * scaling # set up piece -- here is where the really interesting stuff happens. # We will work from the ends inwards, so that symmetry counterparts are adjacent. # The QLine.pointAt function is used to transform everything into the coordinate # space defined by the us. # -- end points r1y = ends_ctldist * o.basepos * dsin(o.startangle) q6y = ends_ctldist * (1. - o.basepos) * dsin(o.endangle) p1 = u_x.p1() p6 = u_x.p2() r1 = u_x.pointAt( ends_ctldist * o.basepos * dcos(o.startangle)) + u_y.pointAt(r1y) q6 = u_x.pointAt(1. - ends_ctldist * (1. - o.basepos) * dcos(o.endangle)) + u_y.pointAt(q6y) # -- base points p2x = o.basepos - 0.5 * o.basewidth * scaling p5x = o.basepos + 0.5 * o.basewidth * scaling if p2x < 0.1 or p5x > 0.9: # knob to large. center knob on the edge. (o.basewidth * scaling < 0.8 -- see above) p2x = 0.5 - 0.5 * o.basewidth * scaling p5x = 0.5 + 0.5 * o.basewidth * scaling #base_y = r1y > q6y ? r1y : q6y #base_y = 0.5*(r1y + q6y) base_y = -o.baseroundness * ends_ctldist * min(p2x, 1. - p5x) if base_y > 0: base_y = 0 base_lcy = base_y * 2.0 base_y += base_ucdist / 2 base_lcy -= base_ucdist / 2 #base_lcy = r1y #if (q6y < r1y): base_lcy = q6y # at least -base_ucdist from base_y #if (base_lcy > base_y - base_ucdist): base_lcy = base_y-base_ucdist q2 = u_x.pointAt(p2x) + u_y.pointAt(base_lcy) r5 = u_x.pointAt(p5x) + u_y.pointAt(base_lcy) p2 = u_x.pointAt(p2x) + u_y.pointAt(base_y) p5 = u_x.pointAt(p5x) + u_y.pointAt(base_y) r2 = u_x.pointAt(p2x) + u_y.pointAt(base_y + base_ucdist) q5 = u_x.pointAt(p5x) + u_y.pointAt(base_y + base_ucdist) if o._is_plugless: if not o.flipped: path.cubicTo(r1, q2, p2) path.cubicTo(r2, q5, p5) path.cubicTo(r5, q6, p6) else: path.cubicTo(q6, r5, p5) path.cubicTo(q5, r2, p2) path.cubicTo(q2, r1, p1) return path # -- knob points p3x = p2x - o.knobsize * scaling * dsin(o.knobangle - o.knobtilt) p4x = p5x + o.knobsize * scaling * dsin(o.knobangle + o.knobtilt) # for the y coordinate, knobtilt sign was swapped. Knobs look better this way... # like x offset from base points y, but that is 0. p3y = o.knobsize * scaling * dcos(o.knobangle + o.knobtilt) + base_y p4y = o.knobsize * scaling * dcos(o.knobangle - o.knobtilt) + base_y q3 = u_x.pointAt(p3x) + u_y.pointAt(p3y - knob_lcdist) r4 = u_x.pointAt(p4x) + u_y.pointAt(p4y - knob_lcdist) p3 = u_x.pointAt(p3x) + u_y.pointAt(p3y) p4 = u_x.pointAt(p4x) + u_y.pointAt(p4y) r3 = u_x.pointAt(p3x) + u_y.pointAt(p3y + knob_ucdist) q4 = u_x.pointAt(p4x) + u_y.pointAt(p4y + knob_ucdist) # done setting up. construct path. # if flipped, add points in reverse. if not o.flipped: path.cubicTo(r1, q2, p2) path.cubicTo(r2, q3, p3) path.cubicTo(r3, q4, p4) path.cubicTo(r4, q5, p5) path.cubicTo(r5, q6, p6) else: path.cubicTo(q6, r5, p5) path.cubicTo(q5, r4, p4) path.cubicTo(q4, r3, p3) path.cubicTo(q3, r2, p2) path.cubicTo(q2, r1, p1) return path