def getPoints(self, count, opposite=False): result = [] line = QLineF(self.__polygon.boundingRect().topLeft(), self.__polygon.boundingRect().topRight()) if opposite: line = QLineF(self.__polygon.boundingRect().bottomLeft(), self.__polygon.boundingRect().bottomRight()) step = 1.0 / (count + 1) currentStep = step for x in range(0, count): result.append(line.pointAt(currentStep)) currentStep += step return result
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)
class Line( QGraphicsLineItem ): """Defines a line by two points. If points are moved, line follows these movements.""" def __init__( self, startPoint, endPoint, ccs, paintToBorder = False, showIncline = False, color = 'orange', minLength = 0 ): super( Line, self ).__init__( ccs ) self.startPoint = startPoint self.endPoint = endPoint self.ccs = ccs self.paintToBorder = paintToBorder self.showIncline = showIncline self.color = color self.visible = True # by default we only want to draw lines if its two # defining points are not too close together self.drawAlways = False self.minLength = minLength # pixel # grmbl. Line was designed to be defined by two Point.Points. Now I want to be able to define # lines as well from QPointFs. try: self.Rect = QRectF( self.startPoint.x, self.startPoint.y, self.endPoint.x, self.endPoint.y ) except: self.Rect = QRectF( self.startPoint.x(), self.startPoint.y(), self.endPoint.x(), self.endPoint.y() ) def boundingRect( self ): return self.Rect def paint( self, painter, option, widget=None ): if self.visible == True: painter.setPen( QColor( self.color ) ) # see try-catch (pardon me) above try: self.sp = CST.toCcsCoord( self.ccs, self.startPoint.x, self.startPoint.y ) self.ep = CST.toCcsCoord( self.ccs, self.endPoint.x, self.endPoint.y ) except: self.sp = CST.toCcsCoord( self.ccs, self.startPoint.x(), self.startPoint.y() ) self.ep = CST.toCcsCoord( self.ccs, self.endPoint.x(), self.endPoint.y() ) self.Rect = QRectF( self.sp, self.ep ) self.line = QLineF( self.sp, self.ep ) if self.line.length() > self.minLength or self.drawAlways == True: painter.drawLine( self.line ) if self.paintToBorder == True: # paint line to approximately the edge of the ccs. ep2 = self.line.pointAt( self.ccs.width / self.line.length() * 2) painter.drawLine(self.ep,ep2) sp2 = self.line.pointAt(-self.ccs.width / self.line.length() * 2) painter.drawLine(self.sp,sp2) if self.showIncline == True: incline = ( self.endPoint.y - self.startPoint.y ) / ( self.endPoint.x - self.startPoint.x ) # print text limited to 2 decimal digits. painter.setBackground ( QBrush ( QColor( 'lightGrey' ) ) ) painter.setBackgroundMode (Qt.BGMode(1)) painter.setPen( QColor( 'black' ) ) #~ painter.drawText( self.ep.x() + 10, self.ep.y() + 10, QString ( '%.2f' %(incline) ) ) def setVisible( self, value ): self.visible = value def setPosition( self, startPoint, endPoint ): self.startPoint = startPoint self.endPoint = endPoint def updateYourself( self, xDelta, yDelta ): # There is no action needed, as a line gets its information # from startPoint and endPoint # Just adjust self.Rect to avoid case where line disappears mysteriously and after then, # paint() is never called again self.Rect = QRectF( self.startPoint.x, self.startPoint.y, self.endPoint.x, self.endPoint.y )
def adjust(self): line = QLineF(self.mapFromItem(self.source, 0, 0), self.mapFromItem(self.dest, 0, 0)) self.label.setPos(line.pointAt(.5)) self.setLine(self.__transform().map(line))
def adjust(self): line = QLineF(self.source.pos(), self.dest.pos()) self.setLine(line) self.label.setPos( line.pointAt(.5) - self.label.boundingRect().center()) self.squares.placeBelow(self.label)
def __getSelectedCenter(self): tLine = QLineF(self.__selected.mapToScene(self.__selected.boundingRect().topLeft()), self.__selected.mapToScene(self.__selected.boundingRect().topRight())) return tLine.pointAt(0.5)
def adjust(self): line = QLineF(self.source.pos(), self.dest.pos()) self.setLine(line) self.label.setPos(line.pointAt(.5) - self.label.boundingRect().center()) self.squares.placeBelow(self.label)
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