From c0053ad31507a3361f89733c154f5e50d16a168e 2012-12-10 07:41:52 From: Marek Rosa Date: 2012-12-10 07:41:52 Subject: [PATCH] Negative values with log axis handled --- diff --git a/src/barchart/horizontal/bar/horizontalbarchartitem.cpp b/src/barchart/horizontal/bar/horizontalbarchartitem.cpp index c3633e5..b2cedc5 100644 --- a/src/barchart/horizontal/bar/horizontalbarchartitem.cpp +++ b/src/barchart/horizontal/bar/horizontalbarchartitem.cpp @@ -43,13 +43,16 @@ void HorizontalBarChartItem::initializeLayout() QPointF topLeft; QPointF bottomRight; if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) { - topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth)); - bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2 + (set + 1)/setCount * barWidth)); + topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2 + (set + 1)/setCount * barWidth), m_validData); } else { - topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth)); - bottomRight = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + (set + 1)/setCount * barWidth)); + topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + (set + 1)/setCount * barWidth), m_validData); } + if (!m_validData) + return; + rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); m_layout.append(rect.normalized()); @@ -72,11 +75,15 @@ QVector HorizontalBarChartItem::calculateLayout() QRectF rect; QPointF topLeft; if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) - topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth)); + topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth), m_validData); else - topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth)); + topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth), m_validData); + + QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(value, category - barWidth / 2 + (set + 1)/setCount * barWidth), m_validData); + + if (!m_validData) + return QVector(); - QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(value, category - barWidth / 2 + (set + 1)/setCount * barWidth)); rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); layout.append(rect.normalized()); diff --git a/src/barchart/horizontal/percent/horizontalpercentbarchartitem.cpp b/src/barchart/horizontal/percent/horizontalpercentbarchartitem.cpp index af679d0..dd650a9 100644 --- a/src/barchart/horizontal/percent/horizontalpercentbarchartitem.cpp +++ b/src/barchart/horizontal/percent/horizontalpercentbarchartitem.cpp @@ -43,13 +43,16 @@ void HorizontalPercentBarChartItem::initializeLayout() QPointF topLeft; QPointF bottomRight; if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) { - topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2)); - bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2)); + topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2), m_validData); } else { - topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2)); - bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2)); + topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2), m_validData); } + if (!m_validData) + return; + rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); m_layout.append(rect.normalized()); @@ -74,10 +77,13 @@ QVector HorizontalPercentBarChartItem::calculateLayout() QRectF rect; QPointF topLeft; if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) - topLeft = domain()->calculateGeometryPoint(QPointF(set ? 100 * sum/categorySum : domain()->minX(), category - barWidth/2)); + topLeft = domain()->calculateGeometryPoint(QPointF(set ? 100 * sum/categorySum : domain()->minX(), category - barWidth/2), m_validData); else - topLeft = domain()->calculateGeometryPoint(QPointF(set ? 100 * sum/categorySum : 0, category - barWidth/2)); - QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(100 * (value + sum)/categorySum, category + barWidth/2)); + topLeft = domain()->calculateGeometryPoint(QPointF(set ? 100 * sum/categorySum : 0, category - barWidth/2), m_validData); + QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(100 * (value + sum)/categorySum, category + barWidth/2), m_validData); + + if (!m_validData) + return QVector(); rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); layout.append(rect.normalized()); diff --git a/src/barchart/horizontal/stacked/horizontalstackedbarchartitem.cpp b/src/barchart/horizontal/stacked/horizontalstackedbarchartitem.cpp index e603d04..88227ad 100644 --- a/src/barchart/horizontal/stacked/horizontalstackedbarchartitem.cpp +++ b/src/barchart/horizontal/stacked/horizontalstackedbarchartitem.cpp @@ -43,13 +43,16 @@ void HorizontalStackedBarChartItem::initializeLayout() QPointF topLeft; QPointF bottomRight; if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) { - topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2)); - bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2)); + topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2), m_validData); } else { - topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2)); - bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2)); + topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2), m_validData); } + if (!m_validData) + return; + rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); m_layout.append(rect.normalized()); @@ -75,20 +78,22 @@ QVector HorizontalStackedBarChartItem::calculateLayout() QPointF topLeft; QPointF bottomRight; if (value < 0) { - bottomRight = domain()->calculateGeometryPoint(QPointF(value + negativeSum, category - barWidth / 2)); + bottomRight = domain()->calculateGeometryPoint(QPointF(value + negativeSum, category - barWidth / 2), m_validData); if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) - topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : domain()->minX(), category + barWidth / 2)); + topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : domain()->minX(), category + barWidth / 2), m_validData); else - topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : 0, category + barWidth / 2)); + topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : 0, category + barWidth / 2), m_validData); negativeSum += value; } else { - bottomRight = domain()->calculateGeometryPoint(QPointF(value + positiveSum, category - barWidth / 2)); + bottomRight = domain()->calculateGeometryPoint(QPointF(value + positiveSum, category - barWidth / 2), m_validData); if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) - topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : domain()->minX(), category + barWidth / 2)); + topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : domain()->minX(), category + barWidth / 2), m_validData); else - topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : 0, category + barWidth / 2)); + topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : 0, category + barWidth / 2), m_validData); positiveSum += value; } + if (!m_validData) + return QVector(); rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); layout.append(rect.normalized()); diff --git a/src/barchart/vertical/bar/barchartitem.cpp b/src/barchart/vertical/bar/barchartitem.cpp index d58ca35..7fb17f2 100644 --- a/src/barchart/vertical/bar/barchartitem.cpp +++ b/src/barchart/vertical/bar/barchartitem.cpp @@ -45,13 +45,15 @@ void BarChartItem::initializeLayout() QPointF bottomRight; if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) { - topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, domain()->minY())); - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2 + (set + 1)/setCount * barWidth, domain()->minY())); + topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, domain()->minY()), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2 + (set + 1)/setCount * barWidth, domain()->minY()), m_validData); } else { - topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, 0)); - bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/setCount * barWidth, 0)); + topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, 0), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/setCount * barWidth, 0), m_validData); } + if (!m_validData) + return; rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); m_layout.append(rect.normalized()); @@ -72,12 +74,16 @@ QVector BarChartItem::calculateLayout() for (int set = 0; set < setCount; set++) { qreal value = m_series->barSets().at(set)->at(category); QRectF rect; - QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set)/(setCount) * barWidth, value)); + QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set)/(setCount) * barWidth, value), m_validData); QPointF bottomRight; if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) - bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, domain()->minY())); + bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, domain()->minY()), m_validData); else - bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, 0)); + bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, 0), m_validData); + + if (!m_validData) + return QVector(); + rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); layout.append(rect.normalized()); diff --git a/src/barchart/vertical/percent/percentbarchartitem.cpp b/src/barchart/vertical/percent/percentbarchartitem.cpp index a7e952e..fc04d34 100644 --- a/src/barchart/vertical/percent/percentbarchartitem.cpp +++ b/src/barchart/vertical/percent/percentbarchartitem.cpp @@ -45,13 +45,16 @@ void PercentBarChartItem::initializeLayout() QPointF bottomRight; if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) { - topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY())); - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY())); + topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY()), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY()), m_validData); } else { - topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0)); - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0)); + topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0), m_validData); } + if (!m_validData) + return; + rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); m_layout.append(rect.normalized()); @@ -74,12 +77,15 @@ QVector PercentBarChartItem::calculateLayout() for (int set = 0; set < setCount; set++) { qreal value = m_series->barSets().at(set)->at(category); QRectF rect; - QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth/2, 100 * (value + sum)/categorySum)); + QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth/2, 100 * (value + sum)/categorySum), m_validData); QPointF bottomRight; if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? 100 * sum/categorySum : domain()->minY())); + bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? 100 * sum/categorySum : domain()->minY()), m_validData); else - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? 100 * sum/categorySum : 0)); + bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? 100 * sum/categorySum : 0), m_validData); + + if (!m_validData) + return QVector(); rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); layout.append(rect.normalized()); diff --git a/src/barchart/vertical/stacked/stackedbarchartitem.cpp b/src/barchart/vertical/stacked/stackedbarchartitem.cpp index 377bd5d..9acb125 100644 --- a/src/barchart/vertical/stacked/stackedbarchartitem.cpp +++ b/src/barchart/vertical/stacked/stackedbarchartitem.cpp @@ -45,13 +45,16 @@ void StackedBarChartItem::initializeLayout() QPointF bottomRight; if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) { - topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY())); - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY())); + topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY()), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY()), m_validData); } else { - topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0)); - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0)); + topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0), m_validData); + bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0), m_validData); } + if (!m_validData) + return; + rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); m_layout.append(rect.normalized()); @@ -76,20 +79,22 @@ QVector StackedBarChartItem::calculateLayout() QPointF topLeft; QPointF bottomRight; if (value < 0) { - bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + negativeSum)); + bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + negativeSum), m_validData); if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) - topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : domain()->minY())); + topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : domain()->minY()), m_validData); else - topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : 0)); + topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : 0), m_validData); negativeSum += value; } else { - topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + positiveSum)); + topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + positiveSum), m_validData); if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : domain()->minY())); + bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : domain()->minY()), m_validData); else - bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : 0)); + bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : 0), m_validData); positiveSum += value; } + if (!m_validData) + return QVector(); rect.setTopLeft(topLeft); rect.setBottomRight(bottomRight); layout.append(rect.normalized()); diff --git a/src/chartdataset.cpp b/src/chartdataset.cpp index 11adfe6..a920f30 100644 --- a/src/chartdataset.cpp +++ b/src/chartdataset.cpp @@ -408,8 +408,9 @@ QPointF ChartDataSet::mapToPosition(const QPointF &value, QAbstractSeries *serie if (series && series->type() == QAbstractSeries::SeriesTypePie) return QPoint(0, 0); + bool ok; if (series && m_seriesList.contains(series)) - point += series->d_ptr->m_domain->calculateGeometryPoint(value); + point += series->d_ptr->m_domain->calculateGeometryPoint(value, ok); return point; } diff --git a/src/chartitem.cpp b/src/chartitem.cpp index 9dd565d..717bd32 100644 --- a/src/chartitem.cpp +++ b/src/chartitem.cpp @@ -26,6 +26,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE ChartItem::ChartItem(QAbstractSeriesPrivate *series,QGraphicsItem* item): ChartElement(item), + m_validData(true), m_series(series) { diff --git a/src/chartitem_p.h b/src/chartitem_p.h index 0a43709..a24f4dd 100644 --- a/src/chartitem_p.h +++ b/src/chartitem_p.h @@ -45,8 +45,11 @@ public: AbstractDomain* domain() const; public Q_SLOTS: virtual void handleDomainUpdated(); + +protected: + bool m_validData; private: - QAbstractSeriesPrivate* m_series; + QAbstractSeriesPrivate* m_series; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/domain/abstractdomain_p.h b/src/domain/abstractdomain_p.h index 4ef84eb..3b016a1 100644 --- a/src/domain/abstractdomain_p.h +++ b/src/domain/abstractdomain_p.h @@ -80,7 +80,7 @@ public: virtual void zoomOut(const QRectF &rect) = 0; virtual void move(qreal dx, qreal dy) = 0; - virtual QPointF calculateGeometryPoint(const QPointF &point) const = 0; + virtual QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const = 0; virtual QPointF calculateDomainPoint(const QPointF &point) const = 0; virtual QVector calculateGeometryPoints(const QList& vector) const = 0; diff --git a/src/domain/logxlogydomain.cpp b/src/domain/logxlogydomain.cpp index 0d98306..78bbfca 100644 --- a/src/domain/logxlogydomain.cpp +++ b/src/domain/logxlogydomain.cpp @@ -54,7 +54,7 @@ void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX; m_logRightX = logMinX > logMaxX ? logMinX : logMaxX; if(!m_signalsBlocked) - emit rangeHorizontalChanged(m_minX, m_maxX); + emit rangeHorizontalChanged(m_minX, m_maxX); } if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) { @@ -66,7 +66,7 @@ void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY; m_logRightY = logMinY > logMaxY ? logMinY : logMaxY; if(!m_signalsBlocked) - emit rangeVerticalChanged(m_minY, m_maxY); + emit rangeVerticalChanged(m_minY, m_maxY); } if (axisXChanged || axisYChanged) @@ -131,13 +131,20 @@ void LogXLogYDomain::move(qreal dx, qreal dy) setRange(minX, maxX, minY, maxY); } -QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point) const +QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const { - const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX); - const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY); - qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; - qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); - return QPointF(x, y); + if (point.x() > 0 && point.y() > 0) { + const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX); + const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY); + qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; + qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); + ok = true; + return QPointF(x, y); + } else { + qWarning() << "Logarithm of negative value is undefined. Empty layout returned"; + ok = false; + return QPointF(); + } } QVector LogXLogYDomain::calculateGeometryPoints(const QList& vector) const @@ -149,10 +156,15 @@ QVector LogXLogYDomain::calculateGeometryPoints(const QList& v result.resize(vector.count()); for (int i = 0; i < vector.count(); ++i) { - qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; - qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); - result[i].setX(x); - result[i].setY(y); + if (vector[i].x() > 0 && vector[i].y() > 0) { + qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; + qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); + result[i].setX(x); + result[i].setY(y); + } else { + qWarning() << "Logarithm of negative value is undefined. Empty layout returned"; + return QVector(); + } } return result; } diff --git a/src/domain/logxlogydomain_p.h b/src/domain/logxlogydomain_p.h index 0b7b22b..99d6615 100644 --- a/src/domain/logxlogydomain_p.h +++ b/src/domain/logxlogydomain_p.h @@ -54,7 +54,7 @@ public: void zoomOut(const QRectF &rect); void move(qreal dx, qreal dy); - QPointF calculateGeometryPoint(const QPointF &point) const; + QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const; QPointF calculateDomainPoint(const QPointF &point) const; QVector calculateGeometryPoints(const QList& vector) const; diff --git a/src/domain/logxydomain.cpp b/src/domain/logxydomain.cpp index dca581c..17bbb16 100644 --- a/src/domain/logxydomain.cpp +++ b/src/domain/logxydomain.cpp @@ -51,7 +51,7 @@ void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX; m_logRightX = logMinX > logMaxX ? logMinX : logMaxX; if(!m_signalsBlocked) - emit rangeHorizontalChanged(m_minX, m_maxX); + emit rangeHorizontalChanged(m_minX, m_maxX); } if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) { @@ -59,7 +59,7 @@ void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) m_maxY = maxY; axisYChanged = true; if(!m_signalsBlocked) - emit rangeVerticalChanged(m_minY, m_maxY); + emit rangeVerticalChanged(m_minY, m_maxY); } if (axisXChanged || axisYChanged) @@ -125,14 +125,22 @@ void LogXYDomain::move(qreal dx, qreal dy) setRange(minX, maxX, minY, maxY); } -QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point) const +QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const { - const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX); - const qreal deltaY = m_size.height() / (m_maxY - m_minY); - qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; - qreal y = (point.y() - m_minY) * -deltaY + m_size.height(); - return QPointF(x, y); + if (point.x() > 0) { + const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX); + const qreal deltaY = m_size.height() / (m_maxY - m_minY); + + qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; + qreal y = (point.y() - m_minY) * -deltaY + m_size.height(); + ok = true; + return QPointF(x, y); + } else { + qWarning() << "Logarithm of negative value is undefined. Empty layout returned"; + ok = false; + return QPointF(); + } } QVector LogXYDomain::calculateGeometryPoints(const QList& vector) const @@ -144,10 +152,15 @@ QVector LogXYDomain::calculateGeometryPoints(const QList& vect result.resize(vector.count()); for (int i = 0; i < vector.count(); ++i) { - qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; - qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height(); - result[i].setX(x); - result[i].setY(y); + if (vector[i].x() > 0) { + qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX; + qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height(); + result[i].setX(x); + result[i].setY(y); + } else { + qWarning() << "Logarithm of negative value is undefined. Empty layout returned"; + return QVector(); + } } return result; } diff --git a/src/domain/logxydomain_p.h b/src/domain/logxydomain_p.h index c127d13..303c2ac 100644 --- a/src/domain/logxydomain_p.h +++ b/src/domain/logxydomain_p.h @@ -54,7 +54,7 @@ public: void zoomOut(const QRectF &rect); void move(qreal dx, qreal dy); - QPointF calculateGeometryPoint(const QPointF &point) const; + QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const; QPointF calculateDomainPoint(const QPointF &point) const; QVector calculateGeometryPoints(const QList& vector) const; diff --git a/src/domain/xlogydomain.cpp b/src/domain/xlogydomain.cpp index 61ae88d..376ef73 100644 --- a/src/domain/xlogydomain.cpp +++ b/src/domain/xlogydomain.cpp @@ -47,7 +47,7 @@ void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) m_maxX = maxX; axisXChanged = true; if(!m_signalsBlocked) - emit rangeHorizontalChanged(m_minX, m_maxX); + emit rangeHorizontalChanged(m_minX, m_maxX); } if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) { @@ -59,7 +59,7 @@ void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY; m_logRightY = logMinY > logMaxY ? logMinY : logMaxY; if(!m_signalsBlocked) - emit rangeVerticalChanged(m_minY, m_maxY); + emit rangeVerticalChanged(m_minY, m_maxY); } if (axisXChanged || axisYChanged) @@ -125,14 +125,21 @@ void XLogYDomain::move(qreal dx, qreal dy) setRange(minX, maxX, minY, maxY); } -QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point) const +QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const { - const qreal deltaX = m_size.width() / (m_maxX - m_minX); - const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY); - - qreal x = (point.x() - m_minX) * deltaX; - qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); - return QPointF(x, y); + if (point.y() > 0) { + const qreal deltaX = m_size.width() / (m_maxX - m_minX); + const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY); + + qreal x = (point.x() - m_minX) * deltaX; + qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); + ok = true; + return QPointF(x, y); + } else { + qWarning() << "Logarithm of negative value is undefined. Empty layout returned"; + ok = false; + return QPointF(); + } } QVector XLogYDomain::calculateGeometryPoints(const QList& vector) const @@ -144,10 +151,15 @@ QVector XLogYDomain::calculateGeometryPoints(const QList& vect result.resize(vector.count()); for (int i = 0; i < vector.count(); ++i) { - qreal x = (vector[i].x() - m_minX) * deltaX; - qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); - result[i].setX(x); - result[i].setY(y); + if (vector[i].y() > 0) { + qreal x = (vector[i].x() - m_minX) * deltaX; + qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height(); + result[i].setX(x); + result[i].setY(y); + } else { + qWarning() << "Logarithm of negative value is undefined. Empty layout returned"; + return QVector(); + } } return result; } @@ -168,7 +180,7 @@ bool XLogYDomain::attachAxis(QAbstractAxis* axis) if(logAxis && logAxis->orientation()==Qt::Vertical){ QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal))); handleVerticalAxisBaseChanged(logAxis->base()); -} + } return AbstractDomain::attachAxis(axis); } diff --git a/src/domain/xlogydomain_p.h b/src/domain/xlogydomain_p.h index c13ea36..22de9c8 100644 --- a/src/domain/xlogydomain_p.h +++ b/src/domain/xlogydomain_p.h @@ -54,7 +54,7 @@ public: void zoomOut(const QRectF &rect); void move(qreal dx, qreal dy); - QPointF calculateGeometryPoint(const QPointF &point) const; + QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const; QPointF calculateDomainPoint(const QPointF &point) const; QVector calculateGeometryPoints(const QList& vector) const; diff --git a/src/domain/xydomain.cpp b/src/domain/xydomain.cpp index 6603566..c2adb71 100644 --- a/src/domain/xydomain.cpp +++ b/src/domain/xydomain.cpp @@ -116,12 +116,13 @@ void XYDomain::move(qreal dx, qreal dy) setRange(minX, maxX, minY, maxY); } -QPointF XYDomain::calculateGeometryPoint(const QPointF &point) const +QPointF XYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const { const qreal deltaX = m_size.width() / (m_maxX - m_minX); const qreal deltaY = m_size.height() / (m_maxY - m_minY); qreal x = (point.x() - m_minX) * deltaX; qreal y = (point.y() - m_minY) * -deltaY + m_size.height(); + ok = true; return QPointF(x, y); } diff --git a/src/domain/xydomain_p.h b/src/domain/xydomain_p.h index 9ec7a85..ddbf5d1 100644 --- a/src/domain/xydomain_p.h +++ b/src/domain/xydomain_p.h @@ -54,7 +54,7 @@ public: void zoomOut(const QRectF &rect); void move(qreal dx, qreal dy); - QPointF calculateGeometryPoint(const QPointF &point) const; + QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const; QPointF calculateDomainPoint(const QPointF &point) const; QVector calculateGeometryPoints(const QList& vector) const; }; diff --git a/src/linechart/linechartitem.cpp b/src/linechart/linechartitem.cpp index 224770e..2a01326 100644 --- a/src/linechart/linechartitem.cpp +++ b/src/linechart/linechartitem.cpp @@ -135,15 +135,15 @@ void LineChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event) void LineChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), true); - event->accept(); - //QGraphicsItem::hoverEnterEvent(event); +// event->accept(); + QGraphicsItem::hoverEnterEvent(event); } void LineChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), false); - event->accept(); - //QGraphicsItem::hoverEnterEvent(event); +// event->accept(); + QGraphicsItem::hoverEnterEvent(event); } #include "moc_linechartitem_p.cpp" diff --git a/src/splinechart/splinechartitem.cpp b/src/splinechart/splinechartitem.cpp index 04e5ad7..d991d39 100644 --- a/src/splinechart/splinechartitem.cpp +++ b/src/splinechart/splinechartitem.cpp @@ -101,7 +101,8 @@ void SplineChartItem::updateChart(QVector &oldPoints, QVector QPointF SplineChartItem::calculateGeometryControlPoint(int index) const { - return domain()->calculateGeometryPoint(m_series->d_func()->controlPoint(index)); + bool ok; + return domain()->calculateGeometryPoint(m_series->d_func()->controlPoint(index), ok); } void SplineChartItem::updateGeometry() @@ -176,13 +177,13 @@ void SplineChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event) void SplineChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), true); - event->accept(); + QGraphicsItem::hoverEnterEvent(event); } void SplineChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), false); - event->accept(); + QGraphicsItem::hoverLeaveEvent(event); } #include "moc_splinechartitem_p.cpp" diff --git a/src/xychart/xychart.cpp b/src/xychart/xychart.cpp index d9a3df6..26bed33 100644 --- a/src/xychart/xychart.cpp +++ b/src/xychart/xychart.cpp @@ -88,7 +88,11 @@ void XYChart::handlePointAdded(int index) points = domain()->calculateGeometryPoints(m_series->points()); } else { points = m_points; - QPointF point = domain()->calculateGeometryPoint(m_series->points()[index]); + QPointF point = domain()->calculateGeometryPoint(m_series->points()[index], m_validData); + if (!m_validData) { + m_points.clear(); + return; + } points.insert(index, point); } @@ -122,7 +126,11 @@ void XYChart::handlePointReplaced(int index) if (m_dirty) { points = domain()->calculateGeometryPoints(m_series->points()); } else { - QPointF point = domain()->calculateGeometryPoint(m_series->points()[index]); + QPointF point = domain()->calculateGeometryPoint(m_series->points()[index], m_validData); + if (!m_validData) { + m_points.clear(); + return; + } points = m_points; points.replace(index, point); }