]> Devoid-pointer.net GitWeb - anyanka.git/commitdiff
Update data plotting logic so that the peak baseline is rendered
authorMichal Malý <madcatxster@prifuk.cz>
Thu, 13 Mar 2014 22:48:42 +0000 (23:48 +0100)
committerMichal Malý <madcatxster@prifuk.cz>
Thu, 13 Mar 2014 22:48:42 +0000 (23:48 +0100)
properly and Y-axis scale is more accurate

integratedpeak.cpp
integratedpeak.h
integrator.cpp
integrator.h
signalcontroller.cpp
signalcontroller.h
signaldrawer.cpp
signaldrawer.h

index 26444915bae46e4f7f7242f7b545f630c8b114d9..b0c42161d30f89627bf23010ef44fd78e1831681 100644 (file)
@@ -34,9 +34,12 @@ const QString IntegratedPeak::KEY_TOIDX("toIdx");
 const QString IntegratedPeak::KEY_TOTIME("toTime");
 const QString IntegratedPeak::KEY_TOY("toY");
 const QString IntegratedPeak::KEY_TYPE("type");
+const QString IntegratedPeak::KEY_RELBLSLOPE("relBlSlope");
+const QString IntegratedPeak::KEY_RELBLQ("relBlQ");
 
 IntegratedPeak::IntegratedPeak(IntegratedPeak::Type type, double auc, size_t peakIdx, double peakTime, double peakY,
-                               size_t fromIdx, size_t toIdx, double fromTime, double toTime, double fromY, double toY, QObject* parent) :
+                               size_t fromIdx, size_t toIdx, double fromTime, double toTime, double fromY, double toY,
+                               double relBlSlope, double relBlQ, QObject* parent) :
   QObject(parent),
   JSONSerializable(),
   m_auc(auc),
@@ -49,7 +52,9 @@ IntegratedPeak::IntegratedPeak(IntegratedPeak::Type type, double auc, size_t pea
   m_toIdx(toIdx),
   m_toTime(toTime),
   m_toY(toY),
-  m_type(type)
+  m_type(type),
+  m_relBlSlope(relBlSlope),
+  m_relBlQ(relBlQ)
 {
 }
 
@@ -109,6 +114,13 @@ bool IntegratedPeak::deserialize(const QJsonValue& value)
   else
     m_type = Type::VALLEY;
 
+  if (!jso.contains(KEY_RELBLSLOPE))
+    return false;
+  m_relBlSlope = jso.value(KEY_RELBLSLOPE).toDouble();
+  if (!jso.contains(KEY_RELBLQ))
+    return false;
+  m_relBlQ = jso.value(KEY_RELBLQ).toDouble();
+
   return true;
 }
 
@@ -133,6 +145,8 @@ QJsonValue IntegratedPeak::serialize() const
   jso.insert(KEY_TOTIME, QJsonValue(m_toTime));
   jso.insert(KEY_TOY, QJsonValue(m_toY));
   jso.insert(KEY_TYPE, QJsonValue(type));
+  jso.insert(KEY_RELBLSLOPE, QJsonValue(m_relBlSlope));
+  jso.insert(KEY_RELBLQ, QJsonValue(m_relBlQ));
 
   return jso;
 }
index 89228e345d06cb40d55af8d46232cca72eda8201..af38729ff937ea03a8dee6c5cf1a780fc35ae0e2 100644 (file)
@@ -39,7 +39,7 @@ public:
 
   explicit IntegratedPeak() : m_type(Type::INVALID) {}
   explicit IntegratedPeak(Type type, double auc, size_t peakIdx, double peakTime, double peakY, size_t fromIdx, size_t toIdx, double fromTime, double toTime,
-                          double fromY, double toY, QObject* parent = nullptr);
+                          double fromY, double toY, double relBlSlope, double relBlQ, QObject* parent = nullptr);
   double auc() const { return m_auc; }
   double baselineSlope() const;
   size_t fromIdx() const { return m_fromIdx; }
@@ -49,6 +49,8 @@ public:
   size_t peakIdx() const { return m_peakIdx; }
   double peakTime() const { return m_peakTime; }
   double peakY() const { return m_peakY; }
+  double relBlQ() const { return m_relBlQ; }
+  double relBlSlope() const { return m_relBlSlope; }
   size_t toIdx() const { return m_toIdx; }
   double toTime() const { return m_toTime; }
   double toY() const { return m_toY; }
@@ -70,6 +72,8 @@ private:
   double m_toTime;
   double m_toY;
   Type m_type;
+  double m_relBlSlope;
+  double m_relBlQ;
 
   static const QString KEY_AUC;
   static const QString KEY_FROMIDX;
@@ -82,6 +86,8 @@ private:
   static const QString KEY_TOTIME;
   static const QString KEY_TOY;
   static const QString KEY_TYPE;
+  static const QString KEY_RELBLSLOPE;
+  static const QString KEY_RELBLQ;
 
 
 public slots:
index 6aa8ed06703214f4d3093761b529856db5831858..41b1d275d6d2011a8db80f6aeba78eab690680d8 100644 (file)
@@ -77,7 +77,8 @@ std::vector<std::shared_ptr<const IntegratedPeak>> Integrator::allPeaks()
   return allPeaks;
 }
 
-Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, double startY, double stopY, std::shared_ptr<IntegratedPeak>& peak)
+Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, double startY, double stopY, std::shared_ptr<IntegratedPeak>& peak,
+                                             double relBlSlope, double relBlQ)
 {
   size_t peakValueIdx;
   size_t startIntersIdx, stopIntersIdx;
@@ -102,8 +103,6 @@ Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, do
     std::swap(startY, stopY);
   }
 
-  qDebug() << "INTEG" << startIdx << stopIdx << startY << stopY;
-
   slope = (stopY - startY) / static_cast<double>(stopIdx - startIdx);
   /* Try to find first intersection */
   if (startY < m_signal->valueAt(startIdx)) {
@@ -183,7 +182,7 @@ Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, do
 
   peak = std::shared_ptr<IntegratedPeak>(new IntegratedPeak(peakType, auc, peakValueIdx, m_signal->timeAt(peakValueIdx), m_signal->valueAt(peakValueIdx),
                                                             startIntersIdx, stopIntersIdx, m_signal->timeAt(startIntersIdx), m_signal->timeAt(stopIntersIdx),
-                                                            startYVal, stopYVal));
+                                                            startYVal, stopYVal, relBlSlope, relBlQ));
   emit addingPeak(m_peaksList.count());
   m_peaksList.append(peak);
   emit peakAdded();
index b170f6989b888a3fa151691e93216ed6696e1c98..2dce9acd77f5d18b3ffbe5eec7967cf7180cfdaf 100644 (file)
@@ -46,7 +46,8 @@ public:
   void addPeak(std::shared_ptr<IntegratedPeak> peak);
   std::shared_ptr<const IntegratedPeak> deletePeak(size_t idx);
   std::vector<std::shared_ptr<const IntegratedPeak>> allPeaks();
-  ReturnCode integrate(size_t startIdx, size_t stopIdx, double startY, double stopY, std::shared_ptr<IntegratedPeak>& peak);
+  ReturnCode integrate(size_t startIdx, size_t stopIdx, double startY, double stopY, std::shared_ptr<IntegratedPeak>& peak,
+                       double relBlSlope, double relBlQ);
   std::shared_ptr<const IntegratedPeak> peakByListIdx(const size_t idx);
   //std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator peaksCBegin() const { return m_peaks.cbegin(); }
   //std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator peaksCEnd() const { return m_peaks.cend(); }
index 63406b017028639d4e1f0ceee830a733cd6a7bb8..a205aeaeff7ed877385d84cbc357b0e0cd796efe 100644 (file)
@@ -104,7 +104,7 @@ bool SignalController::deserialize(const QJsonValue& value)
 std::shared_ptr<GraphDrawData> SignalController::getGraphDrawData(const double fromX, const double toX)
 {
   size_t fromIdx, toIdx;
-  double* ddata;
+  std::pair<double, double>* ddata;
   size_t ddataLen;
 
   if (toX <= fromX) {
@@ -113,19 +113,20 @@ std::shared_ptr<GraphDrawData> SignalController::getGraphDrawData(const double f
   }
 
   fromIdx = relToIdx(fromX);
-  toIdx = relToIdx(toX);
+  toIdx = relToIdx(toX)+1;
 
   if (toIdx >= m_signal->count()) {
-    Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, __QFUNC__ + " toIdx (" + QString::number(toIdx) + ") out of bounds, max (" +
+    /*Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, __QFUNC__ + " toIdx (" + QString::number(toIdx) + ") out of bounds, max (" +
                 QString::number(m_signal->count()-1) + ") !");
-    return std::shared_ptr<GraphDrawData>(new GraphDrawData());
+    return std::shared_ptr<GraphDrawData>(new GraphDrawData());*/
+    toIdx = m_signal->count()-1;
   }
 
   ddataLen = toIdx - fromIdx + 1;
-  ddata = new double[ddataLen];
+  ddata = new std::pair<double, double>[ddataLen];
   for (size_t idx = fromIdx; idx <= toIdx; idx++) {
-    double current = valueToRel(m_signal->valueAt(idx));
-    ddata[idx - fromIdx] = current;
+    std::pair<double, double> p(idxToRel(idx), valueToRel(m_signal->valueAt(idx)));
+    ddata[idx - fromIdx] = p;
   }
 
   return std::shared_ptr<GraphDrawData>(new GraphDrawData(ddata, ddataLen));
@@ -136,7 +137,6 @@ std::vector<PeakDrawData> SignalController::getPeaksDrawData(const double fromX,
   std::vector<PeakDrawData> peaks;
   size_t fromIdx, toIdx;
   std::vector<std::shared_ptr<const IntegratedPeak>> allPeaks;
-  //  std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator cit = m_integrator->peaksCBegin();
 
   if (toX <= fromX) {
     Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " toX is lower than fromX");
@@ -183,6 +183,8 @@ RulerDrawData SignalController::getRulerDrawData(const double from, const double
     case Axis::VALUE:
       fromAbs = relToValue(from);
       toAbs = relToValue(to);
+
+      qDebug() << __QFUNC__ << fromAbs << toAbs;
       break;
   }
 
@@ -203,21 +205,26 @@ RulerDrawData SignalController::getRulerDrawData(const double from, const double
 Signal::TimeValuePair SignalController::getXYValues(const double x)
 {
   size_t idx = relToIdx(x);
-  if (idx >= m_signal->count()) {
+  if (idx >= m_signal->count()-1) {
     Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, __QFUNC__ + " idx value " + QString::number(idx) + " out of bounds!");
     return Signal::TimeValuePair(0, 0);
   }
 
-  return m_signal->pairAt(idx);
+  /* Workaround for the way how the data are plotted on the screen */
+  return std::pair<double, double>(m_signal->timeAt(idx), m_signal->valueAt(idx+1));
 }
 
 PeakDrawData SignalController::integratePeak(const double fromX, const double fromY, const double toX, const double toY)
 {
   size_t fromIdx, toIdx;
   double fromVal, toVal;
+  double relBlSlope = (toY - fromY) / (toX - fromX);
+  double relBlQ = fromY - relBlSlope * fromX;
   Integrator::ReturnCode ret;
   std::shared_ptr<IntegratedPeak> peak;
 
+  qDebug() << __QFUNC__ << fromX << fromY << toX << toY;
+
   fromIdx = relToIdx(fromX);
   toIdx = relToIdx(toX);
   if (fromIdx >= m_signal->count()) {
@@ -231,7 +238,7 @@ PeakDrawData SignalController::integratePeak(const double fromX, const double fr
   fromVal = relToValue(fromY);
   toVal = relToValue(toY);
 
-  ret = m_integrator->integrate(fromIdx, toIdx, fromVal, toVal, peak);
+  ret = m_integrator->integrate(fromIdx, toIdx, fromVal, toVal, peak, relBlSlope, relBlQ);
 
   switch (ret) {
     case Integrator::ReturnCode::SUCCESS:
@@ -270,8 +277,18 @@ QJsonValue SignalController::serialize() const
 
 PeakDrawData SignalController::genPeakDrawData(const std::shared_ptr<const IntegratedPeak> peak)
 {
-  return PeakDrawData(idxToRel(peak->fromIdx()), valueToRel(peak->fromY()),
-                      idxToRel(peak->toIdx()), valueToRel(peak->toY()),
+  double beforeFromY = m_signal->valueAt(peak->fromIdx() - 1);
+  double beforeToY = m_signal->valueAt(peak->toIdx() - 1);
+  double fromY = m_signal->valueAt(peak->fromIdx());
+  double toY = m_signal->valueAt(peak->toIdx());
+
+  //qDebug() << __QFUNC__ << beforeFromY << fromY
+  //         << beforeToY << toY;
+  //qDebug() << m_signal->timeAt(peak->fromIdx() - 0) << m_signal->timeAt(peak->fromIdx() + 1) << peak->fromTime();
+
+  return PeakDrawData(idxToRel(peak->fromIdx()), valueToRel(fromY), idxToRel(peak->fromIdx()-1), valueToRel(beforeFromY),
+                      idxToRel(peak->toIdx()), valueToRel(toY), idxToRel(peak->toIdx()-1), valueToRel(beforeToY),
+                      peak->relBlSlope(), peak->relBlQ(),
                       idxToRel(peak->peakIdx()), valueToRel(m_signal->valueAt(peak->peakIdx())),
                       peak->peakTime(), peak->auc());
 }
@@ -299,7 +316,7 @@ double SignalController::timeToRel(const double time)
 
 size_t SignalController::relToIdx(const double rel)
 {
-  size_t ret = (m_signal->count() - 1) * (rel - RELATIVE_MIN) / (RELATIVE_MAX - RELATIVE_MIN);
+  size_t ret = (m_signal->count()) * (rel - RELATIVE_MIN) / (RELATIVE_MAX - RELATIVE_MIN);
   //qDebug() << __QFUNC__ << rel << ret << m_signal->count();
   return ret;
 }
index 5a3db71ba4380d748c720a2809e1cb7ad76d5aaa..4f5f8f52bd61fdf530200388fc1f89e2bf17774f 100644 (file)
@@ -49,7 +49,7 @@ struct GUIViewport {
 struct GraphDrawData {
   GraphDrawData() :
     ddata(nullptr), ddataLen(0) {}
-  GraphDrawData(const double* ddata, const size_t ddataLen) :
+  GraphDrawData(const std::pair<double, double>* ddata, const size_t ddataLen) :
     ddata(ddata), ddataLen(ddataLen) {}
   ~GraphDrawData()
   {
@@ -57,17 +57,25 @@ struct GraphDrawData {
       delete[] ddata;
   }
 
-  const double* ddata;
+  const std::pair<double, double>* ddata;
   const size_t ddataLen;
 };
 
 struct PeakDrawData {
-  PeakDrawData() : fromX(0), fromY(0), toX(0), toY(0), peakX(0), peakY(0), auc(0), time(0) {}
-  PeakDrawData(const double fromX, const double fromY, const double toX, const double toY,
+  PeakDrawData() : fromX(0), fromY(0), toX(0), toY(0), beforeFromX(0), beforeFromY(0), beforeToX(0),
+    beforeToY(0), blSlope(0), blQ(0), peakX(0), peakY(0), auc(0), time(0) {}
+  PeakDrawData(const double fromX, const double fromY, const double beforeFromX, const double beforeFromY,
+               const double toX, const double toY, const double beforeToX, const double beforeToY,
+               const double blSlope, const double blQ,
                const double peakX, const double peakY, const double auc, const double time) :
-    fromX(fromX), fromY(fromY), toX(toX), toY(toY), peakX(peakX), peakY(peakY), auc(auc), time(time) {}
+    fromX(fromX), fromY(fromY), toX(toX), toY(toY),
+    beforeFromX(beforeFromX), beforeFromY(beforeFromY), beforeToX(beforeToX), beforeToY(beforeToY),
+    blSlope(blSlope), blQ(blQ),
+    peakX(peakX), peakY(peakY), auc(auc), time(time) {}
 
   const double fromX, fromY, toX, toY;
+  const double beforeFromX, beforeFromY, beforeToX, beforeToY;
+  const double blSlope, blQ;
   const double peakX, peakY;
   const double auc, time;
 };
index 107f60dfe26fb93411952a2765602c8a9f5f8209..1360909a6610b104c72b98c79259a157344211a2 100644 (file)
@@ -287,8 +287,7 @@ QRect SignalDrawer::erasePeak(const PeakDrawData& pd)
 bool SignalDrawer::renderGraph(QPixmap* const target)
 {
   QPainter p;
-  double xStep, yStep;
-  int fromXPix = SCALE_MARGIN_VALUE, fromYPix;
+  int fromXPix, fromYPix;
 
   if (m_width < SCALE_MARGIN_VALUE || m_height < SCALE_MARGIN_VALUE) {
     Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " invalid dimensions (" + QString::number(m_width) + ", " + QString::number(m_height) + ")");
@@ -303,10 +302,10 @@ bool SignalDrawer::renderGraph(QPixmap* const target)
   p.fillRect(0, 0, m_width, m_height, Qt::white);
   p.setPen(QColor(Qt::blue));
 
-  xStep = static_cast<double>(m_gWidth) / m_gdData->ddataLen;
+  /*xStep = static_cast<double>(m_gWidth) / m_gdData->ddataLen;
   yStep = static_cast<double>(m_gHeight) / (m_relYMax - m_relYMin);
   /*Logger::log(Logger::Level::DEBUG, ME_SENDER_STR, __QFUNC__ + " yStep: " + QString::number(yStep)
-              + " fY " + QString::number(m_relYMin) + " tY " + QString::number(m_relYMax));*/
+              + " fY " + QString::number(m_relYMin) + " tY " + QString::number(m_relYMax));*
   fromYPix = m_gHeight - yStep * (m_gdData->ddata[0] - m_relYMin);
   for (size_t i = 1; i < m_gdData->ddataLen; i++) {
     int toXPix = xStep * i + SCALE_MARGIN_VALUE;
@@ -314,11 +313,20 @@ bool SignalDrawer::renderGraph(QPixmap* const target)
     p.drawLine(fromXPix, fromYPix, toXPix, toYPix);
     fromXPix = toXPix;
     fromYPix = toYPix;
+  }*/
+
+  fromXPix = relToXPix(m_gdData->ddata[0].first);
+  fromYPix = relToYPix(m_gdData->ddata[0].second);
+  for (size_t i = 1; i < m_gdData->ddataLen; i++) {
+    int toXPix = relToXPix(m_gdData->ddata[i].first);
+    int toYPix = relToYPix(m_gdData->ddata[i].second);
+    p.drawLine(fromXPix, fromYPix, toXPix, toYPix);
+    fromXPix = toXPix;
+    fromYPix = toYPix;
   }
 
   p.end();
 
-
   return true;
 }
 
@@ -353,8 +361,25 @@ QRect SignalDrawer::renderPeak(const PeakDrawData& pd, QPixmap* const target)
   if (pd.auc == 0)
     return QRect();
 
-  fromXPix = relToXPix(pd.fromX); fromYPix = relToYPix(pd.fromY);
-  toXPix = relToXPix(pd.toX); toYPix = relToYPix(pd.toY);
+  /* Psycho: Calculate precise position of the beginning and end of the baseline */
+  double fromSlope = (pd.fromY - pd.beforeFromY) / (pd.fromX - pd.beforeFromX);
+  double toSlope = (pd.toY - pd.beforeToY) / (pd.toX - pd.beforeToX);
+  double qf = pd.beforeFromY - fromSlope * pd.beforeFromX;
+  double qt = pd.beforeToY - toSlope * pd.beforeToX;
+  double precFromX = linesIntersection(fromSlope, qf, pd.blSlope, pd.blQ);
+  double precToX = linesIntersection(toSlope, qt, pd.blSlope, pd.blQ);
+  double precFromY = precFromX * pd.blSlope + pd.blQ;
+  double precToY = precToX * pd.blSlope + pd.blQ;
+
+  /*qDebug() << __QFUNC__ << "idxStep" << pd.idxStep;
+  qDebug() << __QFUNC__ << "blSlope" << pd.blSlope << "blQ" << pd.blQ;
+  qDebug() << __QFUNC__ << "fromSlope" << fromSlope;
+  qDebug() << __QFUNC__ << "qf" << qf << "qt" << qt;
+  qDebug() << __QFUNC__ << precFromX << pd.beforeFromX;
+  qDebug() << __QFUNC__ << precFromY << pd.beforeFromY;*/
+
+  fromXPix = relToXPix(precFromX); fromYPix = relToYPix(precFromY);
+  toXPix = relToXPix(precToX); toYPix = relToYPix(precToY);
   peakX = relToXPix(pd.peakX); peakY = relToYPix(pd.peakY);
   aucText = m_locale.toString(pd.auc, 'f', 4);
   timeText = QString("A:") + m_locale.toString(pd.time, 'f', 4);
@@ -363,6 +388,14 @@ QRect SignalDrawer::renderPeak(const PeakDrawData& pd, QPixmap* const target)
   p.setPen(Qt::red);
   p.drawLine(fromXPix, fromYPix, toXPix, toYPix);
 
+  /** DEBUG **/
+  p.setPen(Qt::yellow);
+  p.drawEllipse(QPoint(relToXPix(pd.beforeFromX), relToYPix(pd.beforeFromY)), 10, 10);
+  p.drawEllipse(QPoint(relToXPix(pd.beforeToX), relToYPix(pd.beforeToY)), 10, 10);
+  p.setPen(Qt::black);
+  p.drawEllipse(QPoint(relToXPix(pd.fromX), relToYPix(pd.fromY)), 10, 10);
+  p.drawEllipse(QPoint(relToXPix(pd.toX), relToYPix(pd.toY)), 10, 10);
+
   /* Draw AREA and TIME caption */
   p.setFont(font);
   p.setPen(Qt::black);
@@ -378,9 +411,8 @@ QRect SignalDrawer::renderPeak(const PeakDrawData& pd, QPixmap* const target)
   p.restore();
   aTextWidth = fm.width(aucText);
   p.drawText(peakX + 5, peakY, aucText);
-  p.end();
 
-  if (peakX - tTextHeight < fromXPix)
+   if (peakX - tTextHeight < fromXPix)
     beginXPix = (peakX - tTextHeight > 0) ? peakX - tTextHeight : 0;
   else
     beginXPix = fromXPix;
@@ -389,21 +421,30 @@ QRect SignalDrawer::renderPeak(const PeakDrawData& pd, QPixmap* const target)
   else
     endXPix = toXPix;
 
+
   return QRect(beginXPix, 0, endXPix - beginXPix, m_height);
 }
 
 /** Private functions **/
 
+double SignalDrawer::linesIntersection(const double k1, const double q1, const double k2, const double q2)
+{
+  double ret = (q1 - q2) / (k2 - k1);
+  qDebug() << __QFUNC__ << ret;
+
+  return ret;
+}
+
 int SignalDrawer::relToXPix(const double rel)
 {
-  const int ret = m_gWidth / (m_relXMax - m_relXMin) * (rel - m_relXMin) + SCALE_MARGIN_VALUE;
+  const double ret = m_gWidth / (m_relXMax - m_relXMin) * (rel - m_relXMin) + SCALE_MARGIN_VALUE;
   //qDebug() << __QFUNC__ << ret;
   return ret;
 }
 
 int SignalDrawer::relToYPix(const double rel)
 {
-  const int ret = m_gHeight - (m_gHeight / (m_relYMax - m_relYMin) * (rel - m_relYMin));
+  const double ret = m_gHeight - (m_gHeight / (m_relYMax - m_relYMin) * (rel - m_relYMin));
   //qDebug() << __QFUNC__ << ret;
   return ret;
 }
@@ -412,7 +453,7 @@ double SignalDrawer::xPixToRel(const int pix)
 {
   double ret;
   if (pix < SCALE_MARGIN_VALUE)
-    return 0.0;
+    return m_relXMin;
   ret = ((pix - SCALE_MARGIN_VALUE) * (m_relXMax - m_relXMin) / m_gWidth) + m_relXMin;
   //qDebug() << __QFUNC__ << ret;
   return ret;
@@ -423,7 +464,9 @@ double SignalDrawer::yPixToRel(const int pix)
   const double range = m_relYMax - m_relYMin;
   const int invPix = m_gHeight - pix;
   if (invPix < 0)
-    return 0;
+    return m_relYMin;
+  else if (invPix > m_gHeight)
+    return m_relXMax;
   return (range / m_gHeight * invPix) + m_relYMin;
 }
 
index 767b9b706667312eb06df14e8e339d73601df9b5..0140e4d8d78e6f980339ecf6a28c3fdebf90be8a 100644 (file)
@@ -97,6 +97,8 @@ protected:
   static const int SCALE_MARGIN_VALUE;
 
 private:
+  double linesIntersection(const double k1, const double q1, const double k2, const double q2);
+
   int m_height;
   int m_width;
   int m_gHeight;