def setObjectRadius(self, radius): """ TOWRITE :param `radius`: TOWRITE :type `radius`: qreal """ # qreal rad; if radius <= 0: rad = 0.0000001 else: rad = radius center = self.scenePos() # QPointF startLine = QLineF(center, self.objectStartPoint()) # QLineF midLine = QLineF(center, self.objectMidPoint()) # QLineF endLine = QLineF(center, self.objectEndPoint()) # QLineF startLine.setLength(rad) midLine.setLength(rad) endLine.setLength(rad) arcStartPoint = startLine.p2() arcMidPoint = midLine.p2() arcEndPoint = endLine.p2() self.calculateArcData(arcStartPoint.x(), arcStartPoint.y(), arcMidPoint.x(), arcMidPoint.y(), arcEndPoint.x(), arcEndPoint.y())
def mouseSnapPoint(self, mousePoint): """ Returns the closest snap point to the mouse point. :param `mousePoint`: TOWRITE :type `mousePoint`: `QPointF`_ :rtype: `QPointF`_ """ center = self.objectCenter() # QPointF quad0 = self.objectQuadrant0() # QPointF quad90 = self.objectQuadrant90() # QPointF quad180 = self.objectQuadrant180() # QPointF quad270 = self.objectQuadrant270() # QPointF cntrDist = QLineF(mousePoint, center).length() # qreal q0Dist = QLineF(mousePoint, quad0).length() # qreal q90Dist = QLineF(mousePoint, quad90).length() # qreal q180Dist = QLineF(mousePoint, quad180).length() # qreal q270Dist = QLineF(mousePoint, quad270).length() # qreal minDist = qMin(qMin(qMin(q0Dist, q90Dist), qMin(q180Dist, q270Dist)), cntrDist) # qreal if minDist == cntrDist: return center elif minDist == q0Dist: return quad0 elif minDist == q90Dist: return quad90 elif minDist == q180Dist: return quad180 elif minDist == q270Dist: return quad270 return self.scenePos()
def mouseSnapPoint(self, mousePoint): """ Returns the closest snap point to the mouse point. :param `mousePoint`: TOWRITE :type `mousePoint`: `QPointF`_ :rtype: `QPointF`_ """ center = self.objectCenter() # QPointF start = self.objectStartPoint() # QPointF mid = self.objectMidPoint() # QPointF end = self.objectEndPoint() # QPointF cntrDist = QLineF(mousePoint, center).length() # qreal startDist = QLineF(mousePoint, start).length() # qreal midDist = QLineF(mousePoint, mid).length() # qreal endDist = QLineF(mousePoint, end).length() # qreal minDist = qMin(qMin(cntrDist, startDist), qMin(midDist, endDist)) # qreal if minDist == cntrDist: return center elif minDist == startDist: return start elif minDist == midDist: return mid elif minDist == endDist: return end return self.scenePos()
def mouseSnapPoint(self, mousePoint): """ Returns the closest snap point to the mouse point. :param `mousePoint`: TOWRITE :type `mousePoint`: `QPointF`_ :rtype: `QPointF`_ """ ptl = self.objectTopLeft() # QPointF # Top Left Corner QSnap ptr = self.objectTopRight() # QPointF # Top Right Corner QSnap pbl = self.objectBottomLeft() # QPointF # Bottom Left Corner QSnap pbr = self.objectBottomRight() # QPointF # Bottom Right Corner QSnap ptlDist = QLineF(mousePoint, ptl).length() # qreal ptrDist = QLineF(mousePoint, ptr).length() # qreal pblDist = QLineF(mousePoint, pbl).length() # qreal pbrDist = QLineF(mousePoint, pbr).length() # qreal minDist = qMin(qMin(ptlDist, ptrDist), qMin(pblDist, pbrDist)) # qreal if minDist == ptlDist: return ptl elif minDist == ptrDist: return ptr elif minDist == pblDist: return pbl elif minDist == pbrDist: return pbr return self.scenePos()
def mouseSnapPoint(self, mousePoint): """ Returns the closest snap point to the mouse point. :param `mousePoint`: TOWRITE :type `mousePoint`: `QPointF`_ :rtype: `QPointF`_ """ endPoint1 = self.objectEndPoint1() # QPointF endPoint2 = self.objectEndPoint2() # QPointF midPoint = self.objectMidPoint() # QPointF end1Dist = QLineF(mousePoint, endPoint1).length() # qreal end2Dist = QLineF(mousePoint, endPoint2).length() # qreal midDist = QLineF(mousePoint, midPoint).length() # qreal minDist = qMin(end1Dist, end2Dist) # qreal if self.curved: minDist = qMin(minDist, midDist) if minDist == end1Dist: return endPoint1 elif minDist == end2Dist: return endPoint2 elif minDist == midDist: return midPoint return self.scenePos()
def _draw_reticle(self): if self._reticle is None or (self._reticle.size() != self.size()): self._new_reticle() dbm_lines = [ QLineF(self._hz_to_x(self._low_frequency), self._dbm_to_y(dbm), self._hz_to_x(self._high_frequency), self._dbm_to_y(dbm)) for dbm in numpy.arange(self._low_dbm, self._high_dbm, 20.0) ] dbm_labels = [ (dbm, QPointF( self._hz_to_x(self._low_frequency) + 2, self._dbm_to_y(dbm) - 2)) for dbm in numpy.arange(self._low_dbm, self._high_dbm, 20.0) ] frequency_lines = [ QLineF(self._hz_to_x(frequency), self._dbm_to_y(self._high_dbm), self._hz_to_x(frequency), self._dbm_to_y(self._low_dbm)) for frequency in numpy.arange(self._low_frequency, self._high_frequency, self._frequency_step * 10.0) ] frequency_labels = [(frequency, QPointF( self._hz_to_x(frequency) + 2, self._dbm_to_y(self._high_dbm) + 10)) for frequency in numpy.arange( self._low_frequency, self._high_frequency, self._frequency_step * 10.0)] painter = QtGui.QPainter(self._reticle) try: painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setPen(Qt.blue) # TODO: Removed to support old (<1.0) PySide API in Ubuntu 10.10 #painter.drawLines(dbm_lines) for dbm_line in dbm_lines: painter.drawLine(dbm_line) # TODO: Removed to support old (<1.0) PySide API in Ubuntu 10.10 #painter.drawLines(frequency_lines) for frequency_line in frequency_lines: painter.drawLine(frequency_line) painter.setPen(Qt.white) for dbm, point in dbm_labels: painter.drawText(point, '%+.0f' % dbm) for frequency, point in frequency_labels: painter.drawText(point, '%.0f' % (frequency / 1e6)) finally: painter.end()
def find_axis(top_line, bot_line): type, origin = top_line.intersect(bot_line) # Force angles into right half-plane regardless of click order top_angle = (top_line.angle() + 90) % 180 - 90 bot_angle = (bot_line.angle() + 90) % 180 - 90 xaxis = QLineF(origin, QPointF(0, 0)) # Need to make non-zero vector xaxis.setLength(100) xaxis.setAngle((top_angle + bot_angle) / 2) yaxis = QLineF(xaxis) yaxis.setAngle(xaxis.angle() + 90) return origin, xaxis, yaxis
def updateRubber(self, painter): """ TOWRITE :param `painter`: TOWRITE :type `painter`: `QPainter`_ """ rubberMode = self.objectRubberMode() # int if rubberMode == OBJ_RUBBER_LINE: sceneStartPoint = self.objectRubberPoint("LINE_START") # QPointF sceneQSnapPoint = self.objectRubberPoint("LINE_END") # QPointF self.setObjectEndPoint1(sceneStartPoint) self.setObjectEndPoint2(sceneQSnapPoint) self.drawRubberLine(self.line(), painter, VIEW_COLOR_CROSSHAIR) elif rubberMode == OBJ_RUBBER_GRIP: if painter: gripPoint = self.objectRubberPoint("GRIP_POINT") # QPointF if gripPoint == self.objectEndPoint1(): painter.drawLine(self.line().p2(), self.mapFromScene(self.objectRubberPoint(''))) elif gripPoint == objectEndPoint2(): painter.drawLine(self.line().p1(), self.mapFromScene(self.objectRubberPoint(''))) elif gripPoint == objectMidPoint(): painter.drawLine(self.line().translated(self.mapFromScene(self.objectRubberPoint('')) - self.mapFromScene(gripPoint))) rubLine = QLineF(self.mapFromScene(gripPoint), self.mapFromScene(self.objectRubberPoint(''))) self.drawRubberLine(rubLine, painter, VIEW_COLOR_CROSSHAIR)
def objectChord(self): """ TOWRITE :rtype: qreal """ return QLineF(self.objectStartX(), self.objectStartY(), self.objectEndX(), self.objectEndY()).length()
def __init__(self, parent=None): """ Default class constructor. :param `parent`: Pointer to a parent widget instance. :type `parent`: `QGraphicsItem`_ """ super(BaseObject, self).__init__(parent) qDebug("BaseObject Constructor()") self.objPen = QPen() # QPen objPen; self.lwtPen = QPen() # QPen lwtPen; self.objLine = QLineF() # QLineF objLine; self.objRubberMode = int() # int objRubberMode; self.objRubberPoints = {} # QHash<QString, QPointF> objRubberPoints; self.objRubberTexts = {} # QHash<QString, QString> objRubberTexts; self.objID = int() # qint64 objID; self.objPen.setCapStyle(Qt.RoundCap) self.objPen.setJoinStyle(Qt.RoundJoin) self.lwtPen.setCapStyle(Qt.RoundCap) self.lwtPen.setJoinStyle(Qt.RoundJoin) self.objID = QDateTime.currentMSecsSinceEpoch()
def calculateArcData(self, startX, startY, midX, midY, endX, endY): """ TOWRITE :param `startX`: TOWRITE :type `startX`: qreal :param `startY`: TOWRITE :type `startY`: qreal :param `midX`: TOWRITE :type `midX`: qreal :param `midY`: TOWRITE :type `midY`: qreal :param `endX`: TOWRITE :type `endX`: qreal :param `endY`: TOWRITE :type `endY`: qreal """ #TODO/PORT# double centerX; #TODO/PORT# double centerY; #TODO/PORT# getArcCenter(startX, startY, #TODO/PORT# midX, midY, #TODO/PORT# endX, endY, #TODO/PORT# ¢erX, ¢erY); arcStartPoint = QPointF(startX - centerX, startY - centerY) arcMidPoint = QPointF(midX - centerX, midY - centerY) arcEndPoint = QPointF(endX - centerX, endY - centerY) self.setPos(centerX, centerY) radius = QLineF(centerX, centerY, midX, midY).length() # qreal self.updateArcRect(radius) self.updatePath() self.setRotation(0) self.setScale(1)
def updateRubber(self, painter=None): """ TOWRITE :param `painter`: TOWRITE :type `painter`: `QPainter`_ """ rubberMode = self.objectRubberMode() # int if rubberMode == OBJ_RUBBER_TEXTSINGLE: self.setObjectTextFont(self.objectRubberText("TEXT_FONT")) self.setObjectTextJustify(self.objectRubberText("TEXT_JUSTIFY")) self.setObjectPos(self.objectRubberPoint("TEXT_POINT")) hr = self.objectRubberPoint("TEXT_HEIGHT_ROTATION") # QPointF self.setObjectTextSize(hr.x()) self.setRotation(hr.y()) self.setObjectText(self.objectRubberText("TEXT_RAPID")) elif rubberMode == OBJ_RUBBER_GRIP: if painter: gripPoint = self.objectRubberPoint("GRIP_POINT") # QPointF if gripPoint == self.scenePos(): painter.drawPath(self.objectPath().translated( self.mapFromScene(self.objectRubberPoint("")) - self.mapFromScene(gripPoint))) rubLine = QLineF(self.mapFromScene(gripPoint), self.mapFromScene(self.objectRubberPoint(""))) self.drawRubberLine(rubLine, painter, "VIEW_COLOR_CROSSHAIR")
def __init__(self, x1, y1, x2, y2, text, obj, v, parent=None): """ Default class constructor. :param `x1`: TOWRITE :type `x1`: qreal :param `y1`: TOWRITE :type `y1`: qreal :param `x2`: TOWRITE :type `x2`: qreal :param `y2`: TOWRITE :type `y2`: qreal :param `text`: TOWRITE :type `text`: QString :param `obj`: TOWRITE :type `obj`: `BaseObject` :param `v`: TOWRITE :type `v`: `View` :param `parent`: TOWRITE :type `parent`: `QUndoCommand`_ """ super(UndoableMirrorCommand, self).__init__(parent) self.gview = v self.object = obj self.setText(text) self.mirrorLine = QLineF(x1, y1, x2, y2)
def updateLines(self): pen = QPen(QColor.fromHsl(0, 100, 100)) sortedNodes = sorted(self.nodes, key=lambda x: x.pos().x()) for index in range(len(self.nodes) - 1): node = sortedNodes[index] nextNode = sortedNodes[index + 1] if index < len(self.lines): # Just update the line segment lineItem = self.lines[index] else: # Create a new line segment lineItem = QGraphicsLineItem() lineItem.setZValue(250) lineItem.setPen(pen) self.histogramWidget.scene().addItem(lineItem) self.lines.append(lineItem) line = QLineF(node.pos(), nextNode.pos()) lineItem.setLine(line) # Clean up redundent lines if len(self.lines) >= len(self.nodes): # Remove the redundant line segments from the scene for index in range(len(self.nodes) - 1, len(self.lines)): lineItem = self.lines[index] self.histogramWidget.scene().removeItem(lineItem) # Delete the line segments from the list del self.lines[len(self.nodes) - 1:] assert len(self.lines) == len(self.nodes) - 1 self.histogramWidget._scene.update()
def triangle_from_lines(lines): vertices, sides = [], [] for line_pair in combinations(lines, 2): type, point = line_pair[0].intersect(line_pair[1]) vertices.append(point) for vert_pair in combinations(vertices, 2): sides.append(QLineF(vert_pair[0], vert_pair[1])) return vertices, sides
def ruler(self): # All points for this mode are grouped into pairs px_lens = [QLineF(pt[0], pt[1]).length() for pt in self.pts] px_ruler_len = px_lens.pop(-1) mm_ruler_len = 9.0 scale = mm_ruler_len / px_ruler_len print("Side len: {:.2f} mm".format(px_lens[0] * scale)) print("Top len: {:.2f} mm".format(px_lens[1] * scale)) print("Bot len: {:.2f} mm".format(px_lens[2] * scale))
def find_rel_coords(line, origin, xaxis, yaxis): copy = QLineF(line) line.setLength(line.length() / 2.0) midpoint = line.p2() x = midpoint.x() - origin.x() y = midpoint.y() - origin.y() angle = line.angle() % 180 - yaxis.angle( ) # Force line's angle into upper half-plane return x, y, angle
def renewplot(self): """ Do not layout anything, but redraw all lines""" scene = self.graphicsView.scene() self.roots = set() # scene.changed.disconnect(self.renewplot) for i in self.qLines: scene.removeItem(i) self.qLines = [] for edge in self.gv.edges_iter(): qnode1 = self.nodesToQNodes[edge[0]] qnode2 = self.nodesToQNodes[edge[1]] line = QLineF(qnode1.pos(), qnode2.pos()) line.setLength(line.length() - 40) end = line.p2() arrowLine1 = QLineF() arrowLine1.setP1(end) arrowLine1.setLength(10) arrowLine1.setAngle(line.angle() + 210) arrowLine2 = QLineF() arrowLine2.setP1(end) arrowLine2.setLength(10) arrowLine2.setAngle(line.angle() - 210) if edge.attr['color'] not in self.qpens: self.qpens[edge.attr['color']] = QPen( QColor(edge.attr['color'])) item = scene.addLine(line, self.qpens[edge.attr['color']]) item.setZValue(-1) item.setFlag(QGraphicsItem.ItemIsSelectable, True) self.qLines.append(item) item = scene.addLine(arrowLine1, self.qpens[edge.attr['color']]) self.qLines.append(item) item = scene.addLine(arrowLine2, self.qpens[edge.attr['color']]) self.qLines.append(item) self.roots.add(edge[0])
def orthic_triangle(vertices): # Points projected normally onto the opposite side pts, sides = [], [] for i in range(3): # Rotate the list of vertices v1, v2, v3 = vertices[i:] + vertices[:i] dv = v2 - v1 xhat = dv / mag(dv) pts.append(v1 + dot((v3 - v1), xhat) * xhat) for vert_pair in combinations(pts, 2): sides.append(QLineF(vert_pair[0], vert_pair[1])) return pts, sides
def objectEndAngle(self): """ TOWRITE :rtype: qreal """ angle = QLineF(self.scenePos(), self.objectEndPoint()).angle() # qreal while angle >= 360.0: angle -= 360.0 while angle < 0.0: angle += 360.0 return angle
def mouseSnapPoint(self, mousePoint): """ Returns the closest snap point to the mouse point. :param `mousePoint`: TOWRITE :type `mousePoint`: `QPointF`_ :rtype: `QPointF`_ """ element = self.normalPath.elementAt(0) # QPainterPath::Element closestPoint = self.mapToScene(QPointF(element.x, element.y)) # QPointF closestDist = QLineF(mousePoint, closestPoint).length() # qreal elemCount = self.normalPath.elementCount() # int for i in range(0, elemCount): # for(int i = 0; i < elemCount; ++i) element = self.normalPath.elementAt(i) elemPoint = self.mapToScene(element.x, element.y) # QPointF elemDist = QLineF(mousePoint, elemPoint).length() # qreal if elemDist < closestDist: closestPoint = elemPoint closestDist = elemDist return closestPoint
def gripEdit(self, before, after): """ TOWRITE :param `before`: TOWRITE :type `before`: `QPointF`_ :param `after`: TOWRITE :type `after`: `QPointF`_ """ if before == self.objectCenter(): delta = QPointF(after - before) self.moveBy(delta.x(), delta.y()) else: self.setObjectRadius(QLineF(self.objectCenter(), after).length())
def __init__(self, x, y, scaleFactor, text, obj, v, parent): """ Default class constructor. :param `x`: TOWRITE :type `x`: qreal :param `y`: TOWRITE :type `y`: qreal :param `scaleFactor`: TOWRITE :type `scaleFactor`: qreal :param `text`: TOWRITE :type `text`: QString :param `obj`: TOWRITE :type `obj`: `BaseObject` :param `v`: TOWRITE :type `v`: `View` :param `parent`: TOWRITE :type `parent`: `QUndoCommand`_ """ super(UndoableScaleCommand, self).__init__(parent) self.gview = v self.object = obj self.setText(text) # Prevent division by zero and other wacky behavior if scaleFactor <= 0.0: self.dx = 0.0 self.dy = 0.0 self.factor = 1.0 QMessageBox.critical( 0, QObject.tr("ScaleFactor Error"), QObject. tr("Hi there. If you are not a developer, report this as a bug. " "If you are a developer, your code needs examined, and possibly your head too." )) else: # Calculate the offset oldX = self.object.x() # qreal oldY = self.object.y() # qreal scaleLine = QLineF(x, y, oldX, oldY) scaleLine.setLength(scaleLine.length() * scaleFactor) newX = scaleLine.x2() # qreal newY = scaleLine.y2() # qreal self.dx = newX - oldX self.dy = newY - oldY self.factor = scaleFactor
def updateRubber(self, painter): """ TOWRITE :param `painter`: TOWRITE :type `painter`: `QPainter`_ """ rubberMode = self.objectRubberMode() # int if rubberMode == OBJ_RUBBER_GRIP: if painter: gripPoint = self.objectRubberPoint("GRIP_POINT") # QPointF if gripPoint == self.scenePos(): rubLine = QLineF( self.mapFromScene(gripPoint), self.mapFromScene(self.objectRubberPoint(''))) self.drawRubberLine(rubLine, painter, VIEW_COLOR_CROSSHAIR)
def updateRubber(self, painter): """ TOWRITE :param `painter`: TOWRITE :type `painter`: `QPainter`_ """ rubberMode = self.objectRubberMode() # int if rubberMode == OBJ_RUBBER_RECTANGLE: sceneStartPoint = self.objectRubberPoint( "RECTANGLE_START") # QPointF sceneEndPoint = self.objectRubberPoint("RECTANGLE_END") # QPointF x = sceneStartPoint.x() # qreal y = sceneStartPoint.y() # qreal w = sceneEndPoint.x() - sceneStartPoint.x() # qreal h = sceneEndPoint.y() - sceneStartPoint.y() # qreal self.setObjectRect(x, y, w, h) self.updatePath() elif rubberMode == OBJ_RUBBER_GRIP: if painter: ### //TODO: Make this work with rotation & scaling ### /* ### QPointF gripPoint = objectRubberPoint("GRIP_POINT"); ### QPointF after = objectRubberPoint(QString()); ### QPointF delta = after-gripPoint; ### if (gripPoint == objectTopLeft()) { painter->drawPolygon(mapFromScene(QRectF(after.x(), after.y(), objectWidth()-delta.x(), objectHeight()-delta.y()))); } ### else if(gripPoint == objectTopRight()) { painter->drawPolygon(mapFromScene(QRectF(objectTopLeft().x(), objectTopLeft().y()+delta.y(), objectWidth()+delta.x(), objectHeight()-delta.y()))); } ### else if(gripPoint == objectBottomLeft()) { painter->drawPolygon(mapFromScene(QRectF(objectTopLeft().x()+delta.x(), objectTopLeft().y(), objectWidth()-delta.x(), objectHeight()+delta.y()))); } ### else if(gripPoint == objectBottomRight()) { painter->drawPolygon(mapFromScene(QRectF(objectTopLeft().x(), objectTopLeft().y(), objectWidth()+delta.x(), objectHeight()+delta.y()))); } ### ### QLineF rubLine(mapFromScene(gripPoint), mapFromScene(objectRubberPoint(QString()))); ### drawRubberLine(rubLine, painter, VIEW_COLOR_CROSSHAIR); ### */ gripPoint = self.objectRubberPoint("GRIP_POINT") # QPointF after = self.objectRubberPoint('') # QPointF delta = after - gripPoint # QPointF rubLine = QLineF(self.mapFromScene(gripPoint), self.mapFromScene(self.objectRubberPoint(''))) self.drawRubberLine(rubLine, painter, VIEW_COLOR_CROSSHAIR)
def testDrawOverloads(self): '''Calls QPainter.drawLines overloads, if something is wrong Exception and chaos ensues. Bug #395''' self.painter.drawLines([QLine(QPoint(0, 0), QPoint(1, 1))]) self.painter.drawLines([QPoint(0, 0), QPoint(1, 1)]) self.painter.drawLines([QPointF(0, 0), QPointF(1, 1)]) self.painter.drawLines([QLineF(QPointF(0, 0), QPointF(1, 1))]) self.painter.drawPoints([QPoint(0, 0), QPoint(1, 1)]) self.painter.drawPoints([QPointF(0, 0), QPointF(1, 1)]) self.painter.drawConvexPolygon([ QPointF(10.0, 80.0), QPointF(20.0, 10.0), QPointF(80.0, 30.0), QPointF(90.0, 70.0) ]) self.painter.drawConvexPolygon([ QPoint(10.0, 80.0), QPoint(20.0, 10.0), QPoint(80.0, 30.0), QPoint(90.0, 70.0) ]) self.painter.drawPolygon([ QPointF(10.0, 80.0), QPointF(20.0, 10.0), QPointF(80.0, 30.0), QPointF(90.0, 70.0) ]) self.painter.drawPolygon([ QPoint(10.0, 80.0), QPoint(20.0, 10.0), QPoint(80.0, 30.0), QPoint(90.0, 70.0) ]) self.painter.drawPolyline([ QPointF(10.0, 80.0), QPointF(20.0, 10.0), QPointF(80.0, 30.0), QPointF(90.0, 70.0) ]) self.painter.drawPolyline([ QPoint(10.0, 80.0), QPoint(20.0, 10.0), QPoint(80.0, 30.0), QPoint(90.0, 70.0) ])
def angle_arrow(self, path, origin='head'): ''' Compute the two points of the arrow head with the right angle ''' if origin == 'tail': path = path.toReversed() length = path.length() percent = path.percentAtLength(length - 10.0) src = path.pointAtPercent(percent) #path.moveTo(path.pointAtPercent(1)) end_point = path.pointAtPercent(1) #end_point = path.currentPosition() line = QLineF(src, end_point) angle = math.acos(line.dx() / (line.length() or 1)) if line.dy() >= 0: angle = math.pi * 2 - angle arrow_size = 10.0 arrow_p1 = end_point + QPointF( math.sin(angle - math.pi / 3) * arrow_size, math.cos(angle - math.pi / 3) * arrow_size) arrow_p2 = end_point + QPointF( math.sin(angle - math.pi + math.pi / 3) * arrow_size, math.cos(angle - math.pi + math.pi / 3) * arrow_size) return (arrow_p1, arrow_p2)
def tricavity(self, scale_triplet=None): # All points for this mode are grouped into pairs linesegs = [QLineF(pt[0], pt[1]) for pt in self.pts] # Calculate interesting things verts, sides = triangle_from_lines(linesegs) m_verts, m_sides = orthic_triangle(verts) origin, xaxis, yaxis = find_axis(linesegs[1], linesegs[2]) x, y, angle = find_rel_coords(linesegs[0], origin, xaxis, yaxis) if scale_triplet: scale = sum((mm / line.length() for (mm, line) in zip(scale_triplet, linesegs))) / 3.0 units = 'mm' else: scale = 1 units = 'px' # Draw 'cavity' triangle if 'cavity' in self.flags: for side in sides: self.draw_line(side) # Draw 'mode' triangle if 'mode' in self.flags: for side in m_sides: self.draw_line(side) if 'axis' in self.flags: self.draw_line(xaxis) self.draw_line(yaxis) if 'coords' in self.flags: print('x: {:.2f} {}'.format(x * scale, units)) print('y: {:.2f} {}'.format(y * scale, units)) print('angle: {:.2f} degrees'.format(angle))
def updateLeader(self): """ TOWRITE """ arrowStyle = Closed # int # TODO: Make this customizable arrowStyleAngle = 15.0 # qreal # TODO: Make this customizable arrowStyleLength = 1.0 # qreal # TODO: Make this customizable self.lineStyleAngle = 45.0 # qreal # TODO: Make this customizable self.lineStyleLength = 1.0 # qreal # TODO: Make this customizable lyne = self.line() # QLineF angle = lyne.angle() # qreal ap0 = lyne.p1() # QPointF lp0 = lyne.p2() # QPointF # Arrow lynePerp = QLineF(lyne.pointAt(arrowStyleLength / lyne.length()), lp0) lynePerp.setAngle(angle + 90) lyne1 = QLineF(ap0, lp0) lyne2 = QLineF(ap0, lp0) lyne1.setAngle(angle + arrowStyleAngle) lyne2.setAngle(angle - arrowStyleAngle) # ap1 = QPointF() # ap2 = QPointF() _, ap1 = lynePerp.intersect(lyne1) _, ap2 = lynePerp.intersect(lyne2) # Math Diagram # .(ap1) .(lp1) # /| /| # / | / | # / | / | # / | / | # / | / | # / | / | # / | / | # / | / | # /+(aSA) | /+(lSA) | # (ap0)./__(aSL)__|__________(lp0)./__(lSL)__| # \ -(aSA) | \ -(lSA) | # \ | \ | # \ | \ | # \ | \ | # \ | \ | # \ | \ | # \ | \ | # \ | \ | # \ | \ | # \| \| # .(ap2) .(lp2) if arrowStyle == Open: arrowStylePath = QPainterPath() arrowStylePath.moveTo(ap1) arrowStylePath.lineTo(ap0) arrowStylePath.lineTo(ap2) arrowStylePath.lineTo(ap0) arrowStylePath.lineTo(ap1) elif arrowStyle == Closed: arrowStylePath = QPainterPath() arrowStylePath.moveTo(ap1) arrowStylePath.lineTo(ap0) arrowStylePath.lineTo(ap2) arrowStylePath.lineTo(ap1) elif arrowStyle == Dot: arrowStylePath = QPainterPath() arrowStylePath.addEllipse(ap0, arrowStyleLength, arrowStyleLength) elif arrowStyle == Box: arrowStylePath = QPainterPath() side = QLineF(ap1, ap2).length() # qreal ar0 = QRectF(0, 0, side, side) ar0.moveCenter(ap0) arrowStylePath.addRect(ar0) elif arrowStyle == Tick: pass #TODO/PORT# Is this supposed to be empty? lineStylePath = QPainterPath() lineStylePath.moveTo(ap0) lineStylePath.lineTo(lp0)
def redraw(self, base_time, all_tars, employee_id, additional_work_timetracks, additional_presence_timetracks, special_activities=None, view_title=""): scene = QGraphicsScene() # This scene line is a hack to make sure I can control the "centerOn" # execution as I wish. This is very hackish. margin = 30 scene.addLine( QLineF(0, 0, self.width() - margin, self.height() - margin), QPen(Qt.white)) # Dat is heeeel belangerijk om de goede computation te doen all_tars = sorted(all_tars, key=lambda tar: tar.time) # chrono.chrono_click("Redraw step 1") timetracks_tars = dao.task_action_report_dao.compute_activity_timetracks_from_task_action_reports( all_tars, employee_id) # We got (timetrack, reports) tuples timetracks = [tt[0] for tt in timetracks_tars] # presence_time, off_time, presence_timetracks = dao.task_action_report_dao.recompute_presence_on_tars(employee_id, all_tars) # chrono.chrono_click("Redraw step 2") presence_intervals = dao.task_action_report_dao.compute_man_presence_periods( employee_id, base_time, all_tars, timetracks=[], commit=True) # chrono.chrono_click("Redraw step 2B") presence_timetracks = dao.task_action_report_dao.convert_intervals_to_presence_timetracks( presence_intervals, employee_id) # chrono.chrono_click("Redraw step 3") # FIXME this will trigger a session open... Must use the ID without a query first! presence_task_id = dao.task_action_report_dao.presence_task_id_regular_time( ) # chrono.chrono_click("redraw") # mainlog.debug("About to draw ...") # mainlog.debug("additional presence is") # for tt in additional_presence_timetracks: # mainlog.debug(tt) # mainlog.debug("all_tars") # mainlog.debug(all_tars) # mainlog.debug("Timetracks...") # mainlog.debug(timetracks_tars) # mainlog.debug("Presenec Timetracks...") # mainlog.debug(presence_timetracks) if presence_timetracks == [] and additional_presence_timetracks: presence_timetracks += additional_presence_timetracks timetracks += additional_work_timetracks # mainlog.debug("Augmented Timetracks...") # mainlog.debug(timetracks) # mainlog.debug("Augmented Presence Timetracks...") # for tt in presence_timetracks: # mainlog.debug(tt) y = 0 dy = 60 # Title of the view if view_title: description = QGraphicsSimpleTextItem() description.setText(view_title) description.setFont(self.title_font) br = QRect(0, 0, description.boundingRect().width(), description.boundingRect().height()) description.setPos(0, 0) # y - br.height()/2) scene.addItem(description) y += max(br.height() * 2, dy) # Presence timeline pointages = [] for tar in all_tars: # mainlog.debug(tar) # mainlog.debug(tar.kind == TaskActionReportType.presence) if tar.kind == TaskActionReportType.presence: pointages.append((tar.time, Timeline.NO_DIR, tar, self._hoover_text_for(tar))) elif tar.kind in (TaskActionReportType.day_in, TaskActionReportType.start_task): pointages.append((tar.time, Timeline.START, tar, self._hoover_text_for(tar))) elif tar.kind in (TaskActionReportType.day_out, TaskActionReportType.stop_task): pointages.append( (tar.time, Timeline.END, tar, self._hoover_text_for(tar))) else: raise Exception("Unsupported TAR.kind. I get {}".format( tar.kind)) periods = [] for tt in presence_timetracks: periods.append( (tt.start_time, tt.start_time + timedelta(tt.duration / 24.0), None)) # Show the presence timeline pointages_for_presence = [ p for p in pointages if p[2].kind not in (TaskActionReportType.start_task, TaskActionReportType.stop_task) ] if pointages_for_presence: tl = Timeline(base_time, pointages_for_presence, periods, None, _("Presence"), QColor(Qt.green).darker(150)) tl.draw(scene, y) y += dy # Special activities time line if special_activities: periods = [] for sa in special_activities: desc = None if sa.activity_type: desc = sa.activity_type.description periods.append((sa.start_time, sa.end_time, desc)) tl = Timeline(base_time, None, periods, None, _("Absence"), QColor(Qt.red).darker(150)) tl.draw(scene, y) y += dy # Group task action reports according to their task task_tar = dict() for tar in all_tars: task_id = tar.task_id if task_id and task_id != presence_task_id: if not task_id in task_tar: task_tar[task_id] = [] if tar.kind == TaskActionReportType.start_task: task_tar[task_id].append((tar.time, Timeline.START, tar, self._hoover_text_for(tar))) elif tar.kind == TaskActionReportType.stop_task: task_tar[task_id].append((tar.time, Timeline.END, tar, self._hoover_text_for(tar))) # Group timetracks according to their task task_to_timetracks = dict() for timetrack in timetracks: task_id = timetrack.task_id if task_id and task_id != presence_task_id: if not task_id in task_to_timetracks: task_to_timetracks[task_id] = [] task_to_timetracks[task_id].append(timetrack) # Figure out all the tasks (because each task gives a timeline) # It is quite possible that some timetracks are not associated # to any TAR and vice versa. all_tasks = set() for t in timetracks: if t.task_id: all_tasks.add(t.task_id) for t in all_tars: if t.task_id: all_tasks.add(t.task_id) all_tasks = dao.task_dao.find_by_ids_frozen(all_tasks) # map(lambda t:t.task and all_tasks.add(t.task),timetracks) # map(lambda t:t.task and all_tasks.add(t.task),all_tars) # The presence stuff was drawn on a separate timeline => we won't draw # it here again. # Remove presence task (because it's already drawn). # FIXME I use the ID because of session handling all_tasks = list( filter(lambda t: t.task_id != presence_task_id, all_tasks)) for task in list(sorted(all_tasks, key=lambda a: a.description)): # Not all TAR have a timetrack ! periods = [] if task.task_id in task_to_timetracks: for tt in task_to_timetracks[task.task_id]: periods.append( (tt.start_time, tt.start_time + timedelta(tt.duration / 24.0), None)) tars = [] if task.task_id in task_tar: tars = task_tar[task.task_id] timeline_title = task.description # timeline_title = self._make_time_line_title(task) # This will provide nice and complete bar titles if task.type == TaskOnOperation: tl = Timeline(base_time, tars, periods, task, timeline_title, Qt.blue) else: tl = Timeline(base_time, tars, periods, task, timeline_title, Qt.red) tl.draw(scene, y) y += dy self.setScene(scene) # See the hack top of this method ! self.centerOn(-(self.width() - margin) / 2, (self.height() - margin) / 2)