! \internal Returns the polygon needed for drawing (partial) channel fills between this graph and the graph specified by \ref setChannelFillGraph. The data points of this graph are passed as pixel coordinates via \a thisData, the data of the other graph as \a otherData. The returned polygon will be calculated for the specified data segments \a thisSegment and \a otherSegment, perta
| 22241 | \see drawFill, getOverlappingSegments, getNonNanSegments |
| 22242 | */ |
| 22243 | const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *thisData, QCPDataRange thisSegment, const QVector<QPointF> *otherData, QCPDataRange otherSegment) const |
| 22244 | { |
| 22245 | if (!mChannelFillGraph) |
| 22246 | return QPolygonF(); |
| 22247 | |
| 22248 | QCPAxis *keyAxis = mKeyAxis.data(); |
| 22249 | QCPAxis *valueAxis = mValueAxis.data(); |
| 22250 | if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); } |
| 22251 | if (!mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO << "channel fill target key axis invalid"; return QPolygonF(); } |
| 22252 | |
| 22253 | if (mChannelFillGraph.data()->mKeyAxis.data()->orientation() != keyAxis->orientation()) |
| 22254 | return QPolygonF(); // don't have same axis orientation, can't fill that (Note: if keyAxis fits, valueAxis will fit too, because it's always orthogonal to keyAxis) |
| 22255 | |
| 22256 | if (thisData->isEmpty()) return QPolygonF(); |
| 22257 | QVector<QPointF> thisSegmentData(thisSegment.size()); |
| 22258 | QVector<QPointF> otherSegmentData(otherSegment.size()); |
| 22259 | std::copy(thisData->constBegin()+thisSegment.begin(), thisData->constBegin()+thisSegment.end(), thisSegmentData.begin()); |
| 22260 | std::copy(otherData->constBegin()+otherSegment.begin(), otherData->constBegin()+otherSegment.end(), otherSegmentData.begin()); |
| 22261 | // pointers to be able to swap them, depending which data range needs cropping: |
| 22262 | QVector<QPointF> *staticData = &thisSegmentData; |
| 22263 | QVector<QPointF> *croppedData = &otherSegmentData; |
| 22264 | |
| 22265 | // crop both vectors to ranges in which the keys overlap (which coord is key, depends on axisType): |
| 22266 | if (keyAxis->orientation() == Qt::Horizontal) |
| 22267 | { |
| 22268 | // x is key |
| 22269 | // crop lower bound: |
| 22270 | if (staticData->first().x() < croppedData->first().x()) // other one must be cropped |
| 22271 | qSwap(staticData, croppedData); |
| 22272 | const int lowBound = findIndexBelowX(croppedData, staticData->first().x()); |
| 22273 | if (lowBound == -1) return QPolygonF(); // key ranges have no overlap |
| 22274 | croppedData->remove(0, lowBound); |
| 22275 | // set lowest point of cropped data to fit exactly key position of first static data point via linear interpolation: |
| 22276 | if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation |
| 22277 | double slope; |
| 22278 | if (!qFuzzyCompare(croppedData->at(1).x(), croppedData->at(0).x())) |
| 22279 | slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x()); |
| 22280 | else |
| 22281 | slope = 0; |
| 22282 | (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x())); |
| 22283 | (*croppedData)[0].setX(staticData->first().x()); |
| 22284 | |
| 22285 | // crop upper bound: |
| 22286 | if (staticData->last().x() > croppedData->last().x()) // other one must be cropped |
| 22287 | qSwap(staticData, croppedData); |
| 22288 | int highBound = findIndexAboveX(croppedData, staticData->last().x()); |
| 22289 | if (highBound == -1) return QPolygonF(); // key ranges have no overlap |
| 22290 | croppedData->remove(highBound+1, croppedData->size()-(highBound+1)); |
| 22291 | // set highest point of cropped data to fit exactly key position of last static data point via linear interpolation: |
| 22292 | if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation |
| 22293 | const int li = croppedData->size()-1; // last index |
| 22294 | if (!qFuzzyCompare(croppedData->at(li).x(), croppedData->at(li-1).x())) |
| 22295 | slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x()); |
| 22296 | else |
| 22297 | slope = 0; |
| 22298 | (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x())); |
| 22299 | (*croppedData)[li].setX(staticData->last().x()); |
| 22300 | } else // mKeyAxis->orientation() == Qt::Vertical |