diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 16e7d0de9a..77ba4c03be 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -22,6 +22,7 @@ include_directories( ${CMAKE_BINARY_DIR}/Generated ) + #----------------------------------------------------------------- # Configuration of ERT depdendence #----------------------------------------------------------------- @@ -160,7 +161,7 @@ list( APPEND CPP_SOURCES ProjectDataModel/RimCalcScript.cpp ProjectDataModel/RimExportInputPropertySettings.cpp ProjectDataModel/RimBinaryExportSettings.cpp - + ProjectDataModel/Rim3dOverlayInfoConfig.cpp ProjectDataModel/RimUiTreeModelPdm.cpp ProjectDataModel/RimUiTreeView.cpp ) @@ -182,6 +183,8 @@ list( APPEND CPP_SOURCES UserInterface/RIPreferencesDialog.cpp UserInterface/RIResultInfoPanel.cpp UserInterface/RIViewer.cpp + UserInterface/RiuSimpleHistogramWidget.cpp + UserInterface/RIProcessMonitor.cpp ) @@ -240,6 +243,8 @@ list( REMOVE_ITEM RAW_SOURCES FileInterface/RifEclipseUnifiedRestartFileAccess.cpp FileInterface/RifReaderEclipseInput.cpp FileInterface/RifReaderEclipseOutput.cpp + UserInterface/RiuSimpleHistogramWidget.cpp + ) include( CustomPCH.cmake ) diff --git a/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt b/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt index 37d6a2333c..047816c6ef 100644 --- a/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt +++ b/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt @@ -27,9 +27,9 @@ include_directories( #----------------------------------------------------------------- # Ert configuration if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(ERT_ROOT_PATH "${ResInsight_SOURCE_DIR}/../ThirdParty/Ert" CACHE PATH "Root path for ERT distribution to link with") + set(ERT_ROOT_PATH "${ResInsight_SOURCE_DIR}/ThirdParty/Ert" CACHE PATH "Root path for ERT distribution to link with") elseif (${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(ERT_ROOT_PATH "${ResInsight_SOURCE_DIR}/../ThirdParty/Ert-windows" CACHE PATH "Root path for ERT distribution to link with") + set(ERT_ROOT_PATH "${ResInsight_SOURCE_DIR}/ThirdParty/Ert-windows" CACHE PATH "Root path for ERT distribution to link with") endif() set( ERT_ECL_PREFIX "ecl" CACHE STRING "Prefix path to use for ecl code in ert") set( ERT_UTIL_PREFIX "util" CACHE STRING "Prefix path to use for util code in ert") diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 6383b78625..cf3e8d3f14 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -98,11 +98,13 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigGridBase* localGrid, const e mainGrid->nodes().resize(nodeStartIndex + cellCount*8, cvf::Vec3d(0,0,0)); - caf::ProgressInfo progInfo(cellCount, ""); + int progTicks = 100; + double cellsPrProgressTick = cellCount/(float)progTicks; + caf::ProgressInfo progInfo(progTicks, ""); size_t computedCellCount = 0; // Loop over cells and fill them with data - #pragma omp parallel for +#pragma omp parallel for for (int gIdx = 0; gIdx < cellCount; ++gIdx) { RigCell& cell = mainGrid->cells()[cellStartIndex + gIdx]; @@ -149,8 +151,7 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigGridBase* localGrid, const e #pragma omp atomic computedCellCount++; - if (computedCellCount%5000 < 20) - progInfo.setProgress(computedCellCount); + progInfo.setProgress((int)(computedCellCount/cellsPrProgressTick)); } return true; } @@ -255,12 +256,13 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, mainGrid->cells().reserve(totalCellCount); mainGrid->nodes().reserve(8*totalCellCount); - caf::ProgressInfo progInfo(1 + numLGRs, ""); + caf::ProgressInfo progInfo(3 + numLGRs, ""); progInfo.setProgressDescription("Main Grid"); + progInfo.setNextProgressIncrement(3); transferGridCellData(mainGrid, mainGrid, mainEclGrid, 0); - progInfo.setProgress(1); + progInfo.setProgress(3); size_t globalActiveSize = ecl_grid_get_active_size(mainEclGrid); @@ -271,7 +273,7 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, ecl_grid_type* localEclGrid = ecl_grid_iget_lgr(mainEclGrid, lgrIdx); transferGridCellData(mainGrid, static_cast(mainGrid->gridByIndex(lgrIdx+1)), localEclGrid, globalActiveSize); globalActiveSize += ecl_grid_get_active_size(localEclGrid); - progInfo.setProgress(1 + lgrIdx); + progInfo.setProgress(3 + lgrIdx); } #endif @@ -286,7 +288,7 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, bool RifReaderEclipseOutput::open(const QString& fileName, RigReservoir* reservoir) { CVF_ASSERT(reservoir); - caf::ProgressInfo progInfo(4, ""); + caf::ProgressInfo progInfo(10, ""); progInfo.setProgressDescription("Reading Grid"); @@ -306,13 +308,15 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigReservoir* reservo ecl_grid_type * mainEclGrid = ecl_grid_alloc( fileName.toAscii().data() ); progInfo.setProgress(1); + progInfo.setNextProgressIncrement(6); progInfo.setProgressDescription("Transferring grid geometry"); if (!transferGeometry(mainEclGrid, reservoir)) return false; - + progInfo.setProgress(7); + progInfo.setProgressDescription("Releasing reader memory"); ecl_grid_free( mainEclGrid ); - progInfo.setProgress(2); + progInfo.setProgress(8); progInfo.setProgressDescription("Reading Result index"); #endif @@ -320,7 +324,7 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigReservoir* reservo // Build results meta data if (!buildMetaData(reservoir)) return false; - progInfo.setProgress(3); + progInfo.setProgress(9); progInfo.setProgressDescription("Reading Well information"); readWellCells(reservoir); diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp new file mode 100644 index 0000000000..df274a3b02 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -0,0 +1,154 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron 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 "RIStdInclude.h" + +#include "Rim3dOverlayInfoConfig.h" +#include "RimReservoirView.h" +#include "RIViewer.h" +#include "RimReservoir.h" +#include "RigReservoir.h" +#include "RigMainGrid.h" +#include "RigReservoirCellResults.h" + +CAF_PDM_SOURCE_INIT(Rim3dOverlayInfoConfig, "3dOverlayInfoConfig"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Rim3dOverlayInfoConfig::Rim3dOverlayInfoConfig() +{ + CAF_PDM_InitObject("Overlay 3D info", ":/Legend.png", "", ""); + + CAF_PDM_InitField(&showInfoText, "ShowInfoText", true, "Info Text", "", "", ""); + CAF_PDM_InitField(&showAnimProgress, "ShowAnimProgress", true, "Animation progress", "", "", ""); + CAF_PDM_InitField(&showHistogram, "ShowHistogram", true, "Histogram", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Rim3dOverlayInfoConfig::~Rim3dOverlayInfoConfig() +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void Rim3dOverlayInfoConfig::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + this->update3DInfo(); + m_reservoirView->viewer()->update(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void Rim3dOverlayInfoConfig::setPosition(cvf::Vec2ui position) +{ + m_position = position; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void Rim3dOverlayInfoConfig::update3DInfo() +{ + if (!m_reservoirView && m_reservoirView->viewer()) return; + + m_reservoirView->viewer()->showInfoText(showInfoText()); + m_reservoirView->viewer()->showHistogram(false); + m_reservoirView->viewer()->showAnimationProgress(showAnimProgress()); + + if (showInfoText()) + { + QString caseName; + QString totCellCount; + QString activeCellCount; + QString iSize, jSize, kSize; + QString propName; + QString cellEdgeName; + + if (m_reservoirView->eclipseCase()) + { + caseName = m_reservoirView->eclipseCase()->caseName(); + totCellCount = QString::number(m_reservoirView->eclipseCase()->reservoirData()->mainGrid()->cells().size()); + activeCellCount = QString::number(m_reservoirView->eclipseCase()->reservoirData()->mainGrid()->numActiveCells()); + iSize = QString::number(m_reservoirView->eclipseCase()->reservoirData()->mainGrid()->cellCountI()); + jSize = QString::number(m_reservoirView->eclipseCase()->reservoirData()->mainGrid()->cellCountJ()); + kSize = QString::number(m_reservoirView->eclipseCase()->reservoirData()->mainGrid()->cellCountK()); + propName = m_reservoirView->cellResult()->resultVariable(); + cellEdgeName = m_reservoirView->cellEdgeResult()->resultVariable(); + } + + QString infoText = QString( + "

-- %1 --

" + "Cell count: Total: %2 Active: %3
" + "Main Grid I,J,K: %4, %5, %6
").arg(caseName, totCellCount, activeCellCount, iSize, jSize, kSize); + + if (m_reservoirView->animationMode() && m_reservoirView->cellResult()->hasResult()) + { + infoText += QString("Cell Property: %1 ").arg(propName); + + double min, max; + double p10, p90; + size_t scalarIndex = m_reservoirView->cellResult()->gridScalarIndex(); + m_reservoirView->gridCellResults()->minMaxCellScalarValues(scalarIndex, min, max); + m_reservoirView->gridCellResults()->p10p90CellScalarValues(scalarIndex, p10, p90); + + infoText += QString("

Min: %1 P10: %2 P90: %3 Max: %4
").arg(min).arg(p10).arg(p90).arg(max); + } + + + if (m_reservoirView->animationMode() && m_reservoirView->cellEdgeResult()->hasResult()) + { + double min, max; + m_reservoirView->cellEdgeResult()->minMaxCellEdgeValues(min, max); + infoText += QString("Cell Edge Property: %1
Min: %2 Max: %3
").arg(cellEdgeName).arg(min).arg(max); + + } + + if ( m_reservoirView->cellResult()->hasDynamicResult() + || m_reservoirView->propertyFilterCollection()->hasActiveDynamicFilters() + || m_reservoirView->wellCollection()->hasVisibleWellPipes()) + { + int currentTimeStep = m_reservoirView->currentTimeStep(); + QDateTime date = m_reservoirView->gridCellResults()->timeStepDate(0, currentTimeStep); + infoText += QString("Time Step: %1 Time: %2").arg(currentTimeStep).arg(date.toString("dd.MMM yyyy")); + } + + m_reservoirView->viewer()->setInfoText(infoText); + } + + if (showHistogram()) + { + if (m_reservoirView->animationMode() && m_reservoirView->cellResult()->hasResult()) + { + double min, max; + double p10, p90; + size_t scalarIndex = m_reservoirView->cellResult()->gridScalarIndex(); + m_reservoirView->gridCellResults()->minMaxCellScalarValues(scalarIndex, min, max); + m_reservoirView->gridCellResults()->p10p90CellScalarValues(scalarIndex, p10, p90); + + m_reservoirView->viewer()->showHistogram(true); + m_reservoirView->viewer()->setHistogram(min, max, m_reservoirView->gridCellResults()->cellScalarValuesHistogram(scalarIndex)); + m_reservoirView->viewer()->setHistogramPercentiles(p10, p90); + } + } +} diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.h b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.h new file mode 100644 index 0000000000..c45814b432 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.h @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron 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 "cafPdmObject.h" +#include "cafPdmPointer.h" +#include "cafPdmField.h" +#include "cafAppEnum.h" + + +class RimReservoirView; +//================================================================================================== +/// +/// +//================================================================================================== +class Rim3dOverlayInfoConfig: public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + Rim3dOverlayInfoConfig(); + virtual ~Rim3dOverlayInfoConfig(); + + void update3DInfo(); + + void setReservoirView(RimReservoirView* ownerReservoirView) {m_reservoirView = ownerReservoirView; } + + void setPosition(cvf::Vec2ui position); + caf::PdmField showInfoText; + caf::PdmField showAnimProgress; + caf::PdmField showHistogram; + +protected: + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + +private: + caf::PdmPointer m_reservoirView; + + cvf::Vec2ui m_position; +}; diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index cf9b14b3fa..89297ae102 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -294,3 +294,36 @@ void RimCellEdgeResultSlot::updateIgnoredScalarValue() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCellEdgeResultSlot::minMaxCellEdgeValues(double& min, double& max) +{ + CVF_ASSERT(min && max); + + double globalMin, globalMax; + globalMin = HUGE_VAL; + globalMax = -HUGE_VAL; + + size_t resultIndices[6]; + this->gridScalarIndices(resultIndices); + + size_t idx; + for (idx = 0; idx < 6; idx++) + { + if (resultIndices[idx] == cvf::UNDEFINED_SIZE_T) continue; + + { + double cMin, cMax; + m_reservoirView->gridCellResults()->minMaxCellScalarValues(resultIndices[idx], cMin, cMax); + + globalMin = CVF_MIN(globalMin, cMin); + globalMax = CVF_MAX(globalMax, cMax); + } + + } + + min = globalMin; + max = globalMax; +} + diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h index 5eb678d7ff..c37bc7577d 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h @@ -68,6 +68,7 @@ public: void loadResult(); bool hasResult() const; + void minMaxCellEdgeValues(double& min, double& max); protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index b2beb4bff9..f774bc0829 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -42,6 +42,7 @@ #include "cafCadNavigation.h" #include "cafCeetronNavigation.h" #include "RimReservoir.h" +#include "Rim3dOverlayInfoConfig.h" namespace caf { @@ -87,6 +88,10 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); + CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Overlay Info", "", "", ""); + overlayInfoConfig = new Rim3dOverlayInfoConfig(); + overlayInfoConfig->setReservoirView(this); + CAF_PDM_InitField(&name, "UserDescription", QString(""), "Name", "", "", ""); CAF_PDM_InitField(&scaleZ, "GridZScale", 1.0, "Z Scale", "", "Scales the scene in the Z direction", ""); CAF_PDM_InitField(&showWindow, "ShowWindow", true, "Show 3D viewer", "", "", ""); @@ -144,6 +149,8 @@ RimReservoirView::~RimReservoirView() { delete this->cellResult(); delete this->cellEdgeResult(); + delete this->overlayInfoConfig(); + delete rangeFilterCollection(); delete propertyFilterCollection(); @@ -645,6 +652,7 @@ void RimReservoirView::updateCurrentTimeStep() } } + overlayInfoConfig()->update3DInfo(); updateLegends(); } @@ -691,6 +699,7 @@ void RimReservoirView::loadDataAndUpdate() createDisplayModel(); updateDisplayModelVisibility(); setDefaultView(); + overlayInfoConfig()->update3DInfo(); if (animationMode && m_viewer) { @@ -1018,31 +1027,8 @@ void RimReservoirView::updateLegends() if (this->cellEdgeResult()->hasResult()) { - double localMin, localMax; - localMin = HUGE_VAL; - localMax = -HUGE_VAL; double globalMin, globalMax; - globalMin = HUGE_VAL; - globalMax = -HUGE_VAL; - - size_t resultIndices[6]; - this->cellEdgeResult()->gridScalarIndices(resultIndices); - - size_t idx; - for (idx = 0; idx < 6; idx++) - { - if (resultIndices[idx] == cvf::UNDEFINED_SIZE_T) continue; - - { - double min, max; - results->minMaxCellScalarValues(resultIndices[idx], min, max); - - globalMin = CVF_MIN(globalMin, min); - globalMax = CVF_MAX(globalMax, max); - } - - } - + this->cellEdgeResult()->minMaxCellEdgeValues(globalMin, globalMax); this->cellEdgeResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, globalMin, globalMax); m_viewer->setColorLegend2(this->cellEdgeResult()->legendConfig->legend()); this->cellEdgeResult()->legendConfig->legend()->setTitle(cvfqt::Utils::fromQString(QString("Edge Results: \n") + this->cellEdgeResult()->resultVariable)); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index d1866bb8f6..918536910b 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -30,6 +30,7 @@ #include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilter.h" #include "RimCellPropertyFilterCollection.h" +#include "Rim3dOverlayInfoConfig.h" #include "cvfMatrix4.h" #include "cvfStructGridGeometryGenerator.h" @@ -86,6 +87,7 @@ public: caf::PdmField cellResult; caf::PdmField cellEdgeResult; + caf::PdmField overlayInfoConfig; caf::PdmField scaleZ; caf::PdmField showWindow; diff --git a/ApplicationCode/ProjectDataModel/RimResultReservoir.cpp b/ApplicationCode/ProjectDataModel/RimResultReservoir.cpp index 3a616984b0..00ef1333a3 100644 --- a/ApplicationCode/ProjectDataModel/RimResultReservoir.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultReservoir.cpp @@ -44,9 +44,10 @@ RimResultReservoir::RimResultReservoir() //-------------------------------------------------------------------------------------------------- bool RimResultReservoir::openEclipseGridFile() { - caf::ProgressInfo progInfo(2, "Reading Eclipse Grid File"); + caf::ProgressInfo progInfo(20, "Reading Eclipse Grid File"); progInfo.setProgressDescription("Open Grid File"); + progInfo.setNextProgressIncrement(19); // Early exit if reservoir data is created if (m_rigReservoir.notNull()) return true; @@ -83,7 +84,7 @@ bool RimResultReservoir::openEclipseGridFile() m_rigReservoir = reservoir; } - progInfo.setProgress(1); + progInfo.setProgress(19); CVF_ASSERT(m_rigReservoir.notNull()); CVF_ASSERT(readerInterface.notNull()); diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirCellResults.cpp b/ApplicationCode/ReservoirDataModel/RigReservoirCellResults.cpp index 5a8fb7dc04..6aa4f5c3d5 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirCellResults.cpp +++ b/ApplicationCode/ReservoirDataModel/RigReservoirCellResults.cpp @@ -121,6 +121,57 @@ void RigReservoirCellResults::minMaxCellScalarValues(size_t scalarResultIndex, s m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].second= max; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RigReservoirCellResults::cellScalarValuesHistogram(size_t scalarResultIndex) +{ + CVF_ASSERT(scalarResultIndex < resultCount()); + + // Extend array and cache vars + + if (scalarResultIndex >= m_histograms.size() ) + { + m_histograms.resize(resultCount()); + m_p10p90.resize(resultCount(), std::make_pair(HUGE_VAL, HUGE_VAL)); + } + + if (m_histograms[scalarResultIndex].size()) + { + return m_histograms[scalarResultIndex]; + + } + + double min; + double max; + size_t nBins = 100; + this->minMaxCellScalarValues( scalarResultIndex, min, max ); + RigHistogramCalculator histCalc(min, max, nBins, &m_histograms[scalarResultIndex]); + + for (size_t tsIdx = 0; tsIdx < this->timeStepCount(scalarResultIndex); tsIdx++) + { + std::vector& values = m_cellScalarResults[scalarResultIndex][tsIdx]; + + histCalc.addData(values); + } + + m_p10p90[scalarResultIndex].first = histCalc.calculatePercentil(0.1); + m_p10p90[scalarResultIndex].second = histCalc.calculatePercentil(0.9); + + return m_histograms[scalarResultIndex]; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigReservoirCellResults::p10p90CellScalarValues(size_t scalarResultIndex, double& p10, double& p90) +{ + const std::vector& histogr = cellScalarValuesHistogram( scalarResultIndex); + p10 = m_p10p90[scalarResultIndex].first; + p90 = m_p10p90[scalarResultIndex].second; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -417,6 +468,17 @@ bool RigReservoirCellResults::isUsingGlobalActiveIndex(size_t scalarResultIndex) return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QDateTime RigReservoirCellResults::timeStepDate(size_t scalarResultIndex, size_t timeStepIndex) const +{ + if (scalarResultIndex < m_resultInfos.size() && (size_t)(m_resultInfos[scalarResultIndex].m_timeStepDates.size()) > timeStepIndex) + return m_resultInfos[scalarResultIndex].m_timeStepDates[timeStepIndex]; + else + return QDateTime(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -496,4 +558,3 @@ void RigReservoirCellResults::clearAllResults() m_cellScalarResults[i].clear(); } } - diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirCellResults.h b/ApplicationCode/ReservoirDataModel/RigReservoirCellResults.h index 75bc2c437f..5101f4f417 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirCellResults.h +++ b/ApplicationCode/ReservoirDataModel/RigReservoirCellResults.h @@ -21,6 +21,7 @@ #include "RimDefines.h" #include #include +#include class RifReaderInterface; class RigMainGrid; @@ -39,6 +40,8 @@ public: void recalculateMinMax(size_t scalarResultIndex); void minMaxCellScalarValues(size_t scalarResultIndex, double& min, double& max); void minMaxCellScalarValues(size_t scalarResultIndex, size_t timeStepIndex, double& min, double& max); + const std::vector& cellScalarValuesHistogram(size_t scalarResultIndex); + void p10p90CellScalarValues(size_t scalarResultIndex, double& p10, double& p90); // Access meta-information about the results size_t resultCount() const; @@ -46,6 +49,8 @@ public: size_t maxTimeStepCount() const; QStringList resultNames(RimDefines::ResultCatType type) const; bool isUsingGlobalActiveIndex(size_t scalarResultIndex) const; + + QDateTime timeStepDate(size_t scalarResultIndex, size_t timeStepIndex) const; QList timeStepDates(size_t scalarResultIndex) const; void setTimeStepDates(size_t scalarResultIndex, const QList& dates); @@ -69,6 +74,9 @@ public: private: std::vector< std::vector< std::vector > > m_cellScalarResults; ///< Scalar results for each timestep for each Result index (ResultVariable) std::vector< std::pair > m_maxMinValues; ///< Max min values for each Result index + std::vector< std::vector > m_histograms; ///< Histogram for each Result Index + std::vector< std::pair > m_p10p90; ///< P10 and p90 values for each Result Index + std::vector< std::vector< std::pair > > m_maxMinValuesPrTs; ///< Max min values for each timestep and Result index class ResultInfo @@ -90,3 +98,80 @@ private: }; +class RigHistogramCalculator +{ +public: + RigHistogramCalculator(double min, double max, size_t nBins, std::vector* histogram) + { + CVF_ASSERT(histogram); + CVF_ASSERT(nBins > 0); + + if (max == min) { nBins = 1; } // Avoid dividing on 0 range + + m_histogram = histogram; + m_min = min; + m_observationCount = 0; + + // Initialize bins + m_histogram->resize(nBins); + for (size_t i = 0; i < m_histogram->size(); ++i) (*m_histogram)[i] = 0; + + m_range = max - min; + maxIndex = nBins-1; + } + + void addData(const std::vector& data) + { + CVF_ASSERT(m_histogram); + for (size_t i = 0; i < data.size(); ++i) + { + size_t index = 0; + + if (maxIndex > 0) index = (size_t)(maxIndex*(data[i] - m_min)/m_range); + + if(index < m_histogram->size()) // Just clip to the max min range (-index will overflow to positive ) + { + (*m_histogram)[index]++; + m_observationCount++; + } + } + } + + /// Calculates the estimated percentile from the histogram. + /// the percentile is the domain value at which pVal of the observations are below it. + /// Will only consider observed values between min and max, as all other values are discarded from the histogram + + double calculatePercentil(double pVal) + { + CVF_ASSERT(m_histogram); + CVF_ASSERT(m_histogram->size()); + CVF_ASSERT( 0.0 <= pVal && pVal <= 1.0); + + double pValObservationCount = pVal*m_observationCount; + if (pValObservationCount == 0.0) return m_min; + + size_t accObsCount = 0; + double binWidth = m_range/m_histogram->size(); + for (size_t binIdx = 0; binIdx < m_histogram->size(); ++binIdx) + { + size_t binObsCount = (*m_histogram)[binIdx]; + + accObsCount += binObsCount; + if (accObsCount >= pValObservationCount) + { + double domainValueAtEndOfBin = m_min + (binIdx+1) * binWidth; + double unusedFractionOfLastBin = (double)(accObsCount - pValObservationCount)/binObsCount; + return domainValueAtEndOfBin - unusedFractionOfLastBin*binWidth; + } + } + CVF_ASSERT(false); + return HUGE_VAL; + } + +private: + size_t maxIndex; + double m_range; + double m_min; + size_t m_observationCount; + std::vector* m_histogram; +}; diff --git a/ApplicationCode/UserInterface/RIViewer.cpp b/ApplicationCode/UserInterface/RIViewer.cpp index 70afa4dc86..0b34c92985 100644 --- a/ApplicationCode/UserInterface/RIViewer.cpp +++ b/ApplicationCode/UserInterface/RIViewer.cpp @@ -34,6 +34,8 @@ #include "cafFrameAnimationControl.h" #include "cafNavigationPolicy.h" #include "cafEffectGenerator.h" +#include "RiuSimpleHistogramWidget.h" + using cvf::ManipulatorTrackball; @@ -61,6 +63,47 @@ RIViewer::RIViewer(const QGLFormat& format, QWidget* parent) m_mainRendering->addOverlayItem(axisCross, cvf::OverlayItem::BOTTOM_LEFT, cvf::OverlayItem::VERTICAL); setReleaseOGLResourcesEachFrame(true); + + QColor c; + QPalette p = QApplication::palette(); + QColor frameAndTextColor(255, 255, 255, 200); + p.setColor(QPalette::Window, QColor(144, 173, 208, 180)); + p.setColor(QPalette::WindowText, frameAndTextColor); + + c = p.color(QPalette::Base ); + c.setAlpha(100); + p.setColor(QPalette::Base, c); + + //c = p.color(QPalette::AlternateBase ); + //c.setAlpha(0); + //p.setColor(QPalette::AlternateBase, c); + + + p.setColor(QPalette::Highlight, QColor(20, 20, 130, 100)); + + p.setColor(QPalette::HighlightedText, frameAndTextColor); + + p.setColor(QPalette::Dark, QColor(230, 250, 255, 100)); + + // Info Text + m_InfoLabel = new QLabel(); + m_InfoLabel->setPalette(p); + m_InfoLabel->setFrameShape(QFrame::Box); + m_showInfoText = true; + + // Animation progress bar + m_animationProgress = new QProgressBar(); + m_animationProgress->setPalette(p); + m_animationProgress->setFormat("Time Step: %v/%m"); + m_animationProgress->setTextVisible(true); + m_animationProgress->setStyle(new QCDEStyle()); + m_showAnimProgress = false; + + // Histogram + m_histogramWidget = new RiuSimpleHistogramWidget(); + m_histogramWidget->setPalette(p); + m_showHistogram = false; + } @@ -356,3 +399,95 @@ cvf::Part* RIViewer::pickPointAndFace(int winPosX, int winPosY, uint* faceHit, c return NULL; } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RIViewer::paintOverlayItems(QPainter* painter) +{ + int columnWidth = 200; + int margin = 5; + int yPos = margin; + + bool showAnimBar = false; + if (isAnimationActive() && frameCount() > 1) showAnimBar = true; + + //if (showAnimBar) columnWidth = CVF_MAX(columnWidth, m_animationProgress->width()); + if (m_showInfoText) columnWidth = CVF_MAX(columnWidth, m_InfoLabel->sizeHint().width()); + + int columnPos = this->width() - columnWidth - margin; + + if (showAnimBar && m_showAnimProgress) + { + m_animationProgress->setMinimum(0); + m_animationProgress->setMaximum(frameCount() - 1); + m_animationProgress->setValue(currentFrameIndex()); + m_animationProgress->resize(columnWidth, m_animationProgress->sizeHint().height()); + + m_animationProgress->render(painter,QPoint(columnPos, yPos)); + yPos += m_animationProgress->height() + margin; + + } + + if (m_showInfoText) + { + m_InfoLabel->resize(columnWidth, m_InfoLabel->sizeHint().height()); + m_InfoLabel->render(painter, QPoint(columnPos, yPos)); + yPos += m_InfoLabel->height() + margin; + } + + if (m_showHistogram) + { + m_histogramWidget->resize(columnWidth, 40); + m_histogramWidget->render(painter,QPoint(columnPos, yPos)); + yPos += m_InfoLabel->height() + margin; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RIViewer::setInfoText(QString text) +{ + m_InfoLabel->setText(text); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RIViewer::showInfoText(bool enable) +{ + m_showInfoText = enable; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RIViewer::setHistogram(double min, double max, const std::vector& histogram) +{ + m_histogramWidget->setHistogramData(min, max, histogram); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RIViewer::setHistogramPercentiles(double pmin, double pmax) +{ + m_histogramWidget->setPercentiles(pmin, pmax); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RIViewer::showAnimationProgress(bool enable) +{ + m_showAnimProgress = enable; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RIViewer::showHistogram(bool enable) +{ + m_showHistogram = enable; +} diff --git a/ApplicationCode/UserInterface/RIViewer.h b/ApplicationCode/UserInterface/RIViewer.h index c0bda1ad9c..1853cb6e90 100644 --- a/ApplicationCode/UserInterface/RIViewer.h +++ b/ApplicationCode/UserInterface/RIViewer.h @@ -26,6 +26,9 @@ #include "cafMouseState.h" class RimReservoirView; +class QLabel; +class QProgressBar; +class RiuSimpleHistogramWidget; namespace cvf { @@ -52,12 +55,21 @@ public: void setPointOfInterest(cvf::Vec3d poi); void setOwnerReservoirView(RimReservoirView * owner); void setEnableMask(unsigned int mask); + + void showInfoText(bool enable); + void setInfoText(QString text); + void showHistogram(bool enable); + void setHistogram(double min, double max, const std::vector& histogram); + void setHistogramPercentiles(double pmin, double pmax); + + void showAnimationProgress(bool enable); public slots: virtual void slotSetCurrentFrame(int frameIndex); virtual void slotEndAnimation(); protected: + void paintOverlayItems(QPainter* painter); void keyPressEvent(QKeyEvent* event); void mouseReleaseEvent(QMouseEvent* event); @@ -68,6 +80,16 @@ private: void updateLegends(); caf::QtMouseState m_mouseState; + QLabel* m_InfoLabel; + bool m_showInfoText;; + + QProgressBar* m_animationProgress; + bool m_showAnimProgress; + RiuSimpleHistogramWidget* m_histogramWidget; + bool m_showHistogram; + + + cvf::ref m_legend1; cvf::ref m_legend2; diff --git a/ApplicationCode/UserInterface/RiuSimpleHistogramWidget.cpp b/ApplicationCode/UserInterface/RiuSimpleHistogramWidget.cpp new file mode 100644 index 0000000000..2495f94ab4 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuSimpleHistogramWidget.cpp @@ -0,0 +1,97 @@ +#include "RiuSimpleHistogramWidget.h" +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuSimpleHistogramWidget::RiuSimpleHistogramWidget(QWidget * parent /*= 0*/, Qt::WindowFlags f /*= 0*/): +QWidget(parent, f) +{ + m_minPercentile = HUGE_VAL; + m_maxPercentile = HUGE_VAL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSimpleHistogramWidget::paintEvent(QPaintEvent* event) +{ + QPainter painter(this); + this->draw(&painter, 0, 0, this->width()-1, this->height()-1); +} + + + +void RiuSimpleHistogramWidget::draw(QPainter *painter,int x, int y, int width, int height ) +{ + + // Initialize variables + m_x = x; m_y = y; m_width = width; m_height = height; + + QRect r1(x,y,width, height); + + // Frame around it all; + QColor windowColor = palette().color(QPalette::Window);// QColor(144, 173, 208, 180); + QColor frameColor = palette().color(QPalette::WindowText);//QColor(220, 240, 255, 100); + QColor foregroundColor = palette().color(QPalette::Dark);// QColor(100, 141, 189); + + //painter->fillRect(r1, windowColor); + painter->setPen(frameColor); + painter->drawRect(r1); + + // Columns + painter->setPen(foregroundColor); + + int yColBottom = yPosFromCount(0); + + for ( size_t colIdx = 0; colIdx < m_histogramData.size(); ++colIdx) + { + size_t colCount = m_histogramData[colIdx]; + int yColTop = yPosFromCount(colCount); + int xColStart = xPosFromColIdx(colIdx); + int xColEnd = xPosFromColIdx(colIdx+1); + + // First line + painter->drawLine(xColStart, yColBottom, xColStart, yColTop); + // If we span more than one pixel with : + ++xColStart; + for (;xColStart < xColEnd; ++xColStart ) + { + painter->drawLine(xColStart, yColBottom, xColStart, yColTop); + } + + } + + // Vertical lines for percentiles + if (m_minPercentile != HUGE_VAL) + { + int xpos = xPosFromDomainValue(m_minPercentile); + painter->setPen(QColor(255, 0, 0, 200)); + painter->drawLine(xpos, y+1, xpos, y + height -1); + } + + // Vertical lines for percentiles + if (m_maxPercentile != HUGE_VAL) + { + int xpos = xPosFromDomainValue(m_maxPercentile); + painter->setPen(QColor(255, 0, 0, 200)); + painter->drawLine(xpos, y+1, xpos, y + height -1); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSimpleHistogramWidget::setHistogramData(double min, double max, const std::vector& histogram) +{ + m_min = min; + m_max = max; + m_histogramData = histogram; + + m_maxHistogramCount = 0; + for (size_t colIdx = 0; colIdx < m_histogramData.size(); ++colIdx) + { + if (m_maxHistogramCount < m_histogramData[colIdx]) m_maxHistogramCount = m_histogramData[colIdx] ; + } +} diff --git a/ApplicationCode/UserInterface/RiuSimpleHistogramWidget.h b/ApplicationCode/UserInterface/RiuSimpleHistogramWidget.h new file mode 100644 index 0000000000..c621100e00 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuSimpleHistogramWidget.h @@ -0,0 +1,37 @@ +#include +class QPaintEvent; +class QString; +class QStringList; + + +class RiuSimpleHistogramWidget : public QWidget +{ +public: + RiuSimpleHistogramWidget( QWidget * parent = 0, Qt::WindowFlags f = 0); + + void setHistogramData(double min, double max, const std::vector& histogram); + void setPercentiles(double pmin, double pmax) {m_minPercentile = pmin; m_maxPercentile = pmax;} + +protected: + virtual void paintEvent(QPaintEvent* event); + +private: + void draw(QPainter *painter,int x, int y, int width, int height ); + + int xPosFromColIdx(size_t colIdx) { return (int)(m_x + 1 + (m_width - 2 ) * colIdx/m_histogramData.size());} + int yPosFromCount(size_t colHeight) { return (int)(m_y + m_height - 1 - (m_height - 3 ) * colHeight/m_maxHistogramCount);} + + int xPosFromDomainValue(double value) { double range = m_max - m_min; return (range == 0.0) ? (m_x + 1) : (int)(m_x + 1 + (m_width - 2 ) * (value - m_min)/(m_max - m_min));} + + std::vector m_histogramData; + double m_max; + double m_min; + double m_minPercentile; + double m_maxPercentile; + size_t m_maxHistogramCount; + + double m_width; + double m_height; + double m_x; + double m_y; +}; diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bed0f9ee3..d4c7e9b2bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,13 +34,14 @@ ENDIF() set(CMAKE_MAJOR_VERSION 0) set(CMAKE_MINOR_VERSION 8) -set(CMAKE_PATCH_VERSION 6) +set(CMAKE_PATCH_VERSION 7) set(PRODUCTVER ${CMAKE_MAJOR_VERSION},${CMAKE_MINOR_VERSION},0,${CMAKE_PATCH_VERSION}) set(STRPRODUCTVER ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}) + ################################################################################ # Qt ################################################################################ diff --git a/cafUserInterface/cafProgressInfo.cpp b/cafUserInterface/cafProgressInfo.cpp index ed1f424d26..f5e966aa0b 100644 --- a/cafUserInterface/cafProgressInfo.cpp +++ b/cafUserInterface/cafProgressInfo.cpp @@ -29,9 +29,25 @@ namespace caf { //================================================================================================== /// /// \class caf::ProgressInfo +/// This class provides a simple frontend to the Qt progressbar, allowing distributed +/// progress calculation. /// +/// Create an instance of this object in the method/function that needs progress information +/// Then call incrementProgress() or setProgress() at proper times in your method. +/// When the method returns, the ProgressInfo destructor will clean up and finish. +/// The real beauty is that this class will magically interact with possible ProgressInfo instances +/// instantiated in function your method calls, providing a complete, consistent and detailed progress bar /// -/// +/// caf::ProgressInfo progInfo(3, "Open File"); +/// progInfo.setProgressDescription("Reading"); +/// ...readFile() +/// progInfo.incrementProgress(); +/// progInfo.setProgressDescription("Validating"); +/// ... validateData(); +/// progInfo.incrementProgress(); +/// progInfo.setProgressDescription("Building geometry"); +/// ... buildGeometry(); +/// progInfo.incrementProgress(); // not needed really, caus destructor will send progress to top. //================================================================================================== //-------------------------------------------------------------------------------------------------- @@ -51,7 +67,8 @@ ProgressInfo::~ProgressInfo() } //-------------------------------------------------------------------------------------------------- -/// +/// Sets a description of the step currently being executed. +/// Used to create a nice text in the progressDialog //-------------------------------------------------------------------------------------------------- void ProgressInfo::setProgressDescription(const QString& description) { @@ -66,6 +83,31 @@ void ProgressInfo::setProgress(int progressValue) ProgressInfoStatic::setProgress(progressValue); } +//-------------------------------------------------------------------------------------------------- +/// Increments progress by 1, or by the amount set by setNextProgressStepSize +//-------------------------------------------------------------------------------------------------- +void ProgressInfo::incrementProgress() +{ + ProgressInfoStatic::incrementProgress(); +} + +//-------------------------------------------------------------------------------------------------- +/// To make a certain operation span more of the progress bar than one tick, +/// set the number of progress ticks that you want it to use before calling it. +/// Eg. +/// caf::ProgressInfo progInfo(5, "Doing things"); +/// // ... Do one small thing +/// progInfo.incrementProgress(); +/// progInfo.setNextProgressStepSize(3); +/// // ... Some heavy function call with its own progress handling +/// progInfo.incrementProgress(); +/// +//-------------------------------------------------------------------------------------------------- +void ProgressInfo::setNextProgressIncrement(int nextStepSize) +{ + ProgressInfoStatic::setNextProgressIncrement(nextStepSize); +} + @@ -97,7 +139,7 @@ static QProgressDialog* progressDialog() } //-------------------------------------------------------------------------------------------------- -/// A static vector containing the maximum values for the progress on each sublevel +/// A static vector containing the maximum values for the progress on each sublevel (call stack level) //-------------------------------------------------------------------------------------------------- static std::vector& maxProgressStack() { @@ -127,7 +169,7 @@ static std::vector& descriptionStack() } //-------------------------------------------------------------------------------------------------- -/// +/// The actual progress value on each level (call stack level) 0 corresponds to the outermost function //-------------------------------------------------------------------------------------------------- static std::vector& progressStack() { @@ -136,6 +178,18 @@ static std::vector& progressStack() return m_progressStack; } +//-------------------------------------------------------------------------------------------------- +/// The number of progress ticks (span) on each callstack level that the level deeper (in callstack) shall fill +/// used to balance the progress, making some (heavy) operations span more of the progress bar +//-------------------------------------------------------------------------------------------------- +static std::vector& progressSpanStack() +{ + static std::vector m_progressSpanStack; + + return m_progressSpanStack; +} + + //-------------------------------------------------------------------------------------------------- /// Calculate the total number of progress values we would need if we only look at the levels from /// \a levelDepth and below (increasing subdivision) @@ -158,7 +212,8 @@ static int currentTotalProgress() int progress = 0; for (size_t i = 0; i < progressStack().size(); ++i) { - progress = progress + progressStack()[i]* subLevelsMaxProgressValue(i+1); + int span = (i < 1) ? 1 : progressSpanStack()[i-1]; + progress = progress + span*progressStack()[i]* subLevelsMaxProgressValue(i+1); } return progress; } @@ -185,8 +240,9 @@ static QString currentComposedLabel() if (!descriptionStack()[i].isEmpty()) labelText += descriptionStack()[i] ; if (!(titleStack()[i].isEmpty() && descriptionStack()[i].isEmpty())) labelText += "\n"; } - return labelText; - + labelText += "\n "; + return labelText; + } static bool isWrongThread() @@ -220,6 +276,7 @@ void ProgressInfoStatic::start(int maxProgressValue, const QString& title) maxProgressStack().push_back(maxProgressValue); progressStack().push_back(0); + progressSpanStack().push_back(1); titleStack().push_back(title); descriptionStack().push_back(""); @@ -250,12 +307,14 @@ void ProgressInfoStatic::setProgressDescription(const QString& description) void ProgressInfoStatic::setProgress(int progressValue) { if (isWrongThread()) return; + if (progressValue == progressStack().back()) return; // Do nothing if no progress. // Guard against the max value set for theis level if (progressValue < 0 ) progressValue = 0; if (progressValue > maxProgressStack().back() ) progressValue = maxProgressStack().back(); progressStack().back() = progressValue; + progressSpanStack().back() = 1; assert(currentTotalProgress() <= progressDialog()->maximum()); int totProg = currentTotalProgress(); @@ -265,6 +324,27 @@ void ProgressInfoStatic::setProgress(int progressValue) QCoreApplication::processEvents(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void ProgressInfoStatic::incrementProgress() +{ + assert(progressStack().size()); + ProgressInfoStatic::setProgress(progressStack().back() += progressSpanStack().back()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void ProgressInfoStatic::setNextProgressIncrement(int nextStepSize) +{ + assert(progressSpanStack().size()); + + progressSpanStack().back() = nextStepSize; +} + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -272,16 +352,16 @@ void ProgressInfoStatic::finished() { if (isWrongThread()) return; - assert(maxProgressStack().size() && progressStack().size() && titleStack().size() && descriptionStack().size()); + assert(maxProgressStack().size() && progressStack().size() && progressSpanStack().size() && titleStack().size() && descriptionStack().size()); // Set progress to max value, and leave it there until somebody touches the progress again - progressStack().back() = maxProgressStack().back(); - progressDialog()->setValue(currentTotalProgress()); + ProgressInfoStatic::setProgress(maxProgressStack().back()); // Pop all the stacks maxProgressStack().pop_back(); progressStack().pop_back(); + progressSpanStack().pop_back(); titleStack().pop_back(); descriptionStack().pop_back(); @@ -303,6 +383,4 @@ void ProgressInfoStatic::finished() } - - } // namespace caf diff --git a/cafUserInterface/cafProgressInfo.h b/cafUserInterface/cafProgressInfo.h index f27cb53eec..124700457e 100644 --- a/cafUserInterface/cafProgressInfo.h +++ b/cafUserInterface/cafProgressInfo.h @@ -31,6 +31,9 @@ public: ~ProgressInfo(); void setProgressDescription(const QString& description); void setProgress(int progressValue); + void incrementProgress(); + void setNextProgressIncrement(int nextStepSize); + }; @@ -41,6 +44,8 @@ public: static void setProgressDescription(const QString& description); static void setProgress(int progressValue); + static void incrementProgress(); + static void setNextProgressIncrement(int nextStepSize); static void finished(); }; diff --git a/cafViewer/cafViewer.cpp b/cafViewer/cafViewer.cpp index 42dc75ea81..48b513ae4a 100644 --- a/cafViewer/cafViewer.cpp +++ b/cafViewer/cafViewer.cpp @@ -414,6 +414,9 @@ void caf::Viewer::paintEvent(QPaintEvent* event) painter.endNativePainting(); #endif + // Call virtual method to allow subclasses to paint on the OpenGlCanvas + this->paintOverlayItems(&painter); + if (m_showPerfInfoHud && isShadersSupported()) { cvfqt::PerformanceInfoHud hud; @@ -664,3 +667,12 @@ void caf::Viewer::enableForcedImmediateMode(bool enable) m_mainRendering->renderEngine()->enableForcedImmediateMode(enable); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int caf::Viewer::currentFrameIndex() +{ + if (m_animationControl) return m_animationControl->currentFrame(); + else return 0; +} + diff --git a/cafViewer/cafViewer.h b/cafViewer/cafViewer.h index 2d9c93c726..016511d2a0 100644 --- a/cafViewer/cafViewer.h +++ b/cafViewer/cafViewer.h @@ -112,8 +112,18 @@ public: public slots: virtual void slotSetCurrentFrame(int frameIndex); virtual void slotEndAnimation(); + int currentFrameIndex(); protected: + // Method to override if painting directly on the OpenGl Canvas is needed. + virtual void paintOverlayItems(QPainter* painter) {}; + + // Overridable methods to setup the render system + virtual void setupMainRendering(); + virtual void setupRenderingSequence(); + virtual void optimizeClippingPlanes(); + + // Standard overrides. Not for overriding virtual void resizeGL(int width, int height); virtual void paintEvent(QPaintEvent* event); @@ -123,13 +133,6 @@ protected: m_navigationPolicy; bool m_navigationPolicyEnabled; - // Overridable methods to setup the render system - virtual void setupMainRendering(); - virtual void setupRenderingSequence(); - - virtual void optimizeClippingPlanes(); - void updateCamera(int width, int height); - // Actual rendering objects cvf::ref m_renderingSequence; cvf::ref m_mainScene; @@ -140,6 +143,8 @@ protected: double m_maxFarPlaneDistance; private: + void updateCamera(int width, int height); + void releaseOGlResourcesForCurrentFrame(); void debugShowRenderingSequencePartNames();