void RangeProfilePlotManager::calculateDifferences() { // ensure we have only two objects selected VERIFYNRV(mpView); std::list<PlotObject*> selected; mpView->getSelectedObjects(selected, true); std::list<PlotObject*>::iterator selIt = selected.begin(); PointSet* pFirst = (selIt == selected.end()) ? NULL : dynamic_cast<PointSet*>(*(selIt++)); PointSet* pSecond = (selIt == selected.end()) ? NULL : dynamic_cast<PointSet*>(*(selIt++)); if (pFirst == NULL || pSecond == NULL) { return; } // locate the Difference point set std::list<PlotObject*> allObjects; mpView->getObjects(POINT_SET, allObjects); PointSet* pDiffSet = NULL; for (std::list<PlotObject*>::iterator obj = allObjects.begin(); obj != allObjects.end(); ++obj) { PointSet* pSet = static_cast<PointSet*>(*obj); std::string name; pSet->getObjectName(name); if (name == "Difference") { pDiffSet = pSet; pDiffSet->clear(true); break; } } if (pDiffSet == NULL) { pDiffSet = static_cast<PointSet*>(mpView->addObject(POINT_SET, true)); pDiffSet->setObjectName("Difference"); } // calculate the differences and errors std::vector<Point*> aPoints = pFirst->getPoints(); std::vector<Point*> bPoints = pSecond->getPoints(); if (aPoints.size() < 2 || bPoints.size() < 2) { return; } double mae = 0.0; double mse1 = 0.0; double mse2 = 0.0; for (size_t aIdx = 0; aIdx < aPoints.size(); ++aIdx) { Point* pA = aPoints[aIdx]; VERIFYNRV(pA); LocationType aVal = pA->getLocation(); LocationType newVal; // locate the associated spot in b for (size_t bIdx = 0; bIdx < bPoints.size(); ++bIdx) { Point* pB = bPoints[bIdx]; VERIFYNRV(pB); LocationType bVal = pB->getLocation(); double diff = aVal.mX - bVal.mX; if (fabs(diff) < 0.0000001) // a == b use the exact value { newVal.mX = aVal.mX; newVal.mY = bVal.mY - aVal.mY; break; } else if (diff < 0.0) // a < b found the upper point, interpolate { newVal.mX = aVal.mX; LocationType secondBVal; if (bIdx == 0) // we are at the start so continue the segment from the right { Point* pSecondB = bPoints[1]; VERIFYNRV(pSecondB); secondBVal = pSecondB->getLocation(); } else // grab the previous point for interpolation { Point* pSecondB = bPoints[bIdx-1]; VERIFYNRV(pSecondB); secondBVal = pSecondB->getLocation(); } // calculate slope-intercept double m = (bVal.mY - secondBVal.mY) / (bVal.mX - secondBVal.mX); double b = bVal.mY - m * bVal.mX; // find the y corresponding to the interpolated x newVal.mY = m * newVal.mX + b; newVal.mY -= aVal.mY; break; } } mae += fabs(newVal.mY); mse1 += newVal.mY * newVal.mY; mse2 += (newVal.mY * newVal.mY) / (aVal.mY * aVal.mY); pDiffSet->addPoint(newVal.mX, newVal.mY); } pDiffSet->setLineColor(ColorType(200, 0, 0)); mpView->refresh(); mae /= aPoints.size(); mse1 /= aPoints.size(); mse2 /= aPoints.size(); QMessageBox::information(mpView->getWidget(), "Comparison metrics", QString("Mean squared error (method 1): %1\n" "Mean squared error (method 2): %2\n" "Mean absolute error: %3").arg(mse1).arg(mse2).arg(mae), QMessageBox::Close); }