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)
Exemple #3
0
    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