! \internal Called by \ref draw to generate points in pixel coordinates which represent the line of the curve. Line segments that aren't visible in the current axis rect are handled in an optimized way. They are projected onto a rectangle slightly larger than the visible axis rect and simplified regarding point count. The algorithm makes sure to preserve appearance of lines and fills i
| 23066 | \see drawCurveLine, drawScatterPlot |
| 23067 | */ |
| 23068 | void QCPCurve::getCurveLines(QVector<QPointF> *lines, const QCPDataRange &dataRange, double penWidth) const |
| 23069 | { |
| 23070 | if (!lines) return; |
| 23071 | lines->clear(); |
| 23072 | QCPAxis *keyAxis = mKeyAxis.data(); |
| 23073 | QCPAxis *valueAxis = mValueAxis.data(); |
| 23074 | if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } |
| 23075 | |
| 23076 | // add margins to rect to compensate for stroke width |
| 23077 | const double strokeMargin = qMax(qreal(1.0), qreal(penWidth*0.75)); // stroke radius + 50% safety |
| 23078 | const double keyMin = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().lower)-strokeMargin*keyAxis->pixelOrientation()); |
| 23079 | const double keyMax = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().upper)+strokeMargin*keyAxis->pixelOrientation()); |
| 23080 | const double valueMin = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().lower)-strokeMargin*valueAxis->pixelOrientation()); |
| 23081 | const double valueMax = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().upper)+strokeMargin*valueAxis->pixelOrientation()); |
| 23082 | QCPCurveDataContainer::const_iterator itBegin = mDataContainer->constBegin(); |
| 23083 | QCPCurveDataContainer::const_iterator itEnd = mDataContainer->constEnd(); |
| 23084 | mDataContainer->limitIteratorsToDataRange(itBegin, itEnd, dataRange); |
| 23085 | if (itBegin == itEnd) |
| 23086 | return; |
| 23087 | QCPCurveDataContainer::const_iterator it = itBegin; |
| 23088 | QCPCurveDataContainer::const_iterator prevIt = itEnd-1; |
| 23089 | int prevRegion = getRegion(prevIt->key, prevIt->value, keyMin, valueMax, keyMax, valueMin); |
| 23090 | QVector<QPointF> trailingPoints; // points that must be applied after all other points (are generated only when handling first point to get virtual segment between last and first point right) |
| 23091 | while (it != itEnd) |
| 23092 | { |
| 23093 | const int currentRegion = getRegion(it->key, it->value, keyMin, valueMax, keyMax, valueMin); |
| 23094 | if (currentRegion != prevRegion) // changed region, possibly need to add some optimized edge points or original points if entering R |
| 23095 | { |
| 23096 | if (currentRegion != 5) // segment doesn't end in R, so it's a candidate for removal |
| 23097 | { |
| 23098 | QPointF crossA, crossB; |
| 23099 | if (prevRegion == 5) // we're coming from R, so add this point optimized |
| 23100 | { |
| 23101 | lines->append(getOptimizedPoint(currentRegion, it->key, it->value, prevIt->key, prevIt->value, keyMin, valueMax, keyMax, valueMin)); |
| 23102 | // in the situations 5->1/7/9/3 the segment may leave R and directly cross through two outer regions. In these cases we need to add an additional corner point |
| 23103 | *lines << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin); |
| 23104 | } else if (mayTraverse(prevRegion, currentRegion) && |
| 23105 | getTraverse(prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin, crossA, crossB)) |
| 23106 | { |
| 23107 | // add the two cross points optimized if segment crosses R and if segment isn't virtual zeroth segment between last and first curve point: |
| 23108 | QVector<QPointF> beforeTraverseCornerPoints, afterTraverseCornerPoints; |
| 23109 | getTraverseCornerPoints(prevRegion, currentRegion, keyMin, valueMax, keyMax, valueMin, beforeTraverseCornerPoints, afterTraverseCornerPoints); |
| 23110 | if (it != itBegin) |
| 23111 | { |
| 23112 | *lines << beforeTraverseCornerPoints; |
| 23113 | lines->append(crossA); |
| 23114 | lines->append(crossB); |
| 23115 | *lines << afterTraverseCornerPoints; |
| 23116 | } else |
| 23117 | { |
| 23118 | lines->append(crossB); |
| 23119 | *lines << afterTraverseCornerPoints; |
| 23120 | trailingPoints << beforeTraverseCornerPoints << crossA ; |
| 23121 | } |
| 23122 | } else // doesn't cross R, line is just moving around in outside regions, so only need to add optimized point(s) at the boundary corner(s) |
| 23123 | { |
| 23124 | *lines << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin); |
| 23125 | } |
nothing calls this directly
no test coverage detected