diff --git a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp index c1b3365db9..4e4ecfbc23 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp @@ -1,492 +1,492 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS -// -// ResInsight is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at -// for more details. -// -///////////////////////////////////////////////////////////////////////////////// - -#include "RimWellLogTrack.h" - -#include "RigStatisticsCalculator.h" - -#include "RimWellLogPlot.h" -#include "RimWellLogCurve.h" - -#include "RiuWellLogTrack.h" -#include "RiuWellLogPlot.h" -#include "RiuMainWindow.h" - -#include "cvfAssert.h" -#include "cvfMath.h" - -#include "qwt_scale_engine.h" - -#include -#include "RimWellFlowRateCurve.h" - -#define RI_LOGPLOTTRACK_MINX_DEFAULT -10.0 -#define RI_LOGPLOTTRACK_MAXX_DEFAULT 100.0 - - -CAF_PDM_SOURCE_INIT(RimWellLogTrack, "WellLogPlotTrack"); - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimWellLogTrack::RimWellLogTrack() -{ - CAF_PDM_InitObject("Track", ":/WellLogTrack16x16.png", "", ""); - - CAF_PDM_InitFieldNoDefault(&m_userName, "TrackDescription", "Name", "", "", ""); - m_userName.uiCapability()->setUiReadOnly(true); - - CAF_PDM_InitField(&m_show, "Show", true, "Show track", "", "", ""); - m_show.uiCapability()->setUiHidden(true); - - CAF_PDM_InitFieldNoDefault(&curves, "Curves", "", "", "", ""); - curves.uiCapability()->setUiHidden(true); - - CAF_PDM_InitField(&m_visibleXRangeMin, "VisibleXRangeMin", RI_LOGPLOTTRACK_MINX_DEFAULT, "Min", "", "", ""); - CAF_PDM_InitField(&m_visibleXRangeMax, "VisibleXRangeMax", RI_LOGPLOTTRACK_MAXX_DEFAULT, "Max", "", "", ""); - - CAF_PDM_InitField(&m_isAutoScaleXEnabled, "AutoScaleX", true, "Auto Scale", "", "", ""); - - CAF_PDM_InitField(&m_isLogarithmicScaleEnabled, "LogarithmicScaleX", false, "Logarithmic Scale", "", "", ""); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimWellLogTrack::~RimWellLogTrack() -{ - curves.deleteAllChildObjects(); - - if (m_wellLogTrackPlotWidget) - { - m_wellLogTrackPlotWidget->deleteLater(); - m_wellLogTrackPlotWidget = nullptr; - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::setDescription(const QString& description) -{ - m_userName = description; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) -{ - if (changedField == &m_show) - { - if (m_wellLogTrackPlotWidget) - { - m_wellLogTrackPlotWidget->setVisible(m_show()); - } - - RimWellLogPlot* wellLogPlot; - this->firstAncestorOrThisOfType(wellLogPlot); - if (wellLogPlot) - { - wellLogPlot->calculateAvailableDepthRange(); - wellLogPlot->updateDepthZoom(); - - RiuWellLogPlot* wellLogPlotViewer = dynamic_cast(wellLogPlot->viewWidget()); - if (wellLogPlotViewer) - { - wellLogPlotViewer->updateChildrenLayout(); - } - } - } - else if (changedField == &m_visibleXRangeMin || changedField == &m_visibleXRangeMax) - { - m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); - m_wellLogTrackPlotWidget->replot(); - m_isAutoScaleXEnabled = false; - } - else if (changedField == &m_isAutoScaleXEnabled) - { - if (m_isAutoScaleXEnabled()) - { - this->updateXZoom(); - computeAndSetXRangeMinForLogarithmicScale(); - - if (m_wellLogTrackPlotWidget) m_wellLogTrackPlotWidget->replot(); - } - } - else if (changedField == &m_isLogarithmicScaleEnabled) - { - updateAxisScaleEngine(); - - this->updateXZoom(); - computeAndSetXRangeMinForLogarithmicScale(); - - m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); - - m_wellLogTrackPlotWidget->replot(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::PdmFieldHandle* RimWellLogTrack::objectToggleField() -{ - return &m_show; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::PdmFieldHandle* RimWellLogTrack::userDescriptionField() -{ - return &m_userName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::addCurve(RimWellLogCurve* curve) -{ - curves.push_back(curve); - - if (m_wellLogTrackPlotWidget) - { - curve->setParentQwtPlot(m_wellLogTrackPlotWidget); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::insertCurve(RimWellLogCurve* curve, size_t index) -{ - curves.insert(index, curve); - // Todo: Mark curve data to use either TVD or MD - - if (m_wellLogTrackPlotWidget) - { - curve->setParentQwtPlot(m_wellLogTrackPlotWidget); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::removeCurve(RimWellLogCurve* curve) -{ - size_t index = curves.index(curve); - if ( index < curves.size()) - { - curves[index]->detachQwtCurve(); - curves.removeChildObject(curve); - } -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuWellLogTrack* RimWellLogTrack::viewer() -{ - return m_wellLogTrackPlotWidget; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::availableDepthRange(double* minimumDepth, double* maximumDepth) -{ - double minDepth = HUGE_VAL; - double maxDepth = -HUGE_VAL; - - size_t curveCount = curves.size(); - - for (size_t cIdx = 0; cIdx < curveCount; cIdx++) - { - double minCurveDepth = HUGE_VAL; - double maxCurveDepth = -HUGE_VAL; - - if (curves[cIdx]->isCurveVisible() && curves[cIdx]->depthRange(&minCurveDepth, &maxCurveDepth)) - { - if (minCurveDepth < minDepth) - { - minDepth = minCurveDepth; - } - - if (maxCurveDepth > maxDepth) - { - maxDepth = maxCurveDepth; - } - } - } - - *minimumDepth = minDepth; - *maximumDepth = maxDepth; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::loadDataAndUpdate() -{ - RimWellLogPlot* wellLogPlot; - firstAncestorOrThisOfType(wellLogPlot); - if (wellLogPlot && m_wellLogTrackPlotWidget) - { - m_wellLogTrackPlotWidget->setDepthTitle(wellLogPlot->depthPlotTitle()); - m_wellLogTrackPlotWidget->setXTitle(m_xAxisTitle); - } - - for (size_t cIdx = 0; cIdx < curves.size(); ++cIdx) - { - curves[cIdx]->loadDataAndUpdate(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::setXAxisTitle(const QString& text) -{ - m_xAxisTitle = text; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::recreateViewer() -{ - if (m_wellLogTrackPlotWidget == NULL) - { - m_wellLogTrackPlotWidget = new RiuWellLogTrack(this); - updateAxisScaleEngine(); - - for (size_t cIdx = 0; cIdx < curves.size(); ++cIdx) - { - curves[cIdx]->setParentQwtPlot(this->m_wellLogTrackPlotWidget); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::detachAllCurves() -{ - for (size_t cIdx = 0; cIdx < curves.size(); ++cIdx) - { - curves[cIdx]->detachQwtCurve(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::updateXZoomAndParentPlotDepthZoom() -{ - if (m_wellLogTrackPlotWidget) - { - RimWellLogPlot* wellLogPlot; - firstAncestorOrThisOfType(wellLogPlot); - if (wellLogPlot) - { - wellLogPlot->updateDepthZoom(); - } - - updateXZoom(); - - m_wellLogTrackPlotWidget->replot(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::updateXZoom() -{ - std::vector stackCurves = visibleStackedCurves(); - for (RimWellFlowRateCurve* stCurve: stackCurves) stCurve->updateStackedPlotData(); - - if (!m_isAutoScaleXEnabled()) - { - m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); - m_wellLogTrackPlotWidget->replot(); - return; - } - - double minValue = HUGE_VAL; - double maxValue = -HUGE_VAL; - - for (size_t cIdx = 0; cIdx < curves.size(); cIdx++) - { - double minCurveValue = HUGE_VAL; - double maxCurveValue = -HUGE_VAL; - - if (curves[cIdx]->isCurveVisible() && curves[cIdx]->valueRange(&minCurveValue, &maxCurveValue)) - { - if (minCurveValue < minValue) - { - minValue = minCurveValue; - } - - if (maxCurveValue > maxValue) - { - maxValue = maxCurveValue; - } - } - } - - if (minValue == HUGE_VAL) - { - minValue = RI_LOGPLOTTRACK_MINX_DEFAULT; - maxValue = RI_LOGPLOTTRACK_MAXX_DEFAULT; - } - - m_visibleXRangeMin = minValue; - m_visibleXRangeMax = maxValue; - - computeAndSetXRangeMinForLogarithmicScale(); - - if (m_wellLogTrackPlotWidget) m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); - - updateConnectedEditors(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimWellLogCurve* RimWellLogTrack::curveDefinitionFromCurve(const QwtPlotCurve* curve) const -{ - for (size_t idx = 0; idx < curves.size(); idx++) - { - if (curves[idx]->qwtPlotCurve() == curve) - { - return curves[idx]; - } - } - - return NULL; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) -{ - uiOrdering.add(&m_userName); - - caf::PdmUiGroup* gridGroup = uiOrdering.addNewGroup("Visible X Axis Range"); - gridGroup->add(&m_isAutoScaleXEnabled); - gridGroup->add(&m_visibleXRangeMin); - gridGroup->add(&m_visibleXRangeMax); - gridGroup->add(&m_isLogarithmicScaleEnabled); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -size_t RimWellLogTrack::curveIndex(RimWellLogCurve* curve) -{ - return curves.index(curve); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimWellLogTrack::isVisible() -{ - return m_show; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::updateAxisScaleEngine() -{ - if (m_isLogarithmicScaleEnabled) - { - m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xTop, new QwtLogScaleEngine); - - // NB! Must assign scale engine to bottom in order to make QwtPlotGrid work - m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine); - } - else - { - m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xTop, new QwtLinearScaleEngine); - - // NB! Must assign scale engine to bottom in order to make QwtPlotGrid work - m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine); - } -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::computeAndSetXRangeMinForLogarithmicScale() -{ - if (m_isAutoScaleXEnabled && m_isLogarithmicScaleEnabled) - { - double pos = HUGE_VAL; - double neg = -HUGE_VAL; - - for (size_t cIdx = 0; cIdx < curves.size(); cIdx++) - { - if (curves[cIdx]->isCurveVisible() && curves[cIdx]->curveData()) - { - RigStatisticsCalculator::posNegClosestToZero(curves[cIdx]->curveData()->xPlotValues(), pos, neg); - } - } - - if (pos != HUGE_VAL) - { - m_visibleXRangeMin = pos; - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::setLogarithmicScale(bool enable) -{ - m_isLogarithmicScaleEnabled = enable; - - updateAxisScaleEngine(); - computeAndSetXRangeMinForLogarithmicScale(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimWellLogTrack::visibleStackedCurves() -{ - std::vector stackedCurves; - for (RimWellLogCurve* curve: curves) - { - if (curve && curve->isCurveVisible() ) - { - RimWellFlowRateCurve* wfrCurve = dynamic_cast(curve); - if (wfrCurve) stackedCurves.push_back(wfrCurve); - } - } - - return stackedCurves; -} +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimWellLogTrack.h" + +#include "RigStatisticsCalculator.h" + +#include "RimWellLogPlot.h" +#include "RimWellLogCurve.h" + +#include "RiuWellLogTrack.h" +#include "RiuWellLogPlot.h" +#include "RiuMainWindow.h" + +#include "cvfAssert.h" +#include "cvfMath.h" + +#include "qwt_scale_engine.h" + +#include +#include "RimWellFlowRateCurve.h" + +#define RI_LOGPLOTTRACK_MINX_DEFAULT -10.0 +#define RI_LOGPLOTTRACK_MAXX_DEFAULT 100.0 + + +CAF_PDM_SOURCE_INIT(RimWellLogTrack, "WellLogPlotTrack"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellLogTrack::RimWellLogTrack() +{ + CAF_PDM_InitObject("Track", ":/WellLogTrack16x16.png", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_userName, "TrackDescription", "Name", "", "", ""); + m_userName.uiCapability()->setUiReadOnly(true); + + CAF_PDM_InitField(&m_show, "Show", true, "Show track", "", "", ""); + m_show.uiCapability()->setUiHidden(true); + + CAF_PDM_InitFieldNoDefault(&curves, "Curves", "", "", "", ""); + curves.uiCapability()->setUiHidden(true); + + CAF_PDM_InitField(&m_visibleXRangeMin, "VisibleXRangeMin", RI_LOGPLOTTRACK_MINX_DEFAULT, "Min", "", "", ""); + CAF_PDM_InitField(&m_visibleXRangeMax, "VisibleXRangeMax", RI_LOGPLOTTRACK_MAXX_DEFAULT, "Max", "", "", ""); + + CAF_PDM_InitField(&m_isAutoScaleXEnabled, "AutoScaleX", true, "Auto Scale", "", "", ""); + + CAF_PDM_InitField(&m_isLogarithmicScaleEnabled, "LogarithmicScaleX", false, "Logarithmic Scale", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellLogTrack::~RimWellLogTrack() +{ + curves.deleteAllChildObjects(); + + if (m_wellLogTrackPlotWidget) + { + m_wellLogTrackPlotWidget->deleteLater(); + m_wellLogTrackPlotWidget = nullptr; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::setDescription(const QString& description) +{ + m_userName = description; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + if (changedField == &m_show) + { + if (m_wellLogTrackPlotWidget) + { + m_wellLogTrackPlotWidget->setVisible(m_show()); + } + + RimWellLogPlot* wellLogPlot; + this->firstAncestorOrThisOfType(wellLogPlot); + if (wellLogPlot) + { + wellLogPlot->calculateAvailableDepthRange(); + wellLogPlot->updateDepthZoom(); + + RiuWellLogPlot* wellLogPlotViewer = dynamic_cast(wellLogPlot->viewWidget()); + if (wellLogPlotViewer) + { + wellLogPlotViewer->updateChildrenLayout(); + } + } + } + else if (changedField == &m_visibleXRangeMin || changedField == &m_visibleXRangeMax) + { + m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); + m_wellLogTrackPlotWidget->replot(); + m_isAutoScaleXEnabled = false; + } + else if (changedField == &m_isAutoScaleXEnabled) + { + if (m_isAutoScaleXEnabled()) + { + this->updateXZoom(); + computeAndSetXRangeMinForLogarithmicScale(); + + if (m_wellLogTrackPlotWidget) m_wellLogTrackPlotWidget->replot(); + } + } + else if (changedField == &m_isLogarithmicScaleEnabled) + { + updateAxisScaleEngine(); + + this->updateXZoom(); + computeAndSetXRangeMinForLogarithmicScale(); + + m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); + + m_wellLogTrackPlotWidget->replot(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimWellLogTrack::objectToggleField() +{ + return &m_show; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimWellLogTrack::userDescriptionField() +{ + return &m_userName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::addCurve(RimWellLogCurve* curve) +{ + curves.push_back(curve); + + if (m_wellLogTrackPlotWidget) + { + curve->setParentQwtPlot(m_wellLogTrackPlotWidget); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::insertCurve(RimWellLogCurve* curve, size_t index) +{ + curves.insert(index, curve); + // Todo: Mark curve data to use either TVD or MD + + if (m_wellLogTrackPlotWidget) + { + curve->setParentQwtPlot(m_wellLogTrackPlotWidget); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::removeCurve(RimWellLogCurve* curve) +{ + size_t index = curves.index(curve); + if ( index < curves.size()) + { + curves[index]->detachQwtCurve(); + curves.removeChildObject(curve); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellLogTrack* RimWellLogTrack::viewer() +{ + return m_wellLogTrackPlotWidget; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::availableDepthRange(double* minimumDepth, double* maximumDepth) +{ + double minDepth = HUGE_VAL; + double maxDepth = -HUGE_VAL; + + size_t curveCount = curves.size(); + + for (size_t cIdx = 0; cIdx < curveCount; cIdx++) + { + double minCurveDepth = HUGE_VAL; + double maxCurveDepth = -HUGE_VAL; + + if (curves[cIdx]->isCurveVisible() && curves[cIdx]->depthRange(&minCurveDepth, &maxCurveDepth)) + { + if (minCurveDepth < minDepth) + { + minDepth = minCurveDepth; + } + + if (maxCurveDepth > maxDepth) + { + maxDepth = maxCurveDepth; + } + } + } + + *minimumDepth = minDepth; + *maximumDepth = maxDepth; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::loadDataAndUpdate() +{ + RimWellLogPlot* wellLogPlot; + firstAncestorOrThisOfType(wellLogPlot); + if (wellLogPlot && m_wellLogTrackPlotWidget) + { + m_wellLogTrackPlotWidget->setDepthTitle(wellLogPlot->depthPlotTitle()); + m_wellLogTrackPlotWidget->setXTitle(m_xAxisTitle); + } + + for (size_t cIdx = 0; cIdx < curves.size(); ++cIdx) + { + curves[cIdx]->loadDataAndUpdate(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::setXAxisTitle(const QString& text) +{ + m_xAxisTitle = text; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::recreateViewer() +{ + if (m_wellLogTrackPlotWidget == NULL) + { + m_wellLogTrackPlotWidget = new RiuWellLogTrack(this); + updateAxisScaleEngine(); + + for (size_t cIdx = 0; cIdx < curves.size(); ++cIdx) + { + curves[cIdx]->setParentQwtPlot(this->m_wellLogTrackPlotWidget); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::detachAllCurves() +{ + for (size_t cIdx = 0; cIdx < curves.size(); ++cIdx) + { + curves[cIdx]->detachQwtCurve(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::updateXZoomAndParentPlotDepthZoom() +{ + if (m_wellLogTrackPlotWidget) + { + RimWellLogPlot* wellLogPlot; + firstAncestorOrThisOfType(wellLogPlot); + if (wellLogPlot) + { + wellLogPlot->updateDepthZoom(); + } + + updateXZoom(); + + m_wellLogTrackPlotWidget->replot(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::updateXZoom() +{ + std::vector stackCurves = visibleStackedCurves(); + for (RimWellFlowRateCurve* stCurve: stackCurves) stCurve->updateStackedPlotData(); + + if (!m_isAutoScaleXEnabled()) + { + m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); + m_wellLogTrackPlotWidget->replot(); + return; + } + + double minValue = HUGE_VAL; + double maxValue = -HUGE_VAL; + + for (size_t cIdx = 0; cIdx < curves.size(); cIdx++) + { + double minCurveValue = HUGE_VAL; + double maxCurveValue = -HUGE_VAL; + + if (curves[cIdx]->isCurveVisible() && curves[cIdx]->valueRange(&minCurveValue, &maxCurveValue)) + { + if (minCurveValue < minValue) + { + minValue = minCurveValue; + } + + if (maxCurveValue > maxValue) + { + maxValue = maxCurveValue; + } + } + } + + if (minValue == HUGE_VAL) + { + minValue = RI_LOGPLOTTRACK_MINX_DEFAULT; + maxValue = RI_LOGPLOTTRACK_MAXX_DEFAULT; + } + + m_visibleXRangeMin = minValue; + m_visibleXRangeMax = maxValue; + + computeAndSetXRangeMinForLogarithmicScale(); + + if (m_wellLogTrackPlotWidget) m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax); + + updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellLogCurve* RimWellLogTrack::curveDefinitionFromCurve(const QwtPlotCurve* curve) const +{ + for (size_t idx = 0; idx < curves.size(); idx++) + { + if (curves[idx]->qwtPlotCurve() == curve) + { + return curves[idx]; + } + } + + return NULL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + uiOrdering.add(&m_userName); + + caf::PdmUiGroup* gridGroup = uiOrdering.addNewGroup("Visible X Axis Range"); + gridGroup->add(&m_isAutoScaleXEnabled); + gridGroup->add(&m_visibleXRangeMin); + gridGroup->add(&m_visibleXRangeMax); + gridGroup->add(&m_isLogarithmicScaleEnabled); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RimWellLogTrack::curveIndex(RimWellLogCurve* curve) +{ + return curves.index(curve); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellLogTrack::isVisible() +{ + return m_show; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::updateAxisScaleEngine() +{ + if (m_isLogarithmicScaleEnabled) + { + m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xTop, new QwtLogScaleEngine); + + // NB! Must assign scale engine to bottom in order to make QwtPlotGrid work + m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine); + } + else + { + m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xTop, new QwtLinearScaleEngine); + + // NB! Must assign scale engine to bottom in order to make QwtPlotGrid work + m_wellLogTrackPlotWidget->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::computeAndSetXRangeMinForLogarithmicScale() +{ + if (m_isAutoScaleXEnabled && m_isLogarithmicScaleEnabled) + { + double pos = HUGE_VAL; + double neg = -HUGE_VAL; + + for (size_t cIdx = 0; cIdx < curves.size(); cIdx++) + { + if (curves[cIdx]->isCurveVisible() && curves[cIdx]->curveData()) + { + RigStatisticsCalculator::posNegClosestToZero(curves[cIdx]->curveData()->xPlotValues(), pos, neg); + } + } + + if (pos != HUGE_VAL) + { + m_visibleXRangeMin = pos; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::setLogarithmicScale(bool enable) +{ + m_isLogarithmicScaleEnabled = enable; + + updateAxisScaleEngine(); + computeAndSetXRangeMinForLogarithmicScale(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellLogTrack::visibleStackedCurves() +{ + std::vector stackedCurves; + for (RimWellLogCurve* curve: curves) + { + if (curve && curve->isCurveVisible() ) + { + RimWellFlowRateCurve* wfrCurve = dynamic_cast(curve); + if (wfrCurve) stackedCurves.push_back(wfrCurve); + } + } + + return stackedCurves; +} diff --git a/ApplicationCode/UserInterface/RiuWellLogTrack.cpp b/ApplicationCode/UserInterface/RiuWellLogTrack.cpp index a3ae2f30e0..bb2626894f 100644 --- a/ApplicationCode/UserInterface/RiuWellLogTrack.cpp +++ b/ApplicationCode/UserInterface/RiuWellLogTrack.cpp @@ -1,475 +1,475 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS -// -// ResInsight is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at -// for more details. -// -///////////////////////////////////////////////////////////////////////////////// - -#include "RiuWellLogTrack.h" - -#include "RiaApplication.h" - -#include "RimWellLogPlot.h" -#include "RimWellLogTrack.h" -#include "RimWellLogCurve.h" - -#include "RiuMainPlotWindow.h" - -#include "qwt_legend.h" -#include "qwt_plot_curve.h" -#include "qwt_plot_grid.h" -#include "qwt_plot_layout.h" -#include "qwt_plot_marker.h" -#include "qwt_plot_picker.h" -#include "qwt_scale_draw.h" -#include "qwt_scale_engine.h" -#include "qwt_symbol.h" -#include "qwt_text.h" - -#include -#include -#include -#include - -#include - -#define RIU_SCROLLWHEEL_ZOOMFACTOR 1.1 -#define RIU_SCROLLWHEEL_PANFACTOR 0.1 - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -class RiuWellLogTrackQwtPicker : public QwtPlotPicker -{ -public: - RiuWellLogTrackQwtPicker(QWidget *canvas) - : QwtPlotPicker(canvas) - { - } - -protected: - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - virtual QwtText trackerText(const QPoint& pos) const override - { - QwtText txt; - - const RiuWellLogTrack* wellLogTrack = dynamic_cast(this->plot()); - if (wellLogTrack) - { - QString depthString; - QString valueString; - QPointF closestPoint = wellLogTrack->closestCurvePoint(pos, &valueString, &depthString); - if (!closestPoint.isNull()) - { - QString str = valueString; - - if (!depthString.isEmpty()) - { - str += QString(" (%1)").arg(depthString); - } - - txt.setText(str); - } - - RiuWellLogTrack* nonConstPlot = const_cast(wellLogTrack); - nonConstPlot->updateClosestCurvePointMarker(closestPoint); - } - - return txt; - } -}; - - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuWellLogTrack::RiuWellLogTrack(RimWellLogTrack* plotTrackDefinition, QWidget* parent) - : QwtPlot(parent) -{ - Q_ASSERT(plotTrackDefinition); - m_plotTrackDefinition = plotTrackDefinition; - - m_grid = new QwtPlotGrid(); - m_grid->attach(this); - - setFocusPolicy(Qt::ClickFocus); - setDefaults(); - - // Create a plot picker to display values next to mouse cursor - m_plotPicker = new RiuWellLogTrackQwtPicker(this->canvas()); - m_plotPicker->setTrackerMode(QwtPicker::AlwaysOn); - - m_plotMarker = new QwtPlotMarker; - - // QwtPlotMarker takes ownership of the symbol, it is deleted in destructor of QwtPlotMarker - QwtSymbol* mySymbol = new QwtSymbol(QwtSymbol::Ellipse, Qt::NoBrush, QPen(Qt::black, 2.0), QSize(12, 12)); - m_plotMarker->setSymbol(mySymbol); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuWellLogTrack::~RiuWellLogTrack() -{ - m_grid->detach(); - delete m_grid; - - m_plotMarker->detach(); - delete m_plotMarker; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QPointF RiuWellLogTrack::closestCurvePoint(const QPoint& pos, QString* valueString, QString* depthString) const -{ - QPointF samplePoint; - - QwtPlotCurve* closestCurve = nullptr; - double distMin = DBL_MAX; - int closestPointSampleIndex = -1; - - const QwtPlotItemList& itmList = itemList(); - for (QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++) - { - if ((*it)->rtti() == QwtPlotItem::Rtti_PlotCurve) - { - QwtPlotCurve* candidateCurve = static_cast(*it); - double dist = DBL_MAX; - int candidateSampleIndex = candidateCurve->closestPoint(pos, &dist); - if (dist < distMin) - { - closestCurve = candidateCurve; - distMin = dist; - closestPointSampleIndex = candidateSampleIndex; - } - } - } - - if (closestCurve && distMin < 50) - { - samplePoint = closestCurve->sample(closestPointSampleIndex); - } - - if (depthString) - { - const QwtScaleDraw* depthAxisScaleDraw = axisScaleDraw(QwtPlot::yLeft); - if (depthAxisScaleDraw) - { - *depthString = depthAxisScaleDraw->label(samplePoint.y()).text(); - } - } - - if (valueString && closestCurve) - { - const QwtScaleDraw* xAxisScaleDraw = axisScaleDraw(closestCurve->xAxis()); - if (xAxisScaleDraw) - { - *valueString = xAxisScaleDraw->label(samplePoint.x()).text(); - } - } - - return samplePoint; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::updateClosestCurvePointMarker(const QPointF& pos) -{ - bool replotRequired = false; - - if (!pos.isNull()) - { - if (!m_plotMarker->plot()) - { - m_plotMarker->attach(this); - - replotRequired = true; - } - - if (m_plotMarker->value() != pos) - { - m_plotMarker->setValue(pos.x(), pos.y()); - - replotRequired = true; - } - } - else - { - if (m_plotMarker->plot()) - { - m_plotMarker->detach(); - - replotRequired = true; - } - } - - if (replotRequired) this->replot(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setDefaults() -{ - QPalette newPalette(palette()); - newPalette.setColor(QPalette::Background, Qt::white); - setPalette(newPalette); - - setAutoFillBackground(true); - setCanvasBackground(Qt::white); - - QFrame* canvasFrame = dynamic_cast(canvas()); - if (canvasFrame) - { - canvasFrame->setFrameShape(QFrame::NoFrame); - } - - canvas()->setMouseTracking(true); - canvas()->installEventFilter(this); - - QPen gridPen(Qt::SolidLine); - gridPen.setColor(Qt::lightGray); - m_grid->setPen(gridPen); - - enableAxis(QwtPlot::xTop, true); - enableAxis(QwtPlot::yLeft, true); - enableAxis(QwtPlot::xBottom, false); - enableAxis(QwtPlot::yRight, false); - - plotLayout()->setAlignCanvasToScales(true); - - axisScaleEngine(QwtPlot::yLeft)->setAttribute(QwtScaleEngine::Inverted, true); - - // Align the canvas with the actual min and max values of the curves - axisScaleEngine(QwtPlot::xTop)->setAttribute(QwtScaleEngine::Floating, true); - axisScaleEngine(QwtPlot::yLeft)->setAttribute(QwtScaleEngine::Floating, true); - setAxisScale(QwtPlot::yLeft, 1000, 0); - setAxisScale(QwtPlot::xTop, -10, 100); - - QFont xAxisFont = axisFont(QwtPlot::xTop); - xAxisFont.setPixelSize(9); - setAxisFont(QwtPlot::xTop, xAxisFont); - QwtText axisTitleX = axisTitle(QwtPlot::yLeft); - QFont xAxisTitleFont = axisTitleX.font(); - xAxisTitleFont.setPixelSize(9); - xAxisTitleFont.setBold(false); - axisTitleX.setFont(xAxisTitleFont); - axisTitleX.setRenderFlags(Qt::AlignRight); - setAxisTitle(QwtPlot::xTop, axisTitleX); - - QFont yAxisFont = axisFont(QwtPlot::yLeft); - yAxisFont.setPixelSize(9); - setAxisFont(QwtPlot::yLeft, yAxisFont); - - QwtText axisTitleY = axisTitle(QwtPlot::yLeft); - QFont yAxisTitleFont = axisTitleY.font(); - yAxisTitleFont.setPixelSize(9); - yAxisTitleFont.setBold(false); - axisTitleY.setFont(yAxisTitleFont); - axisTitleY.setRenderFlags(Qt::AlignRight); - setAxisTitle(QwtPlot::yLeft, axisTitleY); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setDepthZoom(double minDepth, double maxDepth) -{ - // Note: Y-axis is inverted - setAxisScale(QwtPlot::yLeft, maxDepth, minDepth); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setXRange(double min, double max) -{ - setAxisScale(QwtPlot::xTop, min, max); - setAxisScale(QwtPlot::xBottom, min, max); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setDepthTitle(const QString& title) -{ - QwtText axisTitleY = axisTitle(QwtPlot::yLeft); - axisTitleY.setText(title); - setAxisTitle(QwtPlot::yLeft, axisTitleY); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setXTitle(const QString& title) -{ - QwtText axisTitleX = axisTitle(QwtPlot::xTop); - axisTitleX.setText(title); - setAxisTitle(QwtPlot::xTop, axisTitleX); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiuWellLogTrack::eventFilter(QObject* watched, QEvent* event) -{ - if (watched == canvas()) - { - QWheelEvent* wheelEvent = dynamic_cast(event); - if (wheelEvent) - { - if (!m_plotTrackDefinition) - { - return QwtPlot::eventFilter(watched, event); - } - - RimWellLogPlot* plotDefinition; - m_plotTrackDefinition->firstAncestorOrThisOfType(plotDefinition); - if (!plotDefinition) - { - return QwtPlot::eventFilter(watched, event); - } - - if (wheelEvent->modifiers() & Qt::ControlModifier) - { - QwtScaleMap scaleMap = canvasMap(QwtPlot::yLeft); - double zoomCenter = scaleMap.invTransform(wheelEvent->pos().y()); - - if (wheelEvent->delta() > 0) - { - plotDefinition->setDepthZoomByFactorAndCenter(RIU_SCROLLWHEEL_ZOOMFACTOR, zoomCenter); - } - else - { - plotDefinition->setDepthZoomByFactorAndCenter(1.0/RIU_SCROLLWHEEL_ZOOMFACTOR, zoomCenter); - } - } - else - { - plotDefinition->panDepth(wheelEvent->delta() < 0 ? RIU_SCROLLWHEEL_PANFACTOR : -RIU_SCROLLWHEEL_PANFACTOR); - } - - event->accept(); - return true; - } - else - { - QMouseEvent* mouseEvent = dynamic_cast(event); - if (mouseEvent) - { - if (mouseEvent->button() == Qt::LeftButton && mouseEvent->type() == QMouseEvent::MouseButtonRelease) - { - selectClosestCurve(mouseEvent->pos()); - } - } - } - } - - return QwtPlot::eventFilter(watched, event); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::focusInEvent(QFocusEvent* event) -{ - if (m_plotTrackDefinition) - { - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(m_plotTrackDefinition); - clearFocus(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::selectClosestCurve(const QPoint& pos) -{ - QwtPlotCurve* closestCurve = NULL; - double distMin = DBL_MAX; - - const QwtPlotItemList& itmList = itemList(); - for (QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++) - { - if ((*it )->rtti() == QwtPlotItem::Rtti_PlotCurve ) - { - QwtPlotCurve* candidateCurve = static_cast(*it); - double dist = DBL_MAX; - candidateCurve->closestPoint(pos, &dist); - if (dist < distMin) - { - closestCurve = candidateCurve; - distMin = dist; - } - } - } - - if (closestCurve && distMin < 20) - { - RimWellLogCurve* selectedCurve = m_plotTrackDefinition->curveDefinitionFromCurve(closestCurve); - if (selectedCurve) - { - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(selectedCurve); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QSize RiuWellLogTrack::sizeHint() const -{ - return QSize(0, 0); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QSize RiuWellLogTrack::minimumSizeHint() const -{ - return QSize(0, 0); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::leaveEvent(QEvent *) -{ - if (m_plotMarker->plot()) - { - m_plotMarker->detach(); - - replot(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiuWellLogTrack::isRimTrackVisible() -{ - if (m_plotTrackDefinition) - { - return m_plotTrackDefinition->isVisible(); - } - - return false; -} - +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RiuWellLogTrack.h" + +#include "RiaApplication.h" + +#include "RimWellLogPlot.h" +#include "RimWellLogTrack.h" +#include "RimWellLogCurve.h" + +#include "RiuMainPlotWindow.h" + +#include "qwt_legend.h" +#include "qwt_plot_curve.h" +#include "qwt_plot_grid.h" +#include "qwt_plot_layout.h" +#include "qwt_plot_marker.h" +#include "qwt_plot_picker.h" +#include "qwt_scale_draw.h" +#include "qwt_scale_engine.h" +#include "qwt_symbol.h" +#include "qwt_text.h" + +#include +#include +#include +#include + +#include + +#define RIU_SCROLLWHEEL_ZOOMFACTOR 1.1 +#define RIU_SCROLLWHEEL_PANFACTOR 0.1 + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RiuWellLogTrackQwtPicker : public QwtPlotPicker +{ +public: + RiuWellLogTrackQwtPicker(QWidget *canvas) + : QwtPlotPicker(canvas) + { + } + +protected: + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + virtual QwtText trackerText(const QPoint& pos) const override + { + QwtText txt; + + const RiuWellLogTrack* wellLogTrack = dynamic_cast(this->plot()); + if (wellLogTrack) + { + QString depthString; + QString valueString; + QPointF closestPoint = wellLogTrack->closestCurvePoint(pos, &valueString, &depthString); + if (!closestPoint.isNull()) + { + QString str = valueString; + + if (!depthString.isEmpty()) + { + str += QString(" (%1)").arg(depthString); + } + + txt.setText(str); + } + + RiuWellLogTrack* nonConstPlot = const_cast(wellLogTrack); + nonConstPlot->updateClosestCurvePointMarker(closestPoint); + } + + return txt; + } +}; + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellLogTrack::RiuWellLogTrack(RimWellLogTrack* plotTrackDefinition, QWidget* parent) + : QwtPlot(parent) +{ + Q_ASSERT(plotTrackDefinition); + m_plotTrackDefinition = plotTrackDefinition; + + m_grid = new QwtPlotGrid(); + m_grid->attach(this); + + setFocusPolicy(Qt::ClickFocus); + setDefaults(); + + // Create a plot picker to display values next to mouse cursor + m_plotPicker = new RiuWellLogTrackQwtPicker(this->canvas()); + m_plotPicker->setTrackerMode(QwtPicker::AlwaysOn); + + m_plotMarker = new QwtPlotMarker; + + // QwtPlotMarker takes ownership of the symbol, it is deleted in destructor of QwtPlotMarker + QwtSymbol* mySymbol = new QwtSymbol(QwtSymbol::Ellipse, Qt::NoBrush, QPen(Qt::black, 2.0), QSize(12, 12)); + m_plotMarker->setSymbol(mySymbol); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellLogTrack::~RiuWellLogTrack() +{ + m_grid->detach(); + delete m_grid; + + m_plotMarker->detach(); + delete m_plotMarker; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QPointF RiuWellLogTrack::closestCurvePoint(const QPoint& pos, QString* valueString, QString* depthString) const +{ + QPointF samplePoint; + + QwtPlotCurve* closestCurve = nullptr; + double distMin = DBL_MAX; + int closestPointSampleIndex = -1; + + const QwtPlotItemList& itmList = itemList(); + for (QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++) + { + if ((*it)->rtti() == QwtPlotItem::Rtti_PlotCurve) + { + QwtPlotCurve* candidateCurve = static_cast(*it); + double dist = DBL_MAX; + int candidateSampleIndex = candidateCurve->closestPoint(pos, &dist); + if (dist < distMin) + { + closestCurve = candidateCurve; + distMin = dist; + closestPointSampleIndex = candidateSampleIndex; + } + } + } + + if (closestCurve && distMin < 50) + { + samplePoint = closestCurve->sample(closestPointSampleIndex); + } + + if (depthString) + { + const QwtScaleDraw* depthAxisScaleDraw = axisScaleDraw(QwtPlot::yLeft); + if (depthAxisScaleDraw) + { + *depthString = depthAxisScaleDraw->label(samplePoint.y()).text(); + } + } + + if (valueString && closestCurve) + { + const QwtScaleDraw* xAxisScaleDraw = axisScaleDraw(closestCurve->xAxis()); + if (xAxisScaleDraw) + { + *valueString = xAxisScaleDraw->label(samplePoint.x()).text(); + } + } + + return samplePoint; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogTrack::updateClosestCurvePointMarker(const QPointF& pos) +{ + bool replotRequired = false; + + if (!pos.isNull()) + { + if (!m_plotMarker->plot()) + { + m_plotMarker->attach(this); + + replotRequired = true; + } + + if (m_plotMarker->value() != pos) + { + m_plotMarker->setValue(pos.x(), pos.y()); + + replotRequired = true; + } + } + else + { + if (m_plotMarker->plot()) + { + m_plotMarker->detach(); + + replotRequired = true; + } + } + + if (replotRequired) this->replot(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogTrack::setDefaults() +{ + QPalette newPalette(palette()); + newPalette.setColor(QPalette::Background, Qt::white); + setPalette(newPalette); + + setAutoFillBackground(true); + setCanvasBackground(Qt::white); + + QFrame* canvasFrame = dynamic_cast(canvas()); + if (canvasFrame) + { + canvasFrame->setFrameShape(QFrame::NoFrame); + } + + canvas()->setMouseTracking(true); + canvas()->installEventFilter(this); + + QPen gridPen(Qt::SolidLine); + gridPen.setColor(Qt::lightGray); + m_grid->setPen(gridPen); + + enableAxis(QwtPlot::xTop, true); + enableAxis(QwtPlot::yLeft, true); + enableAxis(QwtPlot::xBottom, false); + enableAxis(QwtPlot::yRight, false); + + plotLayout()->setAlignCanvasToScales(true); + + axisScaleEngine(QwtPlot::yLeft)->setAttribute(QwtScaleEngine::Inverted, true); + + // Align the canvas with the actual min and max values of the curves + axisScaleEngine(QwtPlot::xTop)->setAttribute(QwtScaleEngine::Floating, true); + axisScaleEngine(QwtPlot::yLeft)->setAttribute(QwtScaleEngine::Floating, true); + setAxisScale(QwtPlot::yLeft, 1000, 0); + setAxisScale(QwtPlot::xTop, -10, 100); + + QFont xAxisFont = axisFont(QwtPlot::xTop); + xAxisFont.setPixelSize(9); + setAxisFont(QwtPlot::xTop, xAxisFont); + QwtText axisTitleX = axisTitle(QwtPlot::yLeft); + QFont xAxisTitleFont = axisTitleX.font(); + xAxisTitleFont.setPixelSize(9); + xAxisTitleFont.setBold(false); + axisTitleX.setFont(xAxisTitleFont); + axisTitleX.setRenderFlags(Qt::AlignRight); + setAxisTitle(QwtPlot::xTop, axisTitleX); + + QFont yAxisFont = axisFont(QwtPlot::yLeft); + yAxisFont.setPixelSize(9); + setAxisFont(QwtPlot::yLeft, yAxisFont); + + QwtText axisTitleY = axisTitle(QwtPlot::yLeft); + QFont yAxisTitleFont = axisTitleY.font(); + yAxisTitleFont.setPixelSize(9); + yAxisTitleFont.setBold(false); + axisTitleY.setFont(yAxisTitleFont); + axisTitleY.setRenderFlags(Qt::AlignRight); + setAxisTitle(QwtPlot::yLeft, axisTitleY); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogTrack::setDepthZoom(double minDepth, double maxDepth) +{ + // Note: Y-axis is inverted + setAxisScale(QwtPlot::yLeft, maxDepth, minDepth); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogTrack::setXRange(double min, double max) +{ + setAxisScale(QwtPlot::xTop, min, max); + setAxisScale(QwtPlot::xBottom, min, max); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogTrack::setDepthTitle(const QString& title) +{ + QwtText axisTitleY = axisTitle(QwtPlot::yLeft); + axisTitleY.setText(title); + setAxisTitle(QwtPlot::yLeft, axisTitleY); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogTrack::setXTitle(const QString& title) +{ + QwtText axisTitleX = axisTitle(QwtPlot::xTop); + axisTitleX.setText(title); + setAxisTitle(QwtPlot::xTop, axisTitleX); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuWellLogTrack::eventFilter(QObject* watched, QEvent* event) +{ + if (watched == canvas()) + { + QWheelEvent* wheelEvent = dynamic_cast(event); + if (wheelEvent) + { + if (!m_plotTrackDefinition) + { + return QwtPlot::eventFilter(watched, event); + } + + RimWellLogPlot* plotDefinition; + m_plotTrackDefinition->firstAncestorOrThisOfType(plotDefinition); + if (!plotDefinition) + { + return QwtPlot::eventFilter(watched, event); + } + + if (wheelEvent->modifiers() & Qt::ControlModifier) + { + QwtScaleMap scaleMap = canvasMap(QwtPlot::yLeft); + double zoomCenter = scaleMap.invTransform(wheelEvent->pos().y()); + + if (wheelEvent->delta() > 0) + { + plotDefinition->setDepthZoomByFactorAndCenter(RIU_SCROLLWHEEL_ZOOMFACTOR, zoomCenter); + } + else + { + plotDefinition->setDepthZoomByFactorAndCenter(1.0/RIU_SCROLLWHEEL_ZOOMFACTOR, zoomCenter); + } + } + else + { + plotDefinition->panDepth(wheelEvent->delta() < 0 ? RIU_SCROLLWHEEL_PANFACTOR : -RIU_SCROLLWHEEL_PANFACTOR); + } + + event->accept(); + return true; + } + else + { + QMouseEvent* mouseEvent = dynamic_cast(event); + if (mouseEvent) + { + if (mouseEvent->button() == Qt::LeftButton && mouseEvent->type() == QMouseEvent::MouseButtonRelease) + { + selectClosestCurve(mouseEvent->pos()); + } + } + } + } + + return QwtPlot::eventFilter(watched, event); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogTrack::focusInEvent(QFocusEvent* event) +{ + if (m_plotTrackDefinition) + { + RiaApplication::instance()->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(m_plotTrackDefinition); + clearFocus(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogTrack::selectClosestCurve(const QPoint& pos) +{ + QwtPlotCurve* closestCurve = NULL; + double distMin = DBL_MAX; + + const QwtPlotItemList& itmList = itemList(); + for (QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++) + { + if ((*it )->rtti() == QwtPlotItem::Rtti_PlotCurve ) + { + QwtPlotCurve* candidateCurve = static_cast(*it); + double dist = DBL_MAX; + candidateCurve->closestPoint(pos, &dist); + if (dist < distMin) + { + closestCurve = candidateCurve; + distMin = dist; + } + } + } + + if (closestCurve && distMin < 20) + { + RimWellLogCurve* selectedCurve = m_plotTrackDefinition->curveDefinitionFromCurve(closestCurve); + if (selectedCurve) + { + RiaApplication::instance()->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(selectedCurve); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiuWellLogTrack::sizeHint() const +{ + return QSize(0, 0); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiuWellLogTrack::minimumSizeHint() const +{ + return QSize(0, 0); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogTrack::leaveEvent(QEvent *) +{ + if (m_plotMarker->plot()) + { + m_plotMarker->detach(); + + replot(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuWellLogTrack::isRimTrackVisible() +{ + if (m_plotTrackDefinition) + { + return m_plotTrackDefinition->isVisible(); + } + + return false; +} + diff --git a/ApplicationCode/UserInterface/RiuWellLogTrack.h b/ApplicationCode/UserInterface/RiuWellLogTrack.h index 3502f3f748..9338791a23 100644 --- a/ApplicationCode/UserInterface/RiuWellLogTrack.h +++ b/ApplicationCode/UserInterface/RiuWellLogTrack.h @@ -1,77 +1,77 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS -// -// ResInsight is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at -// for more details. -// -///////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include "qwt_plot.h" - -#include "cafPdmPointer.h" - -class RimWellLogTrack; - -class QwtLegend; -class QwtPicker; -class QwtPlotGrid; -class QwtPlotMarker; - -class QEvent; - -//================================================================================================== -// -// -// -//================================================================================================== -class RiuWellLogTrack : public QwtPlot -{ - Q_OBJECT - -public: - RiuWellLogTrack(RimWellLogTrack* plotTrackDefinition, QWidget* parent = NULL); - virtual ~RiuWellLogTrack(); - - void setDepthZoom(double minDepth, double maxDepth); - void setDepthTitle(const QString& title); - void setXTitle(const QString& title); - - void setXRange(double min, double max); - - bool isRimTrackVisible(); - -protected: - virtual bool eventFilter(QObject* watched, QEvent* event); - virtual void focusInEvent(QFocusEvent* event); - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - virtual void leaveEvent(QEvent *) override; - -private: - friend class RiuWellLogTrackQwtPicker; - QPointF closestCurvePoint(const QPoint& pos, QString* valueString, QString* depthString) const; - void updateClosestCurvePointMarker(const QPointF& pos); - - void setDefaults(); - void selectClosestCurve(const QPoint& pos); - -private: - caf::PdmPointer m_plotTrackDefinition; - QwtPlotGrid* m_grid; - QwtPicker* m_plotPicker; - QwtPlotMarker* m_plotMarker; -}; +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "qwt_plot.h" + +#include "cafPdmPointer.h" + +class RimWellLogTrack; + +class QwtLegend; +class QwtPicker; +class QwtPlotGrid; +class QwtPlotMarker; + +class QEvent; + +//================================================================================================== +// +// +// +//================================================================================================== +class RiuWellLogTrack : public QwtPlot +{ + Q_OBJECT + +public: + RiuWellLogTrack(RimWellLogTrack* plotTrackDefinition, QWidget* parent = NULL); + virtual ~RiuWellLogTrack(); + + void setDepthZoom(double minDepth, double maxDepth); + void setDepthTitle(const QString& title); + void setXTitle(const QString& title); + void setXRange(double min, double max); + + bool isRimTrackVisible(); + +protected: + virtual bool eventFilter(QObject* watched, QEvent* event); + virtual void focusInEvent(QFocusEvent* event); + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + virtual void leaveEvent(QEvent *) override; + +private: + friend class RiuWellLogTrackQwtPicker; + QPointF closestCurvePoint(const QPoint& pos, QString* valueString, QString* depthString) const; + void updateClosestCurvePointMarker(const QPointF& pos); + + void setDefaults(); + void selectClosestCurve(const QPoint& pos); + +private: + caf::PdmPointer m_plotTrackDefinition; + QwtPlotGrid* m_grid; + QwtPicker* m_plotPicker; + QwtPlotMarker* m_plotMarker; +}; +