Merge branch 'dev' into measurement

This commit is contained in:
Bjørn Erik Jensen 2018-12-21 10:08:41 +01:00
commit 5976298267
76 changed files with 15220 additions and 474 deletions

View File

@ -1,17 +1,18 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
// Copyright (C) 2017 Statoil ASA
//
//
// 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 <http://www.gnu.org/licenses/gpl.html>
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
@ -21,11 +22,13 @@
#include <algorithm>
//--------------------------------------------------------------------------------------------------
///
/// Uses W3.org relative luminance calculation taking into account the different luminance of the different colors
/// https://www.w3.org/TR/WCAG20-TECHS/G18.html
/// Luminance is between [0, 1] so anything above 0.5 is considered in the bright half of the spectrum.
//--------------------------------------------------------------------------------------------------
bool RiaColorTools::isBrightnessAboveThreshold(cvf::Color3f backgroundColor)
{
if (backgroundColor.r() + backgroundColor.g() + backgroundColor.b() > 1.5f)
if (relativeLuminance(backgroundColor) > 0.5)
{
return true;
}
@ -34,7 +37,7 @@ bool RiaColorTools::isBrightnessAboveThreshold(cvf::Color3f backgroundColor)
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RiaColorTools::computeOffsetColor(cvf::Color3f color, float offsetFactor)
{
@ -55,13 +58,12 @@ cvf::Color3f RiaColorTools::computeOffsetColor(cvf::Color3f color, float offsetF
gridB = color.b() + (1.0f - color.b()) * offsetFactor;
}
return cvf::Color3f(cvf::Math::clamp(gridR, 0.0f, 1.0f),
cvf::Math::clamp(gridG, 0.0f, 1.0f),
cvf::Math::clamp(gridB, 0.0f, 1.0f));
return cvf::Color3f(
cvf::Math::clamp(gridR, 0.0f, 1.0f), cvf::Math::clamp(gridG, 0.0f, 1.0f), cvf::Math::clamp(gridB, 0.0f, 1.0f));
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RiaColorTools::darkContrastColor()
{
@ -69,7 +71,7 @@ cvf::Color3f RiaColorTools::darkContrastColor()
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RiaColorTools::brightContrastColor()
{
@ -77,15 +79,35 @@ cvf::Color3f RiaColorTools::brightContrastColor()
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RiaColorTools::constrastColor(cvf::Color3f backgroundColor)
cvf::Color3f RiaColorTools::darkContrastColorSofter()
{
return cvf::Color3f::fromByteColor(30, 30, 30);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RiaColorTools::brightContrastColorSofter()
{
return cvf::Color3f::fromByteColor(200, 200, 200);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RiaColorTools::constrastColor(cvf::Color3f backgroundColor, bool softerContrast)
{
if (isBrightnessAboveThreshold(backgroundColor))
{
if (softerContrast)
return darkContrastColorSofter();
return darkContrastColor();
}
if (softerContrast)
return brightContrastColorSofter();
return brightContrastColor();
}
@ -106,3 +128,38 @@ QColor RiaColorTools::toQColor(cvf::Color4f color)
{
return toQColor(color.toColor3f(), color.a());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RiaColorTools::contrastRatio(cvf::Color3f color1, cvf::Color3f color2)
{
float L1 = relativeLuminance(color1);
float L2 = relativeLuminance(color2);
float Lmin = std::min(L1, L2);
float Lmax = std::max(L1, L2);
return (Lmax + 0.05) / (Lmin + 0.05);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RiaColorTools::relativeLuminance(cvf::Color3f backgroundColor)
{
float R = calculateNonLinearColorValue(backgroundColor.r());
float G = calculateNonLinearColorValue(backgroundColor.g());
float B = calculateNonLinearColorValue(backgroundColor.b());
double luminance = 0.2126 * R + 0.7152 * G + 0.0722 * B;
return luminance;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RiaColorTools::calculateNonLinearColorValue(float colorFraction)
{
return colorFraction <= 0.03928 ? colorFraction / 12.92 : std::pow((colorFraction + 0.055) / 1.055, 2.4);
}

View File

@ -1,17 +1,18 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
// Copyright (C) 2017 Statoil ASA
//
//
// 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 <http://www.gnu.org/licenses/gpl.html>
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
@ -35,7 +36,13 @@ public:
static cvf::Color3f computeOffsetColor(cvf::Color3f color, float offsetFactor);
static cvf::Color3f darkContrastColor();
static cvf::Color3f brightContrastColor();
static cvf::Color3f constrastColor(cvf::Color3f backgroundColor);
static cvf::Color3f darkContrastColorSofter();
static cvf::Color3f brightContrastColorSofter();
static cvf::Color3f constrastColor(cvf::Color3f backgroundColor, bool softerContrast = false);
static QColor toQColor(cvf::Color3f color, float alpha = 1.0f);
static QColor toQColor(cvf::Color4f color);
static float contrastRatio(cvf::Color3f color1, cvf::Color3f color2);
private:
static float relativeLuminance(cvf::Color3f backgroundColor);
static float calculateNonLinearColorValue(float colorFraction);
};

View File

@ -17,6 +17,7 @@
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSummaryCurveAnalyzer.h"
#include "RiaStdStringTools.h"
#include "RiaSummaryCurveDefinition.h"
@ -62,6 +63,44 @@ std::set<std::string> RiaSummaryCurveAnalyzer::quantities() const
return m_quantities;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<std::string> RiaSummaryCurveAnalyzer::quantityNamesWithHistory() const
{
assignCategoryToQuantities();
return m_quantitiesWithMatchingHistory;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<std::string> RiaSummaryCurveAnalyzer::quantityNamesNoHistory() const
{
assignCategoryToQuantities();
return m_quantitiesNoMatchingHistory;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RiaSummaryCurveAnalyzer::quantityNameForTitle() const
{
if (quantityNamesWithHistory().size() == 1 && quantityNamesNoHistory().empty())
{
return *quantityNamesWithHistory().begin();
}
if (quantityNamesNoHistory().size() == 1 && quantityNamesWithHistory().empty())
{
return *quantityNamesNoHistory().begin();
}
return std::string();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -130,7 +169,7 @@ std::vector<QString> RiaSummaryCurveAnalyzer::identifierTexts(RifEclipseSummaryA
///
//--------------------------------------------------------------------------------------------------
std::vector<RifEclipseSummaryAddress>
RiaSummaryCurveAnalyzer::addressesForCategory(const std::set<RifEclipseSummaryAddress>& addresses,
RiaSummaryCurveAnalyzer::addressesForCategory(const std::set<RifEclipseSummaryAddress>& addresses,
RifEclipseSummaryAddress::SummaryVarCategory category)
{
std::vector<RifEclipseSummaryAddress> filteredAddresses;
@ -146,6 +185,24 @@ std::vector<RifEclipseSummaryAddress>
return filteredAddresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RiaSummaryCurveAnalyzer::correspondingHistorySummaryCurveName(const std::string& curveName)
{
static std::string historyIdentifier = "H";
if (RiaStdStringTools::endsWith(curveName, historyIdentifier))
{
std::string candidate = curveName.substr(0, curveName.size() - 1);
return candidate;
}
else
{
return curveName + historyIdentifier;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -158,6 +215,53 @@ void RiaSummaryCurveAnalyzer::clear()
m_categories.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSummaryCurveAnalyzer::assignCategoryToQuantities() const
{
if (!m_quantities.empty())
{
if (m_quantitiesWithMatchingHistory.empty() && m_quantitiesNoMatchingHistory.empty())
{
computeQuantityNamesWithHistory();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSummaryCurveAnalyzer::computeQuantityNamesWithHistory() const
{
m_quantitiesNoMatchingHistory.clear();
m_quantitiesWithMatchingHistory.clear();
const std::string historyIdentifier("H");
for (const auto& s : m_quantities)
{
std::string correspondingHistoryCurve = correspondingHistorySummaryCurveName(s);
if (m_quantities.find(correspondingHistoryCurve) != m_quantities.end())
{
// Insert the curve name without H
if (RiaStdStringTools::endsWith(s, historyIdentifier))
{
m_quantitiesWithMatchingHistory.insert(correspondingHistoryCurve);
}
else
{
m_quantitiesWithMatchingHistory.insert(s);
}
}
else
{
m_quantitiesNoMatchingHistory.insert(s);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -42,6 +42,11 @@ public:
void clear();
std::set<std::string> quantities() const;
std::set<std::string> quantityNamesWithHistory() const;
std::set<std::string> quantityNamesNoHistory() const;
std::string quantityNameForTitle() const;
std::set<std::string> wellNames() const;
std::set<std::string> wellGroupNames() const;
std::set<int> regionNumbers() const;
@ -53,11 +58,19 @@ public:
static std::vector<RifEclipseSummaryAddress> addressesForCategory(const std::set<RifEclipseSummaryAddress>& addresses,
RifEclipseSummaryAddress::SummaryVarCategory category);
static std::string correspondingHistorySummaryCurveName(const std::string& curveName);
private:
void assignCategoryToQuantities() const;
void computeQuantityNamesWithHistory() const;
void analyzeSingleAddress(const RifEclipseSummaryAddress& address);
private:
std::set<std::string> m_quantities;
mutable std::set<std::string> m_quantitiesWithMatchingHistory;
mutable std::set<std::string> m_quantitiesNoMatchingHistory;
std::set<std::string> m_wellNames;
std::set<std::string> m_wellGroupNames;
std::set<int> m_regionNumbers;

View File

@ -399,12 +399,19 @@ if(RESINSIGHT_ENABLE_COTIRE)
ModelVisualization/Intersections/RivIntersectionGeometryGenerator.cpp
# exclude file using Eigen
ReservoirDataModel/RigTransmissibilityCondenser.cpp
ReservoirDataModel/RigEclipseToStimPlanCellTransmissibilityCalculator.cpp
ReservoirDataModel/RigCellGeometryTools.cpp
ReservoirDataModel/Completions/RigTransmissibilityCondenser.cpp
ReservoirDataModel/Completions/RigEclipseToStimPlanCellTransmissibilityCalculator.cpp
ReservoirDataModel/Completions/RigEclipseToStimPlanCalculator.cpp
# exclude file using SolveSpace
Application/Tools/RiaSCurveCalculator.cpp
Application/Tools/WellPathTools/RiaSCurveCalculator.cpp
# QT 5
qrc_cafAnimControl.cpp
qrc_ResInsight.cpp
ProjectDataModel/RimContourMapView.cpp
Commands/CompletionExportCommands/RicExportFractureCompletionsImpl.cpp
)
foreach (fileToExclude ${COTIRE_EXCLUDE_FILES})

View File

@ -31,7 +31,11 @@ CAF_CMD_SOURCE_INIT(RicLaunchUnitTestsFeature, "RicLaunchUnitTestsFeature");
//--------------------------------------------------------------------------------------------------
bool RicLaunchUnitTestsFeature::isCommandEnabled()
{
#ifdef USE_UNIT_TESTS
return true;
#else
return false;
#endif
}
//--------------------------------------------------------------------------------------------------

View File

@ -15,6 +15,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicHoloLensSessionManager.h
${CMAKE_CURRENT_LIST_DIR}/RicHoloLensCreateDummyFileBackedSessionFeature.h
${CMAKE_CURRENT_LIST_DIR}/VdeArrayDataPacket.h
${CMAKE_CURRENT_LIST_DIR}/VdeCachingHashedIdFactory.h
${CMAKE_CURRENT_LIST_DIR}/VdeExportPart.h
${CMAKE_CURRENT_LIST_DIR}/VdeFileExporter.h
${CMAKE_CURRENT_LIST_DIR}/VdePacketDirectory.h
@ -36,6 +37,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicHoloLensSessionManager.cpp
${CMAKE_CURRENT_LIST_DIR}/RicHoloLensCreateDummyFileBackedSessionFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/VdeArrayDataPacket.cpp
${CMAKE_CURRENT_LIST_DIR}/VdeCachingHashedIdFactory.cpp
${CMAKE_CURRENT_LIST_DIR}/VdeExportPart.cpp
${CMAKE_CURRENT_LIST_DIR}/VdeFileExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/VdePacketDirectory.cpp

View File

@ -28,9 +28,12 @@
#include "VdeArrayDataPacket.h"
#include "cvfAssert.h"
#include "cvfTimer.h"
#include <QDir>
#include <algorithm>
//==================================================================================================
//
@ -129,18 +132,23 @@ void RicHoloLensSession::updateSessionDataFromView(const RimGridView& activeView
{
RiaLogging::info("HoloLens: Updating visualization data");
// Note
// Currently we clear the packet directory each time we update the visualization data
// This means we do no caching of actual packet data and we assume that the server will ask for data
// packets/arrays right after having received updated meta data
m_packetDirectory.clear();
// Grab the current max ID as an easy way to detect if new IDs have been added for debugging purposes
const int dbgMaxAssignedIdBeforeExtraction = m_cachingIdFactory.lastAssignedId();
VdeVizDataExtractor extractor(activeView);
// Note that we pass the caching ID factory on the constructor which will try and detect data payloads that
// are equal, and will then "recycle" the array IDs for these
VdeVizDataExtractor extractor(activeView, &m_cachingIdFactory);
QString modelMetaJsonStr;
std::vector<int> allReferencedPacketIds;
extractor.extractViewContents(&modelMetaJsonStr, &allReferencedPacketIds, &m_packetDirectory);
// Note!
// The packet directory should now contain all the packets that are being actively referenced.
// We now prune out any packets that are no longer being referenced. This means we do no caching of actual packet
// data over time and that we assume that the server will ask for data packets/arrays right after having received updated meta data
m_packetDirectory.pruneUnreferencedPackets(allReferencedPacketIds);
m_lastExtractionMetaDataSequenceNumber++;
m_lastExtractionAllReferencedPacketIdsArr = allReferencedPacketIds;
@ -171,9 +179,23 @@ void RicHoloLensSession::updateSessionDataFromView(const RimGridView& activeView
return;
}
RiaLogging::info(QString("HoloLens: Doing debug export of data to folder: %1").arg(absOutputFolder));
// For debugging, write only the new packets to file
// Determine which packets are new by comparing the IDs to the max known ID before extraction
std::vector<int> packetIdsToWrite;
for (int packetId : allReferencedPacketIds)
{
if (packetId > dbgMaxAssignedIdBeforeExtraction)
{
packetIdsToWrite.push_back(packetId);
}
}
// This will write all packets seen in this extraction to file
//packetIdsToWrite = allReferencedPacketIds;
RiaLogging::info(QString("HoloLens: Doing debug export of data (%1 packets) to folder: %2").arg(packetIdsToWrite.size()).arg(absOutputFolder));
VdeFileExporter fileExporter(absOutputFolder);
if (!fileExporter.exportToFile(modelMetaJsonStr, m_packetDirectory, allReferencedPacketIds))
if (!fileExporter.exportToFile(modelMetaJsonStr, m_packetDirectory, packetIdsToWrite))
{
RiaLogging::error("HoloLens: Error exporting debug data to folder");
}
@ -207,29 +229,135 @@ void RicHoloLensSession::handleFailedCreateSession()
//--------------------------------------------------------------------------------------------------
/// Handle the server response we receive after sending new meta data
//--------------------------------------------------------------------------------------------------
void RicHoloLensSession::handleSuccessfulSendMetaData(int metaDataSequenceNumber, const QByteArray& /*jsonServerResponseString*/)
void RicHoloLensSession::handleSuccessfulSendMetaData(int metaDataSequenceNumber, const QByteArray& jsonServerResponseString)
{
RiaLogging::info(QString("HoloLens: Processing server response to meta data (sequenceNumber=%1)").arg(metaDataSequenceNumber));
cvf::Timer tim;
RiaLogging::info(QString("HoloLens: Processing server response (meta data sequenceNumber=%1)").arg(metaDataSequenceNumber));
if (m_lastExtractionMetaDataSequenceNumber != metaDataSequenceNumber)
{
RiaLogging::warning(QString("HoloLens: Ignoring server response, the sequenceNumber(%1) has been superseded").arg(metaDataSequenceNumber));
RiaLogging::warning(QString("HoloLens: Ignoring server response, the meta data sequenceNumber(%1) has been superseded").arg(metaDataSequenceNumber));
return;
}
if (m_lastExtractionAllReferencedPacketIdsArr.size() > 0)
std::vector<int> arrayIdsToSend;
//cvf::Trace::show("Raw JSON response from server: '%s'", jsonServerResponseString.data());
QByteArray trimmedServerResponseString = jsonServerResponseString.trimmed();
if (trimmedServerResponseString.size() > 0)
{
if (!parseJsonIntegerArray(trimmedServerResponseString, &arrayIdsToSend))
{
RiaLogging::error("HoloLens: Error parsing array server response with array Ids, no data will be sent to server");
return;
}
}
else
{
// An empty server response means we should send all array referenced by the last sent meta data
if (m_lastExtractionAllReferencedPacketIdsArr.size() > 0)
{
arrayIdsToSend = m_lastExtractionAllReferencedPacketIdsArr;
RiaLogging::info("HoloLens: Empty server response, sending all arrays referenced by last meta data");
}
}
if (arrayIdsToSend.size() ==0)
{
RiaLogging::info("HoloLens: Nothing to do, no data requested by server");
return;
}
RiaLogging::info(QString("HoloLens: Start sending data to server, %1 data arrays have been requested").arg(arrayIdsToSend.size()));
size_t totalBytesSent = 0;
size_t totalNumArraysSent = 0;
const bool sendAsIndividualPackets = false;
// Sending data packets one by one
if (sendAsIndividualPackets)
{
for (size_t i = 0; i < arrayIdsToSend.size(); i++)
{
const int arrayId = arrayIdsToSend[i];
const VdeArrayDataPacket* packet = m_packetDirectory.lookupPacket(arrayId);
if (!packet)
{
RiaLogging::warning(QString("HoloLens: Could not get the requested data from cache, array id: %1 ").arg(arrayId));
continue;
}
QByteArray packetByteArr(packet->fullPacketRawPtr(), static_cast<int>(packet->fullPacketSize()));
RiaLogging::info(QString("HoloLens: sending array id: %1, %2KB (%3 bytes)").arg(arrayId).arg(packetByteArr.size()/1024.0, 0, 'f', 2).arg(packetByteArr.size()));
m_restClient->sendBinaryData(packetByteArr);
totalNumArraysSent++;
totalBytesSent += packetByteArr.size();
}
}
// Sending all requested arrays/packets in one combined packet
else
{
QByteArray combinedPacketArr;
if (!m_packetDirectory.getPacketsAsCombinedBuffer(m_lastExtractionAllReferencedPacketIdsArr, &combinedPacketArr))
if (!m_packetDirectory.getPacketsAsCombinedBuffer(arrayIdsToSend, &combinedPacketArr))
{
RiaLogging::warning("HoloLens: Error gathering the requested packets, no data will be sent");
RiaLogging::warning("HoloLens: Error gathering the requested arrays, no data will be sent");
return;
}
RiaLogging::info(QString("HoloLens: Sending new data to sharing server (%1 packets)").arg(m_lastExtractionAllReferencedPacketIdsArr.size()));
totalNumArraysSent = arrayIdsToSend.size();
totalBytesSent = combinedPacketArr.size();
RiaLogging::info(QString("HoloLens: Sending data to server (%1 arrays combined), %2KB (%3 bytes)").arg(totalNumArraysSent).arg(totalBytesSent/1024.0, 0, 'f', 2).arg(totalBytesSent));
m_restClient->sendBinaryData(combinedPacketArr);
}
const double totalMb = totalBytesSent/(1024.0*1024.0);
RiaLogging::info(QString("HoloLens: Finished sending data to server, %1 arrays, total %2MB (%3 bytes) in %4ms").arg(totalNumArraysSent).arg(totalMb, 0, 'f', 2).arg(totalBytesSent).arg(static_cast<int>(tim.time()*1000)));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicHoloLensSession::parseJsonIntegerArray(const QByteArray& jsonString, std::vector<int>* integerArr)
{
//cvf::Trace::show("jsonString: '%s'", jsonString.data());
const int openBraceIdx = jsonString.indexOf('[');
const int closeBraceIdx = jsonString.lastIndexOf(']');
if (openBraceIdx < 0 || closeBraceIdx < 0)
{
RiaLogging::debug("Error parsing JSON array, could not find opening or closing braces");
return false;
}
if (closeBraceIdx <= openBraceIdx)
{
RiaLogging::debug("Error parsing JSON array, wrong placement of braces");
return false;
}
QByteArray arrayContents = jsonString.mid(openBraceIdx + 1, closeBraceIdx - openBraceIdx - 1).trimmed();
//cvf::Trace::show("arrayContents: '%s'", arrayContents.data());
QList<QByteArray> stringList = arrayContents.split(',');
for (const QByteArray& entry : stringList)
{
bool convertOk = false;
const int intVal = entry.toInt(&convertOk);
if (convertOk)
{
integerArr->push_back(intVal);
}
}
return true;
}
//--------------------------------------------------------------------------------------------------

View File

@ -22,6 +22,7 @@
#include "RicHoloLensRestClient.h"
#include "VdePacketDirectory.h"
#include "VdeCachingHashedIdFactory.h"
#include <QString>
#include <QPointer>
@ -57,6 +58,8 @@ private:
virtual void handleSuccessfulSendMetaData(int metaDataSequenceNumber, const QByteArray& jsonServerResponseString) override;
virtual void handleError(const QString& errMsg, const QString& url, const QString& serverData) override;
static bool parseJsonIntegerArray(const QByteArray& jsonString, std::vector<int>* integerArr);
void notifyObserver(RicHoloLensSessionObserver::Notification notification);
private:
@ -65,6 +68,7 @@ private:
int m_lastExtractionMetaDataSequenceNumber;
std::vector<int> m_lastExtractionAllReferencedPacketIdsArr;
VdeCachingHashedIdFactory m_cachingIdFactory;
VdePacketDirectory m_packetDirectory;
RicHoloLensSessionObserver* m_sessionObserver;

View File

@ -103,7 +103,7 @@ void RicHoloLensSessionManager::terminateSession()
refreshToolbarState();
m_session->deleteLater();
sessionToDelete->deleteLater();
}
//--------------------------------------------------------------------------------------------------

View File

@ -178,40 +178,40 @@ unsigned char VdeArrayDataPacket::imageComponentCount() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeArrayDataPacket VdeArrayDataPacket::fromFloat32Arr(int arrayId, const float* srcArr, size_t srcArrElementCount)
std::unique_ptr<VdeArrayDataPacket> VdeArrayDataPacket::fromFloat32Arr(int arrayId, const float* srcArr, size_t srcArrElementCount)
{
size_t payloadByteCount = srcArrElementCount*sizeof(float);
const char* rawSrcPtr = reinterpret_cast<const char*>(srcArr);
VdeArrayDataPacket packet;
packet.assign(arrayId, Float32, srcArrElementCount, 0, 0, 0, rawSrcPtr, payloadByteCount);
std::unique_ptr<VdeArrayDataPacket> packet(new VdeArrayDataPacket);
packet->assign(arrayId, Float32, srcArrElementCount, 0, 0, 0, rawSrcPtr, payloadByteCount);
return packet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeArrayDataPacket VdeArrayDataPacket::fromUint32Arr(int arrayId, const unsigned int* srcArr, size_t srcArrElementCount)
std::unique_ptr<VdeArrayDataPacket> VdeArrayDataPacket::fromUint32Arr(int arrayId, const unsigned int* srcArr, size_t srcArrElementCount)
{
size_t payloadByteCount = srcArrElementCount*sizeof(unsigned int);
const char* rawSrcPtr = reinterpret_cast<const char*>(srcArr);
VdeArrayDataPacket packet;
packet.assign(arrayId, Uint32, srcArrElementCount, 0, 0, 0, rawSrcPtr, payloadByteCount);
std::unique_ptr<VdeArrayDataPacket> packet(new VdeArrayDataPacket);
packet->assign(arrayId, Uint32, srcArrElementCount, 0, 0, 0, rawSrcPtr, payloadByteCount);
return packet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeArrayDataPacket VdeArrayDataPacket::fromUint8ImageRGBArr(int arrayId, unsigned short imageWidth, unsigned short imageHeight, const unsigned char* srcArr, size_t srcArrElementCount)
std::unique_ptr<VdeArrayDataPacket> VdeArrayDataPacket::fromUint8ImageRGBArr(int arrayId, unsigned short imageWidth, unsigned short imageHeight, const unsigned char* srcArr, size_t srcArrElementCount)
{
const char* rawSrcPtr = reinterpret_cast<const char*>(srcArr);
assert(3*imageWidth*imageHeight == srcArrElementCount);
VdeArrayDataPacket packet;
packet.assign(arrayId, Uint8, srcArrElementCount, imageWidth, imageHeight, 3, rawSrcPtr, srcArrElementCount);
std::unique_ptr<VdeArrayDataPacket> packet(new VdeArrayDataPacket);
packet->assign(arrayId, Uint8, srcArrElementCount, imageWidth, imageHeight, 3, rawSrcPtr, srcArrElementCount);
return packet;
}

View File

@ -21,6 +21,7 @@
#include <cstddef>
#include <vector>
#include <string>
#include <memory>
//==================================================================================================
@ -42,26 +43,26 @@ public:
public:
VdeArrayDataPacket();
bool isValid() const;
int arrayId() const;
bool isValid() const;
int arrayId() const;
ElementType elementType() const;
size_t elementSize() const;
size_t elementCount() const;
const char* arrayData() const;
ElementType elementType() const;
size_t elementSize() const;
size_t elementCount() const;
const char* arrayData() const;
unsigned short imageWidth() const;
unsigned short imageHeight() const;
unsigned char imageComponentCount() const;
unsigned short imageWidth() const;
unsigned short imageHeight() const;
unsigned char imageComponentCount() const;
size_t fullPacketSize() const;
const char* fullPacketRawPtr() const;
size_t fullPacketSize() const;
const char* fullPacketRawPtr() const;
static VdeArrayDataPacket fromFloat32Arr(int arrayId, const float* srcArr, size_t srcArrElementCount);
static VdeArrayDataPacket fromUint32Arr(int arrayId, const unsigned int* srcArr, size_t srcArrElementCount);
static VdeArrayDataPacket fromUint8ImageRGBArr(int arrayId, unsigned short imageWidth, unsigned short imageHeight, const unsigned char* srcArr, size_t srcArrElementCount);
static std::unique_ptr<VdeArrayDataPacket> fromFloat32Arr(int arrayId, const float* srcArr, size_t srcArrElementCount);
static std::unique_ptr<VdeArrayDataPacket> fromUint32Arr(int arrayId, const unsigned int* srcArr, size_t srcArrElementCount);
static std::unique_ptr<VdeArrayDataPacket> fromUint8ImageRGBArr(int arrayId, unsigned short imageWidth, unsigned short imageHeight, const unsigned char* srcArr, size_t srcArrElementCount);
static VdeArrayDataPacket fromRawPacketBuffer(const char* rawPacketBuffer, size_t bufferSize, std::string* errString);
static VdeArrayDataPacket fromRawPacketBuffer(const char* rawPacketBuffer, size_t bufferSize, std::string* errString);
private:
bool assign(int arrayId, ElementType elementType, size_t elementCount, unsigned short imageWidth, unsigned short imageHeight, unsigned char imageCompCount, const char* arrayDataPtr, size_t arrayDataSizeInBytes);

View File

@ -0,0 +1,257 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 Statoil ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "VdeCachingHashedIdFactory.h"
#define FARMHASH_NO_BUILTIN_EXPECT
#define NAMESPACE_FOR_HASH_FUNCTIONS farmhash
#include "farmhash/farmhash.h"
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4267 4307 4319 4244)
#endif
#include "farmhash/farmhash.cc"
#ifdef _MSC_VER
#pragma warning (pop)
#endif
//==================================================================================================
//
//
//
//==================================================================================================
class Checksum
{
public:
static unsigned int crc(const void* data, size_t numBytes);
};
//==================================================================================================
//
//
//
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool VdeCachingHashedIdFactory::Key::operator<(const Key& other) const
{
if (hashVal != other.hashVal)
{
return hashVal < other.hashVal;
}
else if (role != other.role)
{
return role < other.role;
}
else if (elementType != other.elementType)
{
return elementType < other.elementType;
}
else
{
return elementCount < other.elementCount;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeCachingHashedIdFactory::VdeCachingHashedIdFactory()
: m_lastUsedId(-1)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::getOrCreateIdForFloatArr(ArrayRole arrayRole, const void* floatArr, size_t elementCount)
{
return getOrCreateIdForArrOfType(arrayRole, Float32, sizeof(float), floatArr, elementCount);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::getOrCreateIdForUint32Arr(ArrayRole arrayRole, const unsigned int* uint32Arr, size_t elementCount)
{
return getOrCreateIdForArrOfType(arrayRole, Uint32, sizeof(unsigned int), uint32Arr, elementCount);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::getOrCreateIdForUint8Arr(ArrayRole arrayRole, const unsigned char* uint8Arr, size_t elementCount)
{
return getOrCreateIdForArrOfType(arrayRole, Uint8, sizeof(unsigned char), uint8Arr, elementCount);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::lastAssignedId() const
{
return m_lastUsedId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::getOrCreateIdForArrOfType(ArrayRole arrayRole, ElementType elementType, size_t elementSizeInBytes, const void* data, size_t elementCount)
{
Key key;
key.elementType = elementType;
key.role = arrayRole;
key.elementCount = elementCount;
const size_t arraySizeInBytes = elementCount*elementSizeInBytes;
//key.hashVal = Checksum::crc(data, arraySizeInBytes);
//key.hashVal = farmhash::Hash32(static_cast<const char*>(data), arraySizeInBytes);
//key.hashVal = farmhash::Hash64(static_cast<const char*>(data), arraySizeInBytes);
//key.hashVal = farmhash::Hash128to64(farmhash::Hash128(static_cast<const char*>(data), arraySizeInBytes));
key.hashVal = farmhash::Hash128(static_cast<const char*>(data), arraySizeInBytes);
std::map<Key, int>::iterator it = m_keyToIdMap.find(key);
if (it != m_keyToIdMap.end())
{
return it->second;
}
const int newId = ++m_lastUsedId;
m_keyToIdMap[key] = newId;
return newId;
//const int newId = ++m_lastUsedId;
//return newId;
}
//==================================================================================================
//
// CRC Stuff
//
//==================================================================================================
static const unsigned int crc_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
unsigned int Checksum::crc(const void* data, size_t numBytes)
{
unsigned int sum = 0xffffffff;
const unsigned char* p = reinterpret_cast<const unsigned char*>(data);
// Compute crc
{
unsigned int tbl_idx;
while (numBytes--) {
tbl_idx = (sum ^ *p) & 0xff;
sum = (crc_table[tbl_idx] ^ (sum >> 8)) & 0xffffffff;
p++;
}
sum = sum & 0xffffffff;
}
return sum ^ 0xffffffff;
}

View File

@ -0,0 +1,73 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 Statoil ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <map>
//==================================================================================================
//
//
//
//==================================================================================================
class VdeCachingHashedIdFactory
{
public:
enum ArrayRole
{
VertexArr,
ConnArr,
TexImage,
TexCoordsArr
};
public:
VdeCachingHashedIdFactory();
int getOrCreateIdForFloatArr(ArrayRole arrayRole, const void* floatArr, size_t elementCount);
int getOrCreateIdForUint32Arr(ArrayRole arrayRole, const unsigned int* uint32Arr, size_t elementCount);
int getOrCreateIdForUint8Arr(ArrayRole arrayRole, const unsigned char* uint8Arr, size_t elementCount);
int lastAssignedId() const;
private:
enum ElementType
{
Float32,
Uint32,
Uint8,
};
struct Key
{
std::pair<uint64_t, uint64_t> hashVal;
ArrayRole role;
ElementType elementType;
size_t elementCount;
bool operator<(const Key& other) const;
};
private:
int getOrCreateIdForArrOfType(ArrayRole arrayRole, ElementType elementType, size_t elementSizeInBytes, const void* data, size_t elementCount);
private:
std::map<Key, int> m_keyToIdMap;
int m_lastUsedId;
};

View File

@ -19,6 +19,7 @@
#include "VdeFileExporter.h"
#include "VdeArrayDataPacket.h"
#include "VdePacketDirectory.h"
#include "VdeCachingHashedIdFactory.h"
#include "cvfTrace.h"
@ -72,7 +73,7 @@ bool VdeFileExporter::exportToFile(const QString& modelMetaJsonStr, const VdePac
}
}
cvf::Trace::show("Data exported to folder: %s", m_absOutputFolder.toLatin1().constData());
cvf::Trace::show("Data exported (%d packets) to folder: %s", packetIdsToExport.size(), m_absOutputFolder.toLatin1().constData());
return true;
}
@ -82,11 +83,12 @@ bool VdeFileExporter::exportToFile(const QString& modelMetaJsonStr, const VdePac
//--------------------------------------------------------------------------------------------------
bool VdeFileExporter::exportViewContents(const RimGridView& view)
{
VdeCachingHashedIdFactory localIdFactory;
VdeVizDataExtractor extractor(view, &localIdFactory);
QString modelMetaJsonStr;
std::vector<int> allReferencedArrayIds;
VdePacketDirectory packetDirectory;
VdeVizDataExtractor extractor(view);
extractor.extractViewContents(&modelMetaJsonStr, &allReferencedArrayIds, &packetDirectory);
if (!exportToFile(modelMetaJsonStr, packetDirectory, allReferencedArrayIds))

View File

@ -18,6 +18,7 @@
#include "VdePacketDirectory.h"
#include <algorithm>
//==================================================================================================
@ -36,10 +37,10 @@ VdePacketDirectory::VdePacketDirectory()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void VdePacketDirectory::addPacket(const VdeArrayDataPacket& packet)
void VdePacketDirectory::addPacket(std::unique_ptr<VdeArrayDataPacket> packet)
{
const int id = packet.arrayId();
m_idToPacketMap[id] = std::unique_ptr<VdeArrayDataPacket>(new VdeArrayDataPacket(packet));
const int id = packet->arrayId();
m_idToPacketMap[id] = std::move(packet);
}
//--------------------------------------------------------------------------------------------------
@ -64,6 +65,29 @@ void VdePacketDirectory::clear()
m_idToPacketMap.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void VdePacketDirectory::pruneUnreferencedPackets(const std::vector<int>& packetIdsInUseArr)
{
std::vector<int> sortedPacketsIdsInUse(packetIdsInUseArr);
std::sort(sortedPacketsIdsInUse.begin(), sortedPacketsIdsInUse.end());
IdToPacketMap_T::const_iterator it = m_idToPacketMap.cbegin();
while (it != m_idToPacketMap.cend())
{
const int packetId = it->first;
if (!std::binary_search(sortedPacketsIdsInUse.begin(), sortedPacketsIdsInUse.end(), packetId))
{
it = m_idToPacketMap.erase(it);
}
else
{
++it;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -36,9 +36,11 @@ class VdePacketDirectory
public:
VdePacketDirectory();
void addPacket(const VdeArrayDataPacket& packet);
void addPacket(std::unique_ptr<VdeArrayDataPacket> packet);
const VdeArrayDataPacket* lookupPacket(int arrayId) const;
void clear();
void pruneUnreferencedPackets(const std::vector<int>& packetIdsInUseArr);
bool getPacketsAsCombinedBuffer(const std::vector<int>& packetIdsToGet, QByteArray* combinedPacketArr) const;

View File

@ -19,6 +19,7 @@
#include "VdeVizDataExtractor.h"
#include "VdeArrayDataPacket.h"
#include "VdePacketDirectory.h"
#include "VdeCachingHashedIdFactory.h"
#include "RicHoloLensExportImpl.h"
@ -29,6 +30,8 @@
#include "cvfDrawableGeo.h"
#include "cvfPrimitiveSet.h"
#include "cvfTransform.h"
#include "cvfAssert.h"
#include "cvfTimer.h"
#include "cvfTrace.h"
@ -43,9 +46,11 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeVizDataExtractor::VdeVizDataExtractor(const RimGridView& view)
: m_view(view)
VdeVizDataExtractor::VdeVizDataExtractor(const RimGridView& view, VdeCachingHashedIdFactory* cachingIdFactory)
: m_view(view),
m_cachingIdFactory(cachingIdFactory)
{
CVF_ASSERT(m_cachingIdFactory);
}
//--------------------------------------------------------------------------------------------------
@ -53,84 +58,110 @@ VdeVizDataExtractor::VdeVizDataExtractor(const RimGridView& view)
//--------------------------------------------------------------------------------------------------
void VdeVizDataExtractor::extractViewContents(QString* modelMetaJsonStr, std::vector<int>* allReferencedArrayIds, VdePacketDirectory* packetDirectory)
{
cvf::Timer tim;
// First extract the parts (cvfPart + info) to be exported from from the ResInsight view
const std::vector<VdeExportPart> exportPartsArr = RicHoloLensExportImpl::partsForExport(m_view);
// Convert this to an array of export ready meshes
const std::vector<VdeMesh> meshArr = buildMeshArray(exportPartsArr);
const std::vector<std::unique_ptr<VdeMesh> > meshArr = buildMeshArray(exportPartsArr);
const int buildMeshes_ms = static_cast<int>(tim.lapTime()*1000);
const size_t meshCount = meshArr.size();
cvf::Trace::show("Extracting %d meshes", meshCount);
std::vector<VdeMeshArrayIds> meshArrayIdsArr;
cvf::Trace::show("Analyzing and generating array packet data for %d meshes", meshCount);
std::vector<VdeMeshArrayIds> allMeshesArrayIdsArr;
size_t totNumPrimitives = 0;
int nextArrayId = 0;
for (size_t i = 0; i < meshCount; i++)
{
const VdeMesh& mesh = meshArr[i];
const VdeMesh* mesh = meshArr[i].get();
const size_t primCount = mesh.connArr.size()/mesh.verticesPerPrimitive;
const size_t primCount = mesh->connArr.size()/mesh->verticesPerPrimitive;
totNumPrimitives += primCount;
cvf::Trace::show(" %2d: primCount=%d meshSourceObjName='%s'", i, primCount, mesh.meshSourceObjName.toLatin1().constData());
cvf::Trace::show(" mesh %2d: primCount=%d vertsPerPrim=%d meshSourceObjName='%s' meshSourceObjType='%s'", i, primCount, mesh->verticesPerPrimitive, mesh->meshSourceObjName.toLatin1().constData(), mesh->meshSourceObjTypeStr.toLatin1().constData());
VdeMeshArrayIds meshArrayIds;
VdeMeshArrayIds arrayIdsThisMesh;
{
cvf::Trace::show(" exporting vertices");
meshArrayIds.vertexArrId = nextArrayId++;
const float* floatArr = reinterpret_cast<const float*>(mesh.vertexArr->ptr());
VdeArrayDataPacket dataPacket = VdeArrayDataPacket::fromFloat32Arr(meshArrayIds.vertexArrId, floatArr, 3*mesh.vertexArr->size());
packetDirectory->addPacket(dataPacket);
const float* floatArr = reinterpret_cast<const float*>(mesh->vertexArr->ptr());
const size_t arrElementCount = 3*mesh->vertexArr->size();
arrayIdsThisMesh.vertexArrId = m_cachingIdFactory->getOrCreateIdForFloatArr(VdeCachingHashedIdFactory::VertexArr, floatArr, arrElementCount);
// Debug testing of decoding
debugComparePackets(dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket.fullPacketRawPtr(), dataPacket.fullPacketSize(), nullptr));
}
{
cvf::Trace::show(" exporting connectivities");
meshArrayIds.connArrId = nextArrayId++;
const unsigned int* uintArr = mesh.connArr.data();
VdeArrayDataPacket dataPacket = VdeArrayDataPacket::fromUint32Arr(meshArrayIds.connArrId, uintArr, mesh.connArr.size());
packetDirectory->addPacket(dataPacket);
// Debug testing of decoding
debugComparePackets(dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket.fullPacketRawPtr(), dataPacket.fullPacketSize(), nullptr));
}
if (mesh.texCoordArr.notNull() && mesh.texImage.notNull())
{
if (!packetDirectory->lookupPacket(arrayIdsThisMesh.vertexArrId))
{
cvf::Trace::show(" exporting texture coords");
meshArrayIds.texCoordsArrId = nextArrayId++;
const float* floatArr = reinterpret_cast<const float*>(mesh.texCoordArr->ptr());
VdeArrayDataPacket dataPacket = VdeArrayDataPacket::fromFloat32Arr(meshArrayIds.texCoordsArrId, floatArr, 2*mesh.texCoordArr->size());
packetDirectory->addPacket(dataPacket);
cvf::Trace::show(" generating vertices, arrayId=%d", arrayIdsThisMesh.vertexArrId);
std::unique_ptr<VdeArrayDataPacket> dataPacket = VdeArrayDataPacket::fromFloat32Arr(arrayIdsThisMesh.vertexArrId, floatArr, arrElementCount);
// Debug testing of decoding
debugComparePackets(dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket.fullPacketRawPtr(), dataPacket.fullPacketSize(), nullptr));
//debugComparePackets(*dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket->fullPacketRawPtr(), dataPacket->fullPacketSize(), nullptr));
packetDirectory->addPacket(std::move(dataPacket));
}
}
{
const unsigned int* uintArr = mesh->connArr.data();
const size_t arrElementCount = mesh->connArr.size();
arrayIdsThisMesh.connArrId = m_cachingIdFactory->getOrCreateIdForUint32Arr(VdeCachingHashedIdFactory::ConnArr, uintArr, arrElementCount);
if (!packetDirectory->lookupPacket(arrayIdsThisMesh.connArrId))
{
cvf::Trace::show(" exporting texture image");
meshArrayIds.texImageArrId = nextArrayId++;
cvf::ref<cvf::UByteArray> byteArr = mesh.texImage->toRgb();
VdeArrayDataPacket dataPacket = VdeArrayDataPacket::fromUint8ImageRGBArr(meshArrayIds.texImageArrId, mesh.texImage->width(), mesh.texImage->height(), byteArr->ptr(), byteArr->size());
packetDirectory->addPacket(dataPacket);
cvf::Trace::show(" generating connectivities, arrayId=%d", arrayIdsThisMesh.connArrId);
std::unique_ptr<VdeArrayDataPacket> dataPacket = VdeArrayDataPacket::fromUint32Arr(arrayIdsThisMesh.connArrId, uintArr, arrElementCount);
// Debug testing of decoding
debugComparePackets(dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket.fullPacketRawPtr(), dataPacket.fullPacketSize(), nullptr));
//debugComparePackets(*dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket->fullPacketRawPtr(), dataPacket->fullPacketSize(), nullptr));
packetDirectory->addPacket(std::move(dataPacket));
}
}
meshArrayIdsArr.push_back(meshArrayIds);
if (mesh->texCoordArr.notNull() && mesh->texImage.notNull())
{
{
const float* floatArr = reinterpret_cast<const float*>(mesh->texCoordArr->ptr());
const size_t arrElementCount = 2*mesh->texCoordArr->size();
arrayIdsThisMesh.texCoordsArrId = m_cachingIdFactory->getOrCreateIdForFloatArr(VdeCachingHashedIdFactory::TexCoordsArr, floatArr, arrElementCount);
if (!packetDirectory->lookupPacket(arrayIdsThisMesh.texCoordsArrId))
{
cvf::Trace::show(" generating texture coords, arrayId=%d", arrayIdsThisMesh.texCoordsArrId);
std::unique_ptr<VdeArrayDataPacket> dataPacket = VdeArrayDataPacket::fromFloat32Arr(arrayIdsThisMesh.texCoordsArrId, floatArr, arrElementCount);
// Debug testing of decoding
//debugComparePackets(*dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket->fullPacketRawPtr(), dataPacket->fullPacketSize(), nullptr));
packetDirectory->addPacket(std::move(dataPacket));
}
}
{
cvf::ref<cvf::UByteArray> byteArr = mesh->texImage->toRgb();
arrayIdsThisMesh.texImageArrId = m_cachingIdFactory->getOrCreateIdForUint8Arr(VdeCachingHashedIdFactory::TexImage, byteArr->ptr(), byteArr->size());
if (!packetDirectory->lookupPacket(arrayIdsThisMesh.texImageArrId))
{
cvf::Trace::show(" generating texture image, arrayId=%d", arrayIdsThisMesh.texImageArrId);
std::unique_ptr<VdeArrayDataPacket> dataPacket = VdeArrayDataPacket::fromUint8ImageRGBArr(arrayIdsThisMesh.texImageArrId, mesh->texImage->width(), mesh->texImage->height(), byteArr->ptr(), byteArr->size());
// Debug testing of decoding
//debugComparePackets(*dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket->fullPacketRawPtr(), dataPacket->fullPacketSize(), nullptr));
packetDirectory->addPacket(std::move(dataPacket));
}
}
}
allMeshesArrayIdsArr.push_back(arrayIdsThisMesh);
}
cvf::Trace::show("Total number of primitives extracted: %d", totNumPrimitives);
const int fillPacketDir_ms = static_cast<int>(tim.lapTime()*1000);
*modelMetaJsonStr = createModelMetaJsonString(meshArr, meshArrayIdsArr);
*modelMetaJsonStr = createModelMetaJsonString(meshArr, allMeshesArrayIdsArr);
// Find all unique packet array IDs referenced
std::set<int> referencedIdsSet;
for (const VdeMeshArrayIds& meshArrayIds : meshArrayIdsArr)
for (const VdeMeshArrayIds& meshArrayIds : allMeshesArrayIdsArr)
{
if (meshArrayIds.vertexArrId != -1) referencedIdsSet.insert(meshArrayIds.vertexArrId);
if (meshArrayIds.connArrId != -1) referencedIdsSet.insert(meshArrayIds.connArrId);
@ -139,20 +170,24 @@ void VdeVizDataExtractor::extractViewContents(QString* modelMetaJsonStr, std::ve
}
allReferencedArrayIds->assign(referencedIdsSet.begin(), referencedIdsSet.end());
RiaLogging::debug(QString("HoloLens: Extracted %1 meshes (total of %2 primitives) in %3ms (buildMeshes=%4ms, fillPacketDir=%5ms)").arg(meshCount).arg(totNumPrimitives).arg(static_cast<int>(tim.time()*1000)).arg(buildMeshes_ms).arg(fillPacketDir_ms));
//cvf::Trace::show("Total number of primitives extracted: %d in %dms", totNumPrimitives, static_cast<int>(tim.time()*1000));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<VdeMesh> VdeVizDataExtractor::buildMeshArray(const std::vector<VdeExportPart>& exportPartsArr)
std::vector<std::unique_ptr<VdeMesh> > VdeVizDataExtractor::buildMeshArray(const std::vector<VdeExportPart>& exportPartsArr)
{
std::vector<VdeMesh> meshArr;
std::vector<std::unique_ptr<VdeMesh> > meshArr;
for (const VdeExportPart& exportPart : exportPartsArr)
{
VdeMesh mesh;
if (extractMeshFromExportPart(exportPart, &mesh))
std::unique_ptr<VdeMesh> mesh = createMeshFromExportPart(exportPart);
if (mesh)
{
meshArr.push_back(mesh);
meshArr.push_back(std::move(mesh));
}
}
@ -162,26 +197,28 @@ std::vector<VdeMesh> VdeVizDataExtractor::buildMeshArray(const std::vector<VdeEx
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool VdeVizDataExtractor::extractMeshFromExportPart(const VdeExportPart& exportPart, VdeMesh* mesh)
std::unique_ptr<VdeMesh> VdeVizDataExtractor::createMeshFromExportPart(const VdeExportPart& exportPart)
{
//cvf::Timer tim;
const cvf::Part* cvfPart = exportPart.part();
const cvf::DrawableGeo* geo = dynamic_cast<const cvf::DrawableGeo*>(cvfPart ? cvfPart->drawable() : nullptr);
if (!geo)
{
return false;
return nullptr;
}
if (geo->primitiveSetCount() != 1)
{
RiaLogging::debug("Only geometries with exactly one primitive set is supported");
return false;
return nullptr;
}
const cvf::Vec3fArray* vertexArr = geo->vertexArray();
const cvf::PrimitiveSet* primSet = geo->primitiveSet(0);
if (!vertexArr || !primSet || primSet->faceCount() == 0)
{
return false;
return nullptr;
}
@ -190,23 +227,24 @@ bool VdeVizDataExtractor::extractMeshFromExportPart(const VdeExportPart& exportP
if (primType != cvf::PT_TRIANGLES && primType != cvf::PT_LINES)
{
RiaLogging::debug(QString("Currently only triangle and line primitive sets are supported (saw primitive type: %1)").arg(primType));
return false;
return nullptr;
}
const int vertsPerPrimitive = (primType == cvf::PT_TRIANGLES) ? 3 : 2;
std::unique_ptr<VdeMesh> mesh(new VdeMesh);
mesh->verticesPerPrimitive = vertsPerPrimitive;
// Possibly transform the vertices
if (cvfPart->transform())
{
const size_t vertexCount = vertexArr->size();
cvf::ref<cvf::Vec3fArray> transVertexArr = new cvf::Vec3fArray(vertexArr->size());
const cvf::Mat4f m = cvf::Mat4f(cvfPart->transform()->worldTransform());
cvf::Mat4f m = cvf::Mat4f(cvfPart->transform()->worldTransform());
cvf::ref<cvf::Vec3fArray> transVertexArr = new cvf::Vec3fArray(*vertexArr);
const size_t vertexCount = transVertexArr->size();
for (size_t i = 0; i < vertexCount; i++)
{
transVertexArr->set(i, vertexArr->get(i).getTransformedPoint(m));
transVertexArr->ptr(i)->transformPoint(m);
}
mesh->vertexArr = transVertexArr.p();
@ -216,12 +254,15 @@ bool VdeVizDataExtractor::extractMeshFromExportPart(const VdeExportPart& exportP
mesh->vertexArr = vertexArr;
}
// Fetch connectivities
// Using getFaceIndices() allows us to access strips and fans in the same way as triangles
// Note that HoloLens visualization wants triangles in clockwise order so we try and fix the winding
// This point might be moot if the HoloLens visualization always has to use two-sideded lighting to get good results
cvf::UIntArray faceConn;
// This point might be moot if the HoloLens visualization always has to use two-sided lighting to get good results
const size_t faceCount = primSet->faceCount();
mesh->connArr.reserve(faceCount*vertsPerPrimitive);
cvf::UIntArray faceConn;
for (size_t iface = 0; iface < faceCount; iface++)
{
primSet->getFaceIndices(iface, &faceConn);
@ -259,26 +300,28 @@ bool VdeVizDataExtractor::extractMeshFromExportPart(const VdeExportPart& exportP
mesh->color = exportPart.color();
mesh->opacity = exportPart.opacity();
return true;
//cvf::Trace::show("createMeshFromExportPart(): numFaces=%d, time=%dms", faceCount, static_cast<int>(tim.time()*1000));
return mesh;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString VdeVizDataExtractor::createModelMetaJsonString(const std::vector<VdeMesh>& meshArr, const std::vector<VdeMeshArrayIds>& meshContentIdsArr)
QString VdeVizDataExtractor::createModelMetaJsonString(const std::vector<std::unique_ptr<VdeMesh> >& meshArr, const std::vector<VdeMeshArrayIds>& meshContentIdsArr)
{
QVariantList jsonMeshMetaList;
for (size_t i = 0; i < meshArr.size(); i++)
{
const VdeMesh& mesh = meshArr[i];
const VdeMesh* mesh = meshArr[i].get();
const VdeMeshArrayIds& meshIds = meshContentIdsArr[i];
QMap<QString, QVariant> jsonMeshMeta;
jsonMeshMeta["meshSourceObjType"] = mesh.meshSourceObjTypeStr;
jsonMeshMeta["meshSourceObjName"] = mesh.meshSourceObjName;
jsonMeshMeta["meshSourceObjType"] = mesh->meshSourceObjTypeStr;
jsonMeshMeta["meshSourceObjName"] = mesh->meshSourceObjName;
jsonMeshMeta["verticesPerPrimitive"] = mesh.verticesPerPrimitive;
jsonMeshMeta["verticesPerPrimitive"] = mesh->verticesPerPrimitive;
jsonMeshMeta["vertexArrId"] = meshIds.vertexArrId;
jsonMeshMeta["connArrId"] = meshIds.connArrId;
@ -290,14 +333,14 @@ QString VdeVizDataExtractor::createModelMetaJsonString(const std::vector<VdeMesh
else
{
QMap<QString, QVariant> jsonColor;
jsonColor["r"] = mesh.color.r();
jsonColor["g"] = mesh.color.g();
jsonColor["b"] = mesh.color.b();
jsonColor["r"] = mesh->color.r();
jsonColor["g"] = mesh->color.g();
jsonColor["b"] = mesh->color.b();
jsonMeshMeta["color"] = jsonColor;
}
jsonMeshMeta["opacity"] = mesh.opacity;
jsonMeshMeta["opacity"] = mesh->opacity;
jsonMeshMetaList.push_back(jsonMeshMeta);
}

View File

@ -25,9 +25,12 @@
#include <QString>
#include <memory>
class VdeArrayDataPacket;
class VdePacketDirectory;
class VdeExportPart;
class VdeCachingHashedIdFactory;
class RimGridView;
@ -62,7 +65,7 @@ struct VdeMesh
//==================================================================================================
//
//
// The set of array IDs that are needed for a mesh
//
//==================================================================================================
struct VdeMeshArrayIds
@ -89,17 +92,17 @@ struct VdeMeshArrayIds
class VdeVizDataExtractor
{
public:
VdeVizDataExtractor(const RimGridView& view);
VdeVizDataExtractor(const RimGridView& view, VdeCachingHashedIdFactory* cachingIdFactory);
void extractViewContents(QString* modelMetaJsonStr, std::vector<int>* allReferencedArrayIds, VdePacketDirectory* packetDirectory);
private:
static std::vector<VdeMesh> buildMeshArray(const std::vector<VdeExportPart>& exportPartsArr);
static bool extractMeshFromExportPart(const VdeExportPart& exportPart, VdeMesh* mesh);
static QString createModelMetaJsonString(const std::vector<VdeMesh>& meshArr, const std::vector<VdeMeshArrayIds>& meshContentIdsArr);
static void debugComparePackets(const VdeArrayDataPacket& packetA, const VdeArrayDataPacket& packetB);
static std::vector<std::unique_ptr<VdeMesh> > buildMeshArray(const std::vector<VdeExportPart>& exportPartsArr);
static std::unique_ptr<VdeMesh> createMeshFromExportPart(const VdeExportPart& exportPart);
static QString createModelMetaJsonString(const std::vector<std::unique_ptr<VdeMesh> >& meshArr, const std::vector<VdeMeshArrayIds>& meshContentIdsArr);
static void debugComparePackets(const VdeArrayDataPacket& packetA, const VdeArrayDataPacket& packetB);
private:
const RimGridView& m_view;
const RimGridView& m_view;
VdeCachingHashedIdFactory* m_cachingIdFactory;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,328 @@
// Copyright (c) 2014 Google, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// FarmHash, by Geoff Pike
//
// http://code.google.com/p/farmhash/
//
// This file provides a few functions for hashing strings and other
// data. All of them are high-quality functions in the sense that
// they do well on standard tests such as Austin Appleby's SMHasher.
// They're also fast. FarmHash is the successor to CityHash.
//
// Functions in the FarmHash family are not suitable for cryptography.
//
// WARNING: This code has been only lightly tested on big-endian platforms!
// It is known to work well on little-endian platforms that have a small penalty
// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
// bug reports are welcome.
//
// By the way, for some hash functions, given strings a and b, the hash
// of a+b is easily derived from the hashes of a and b. This property
// doesn't hold for any hash functions in this file.
#ifndef FARM_HASH_H_
#define FARM_HASH_H_
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h> // for memcpy and memset
#include <utility>
#ifndef NAMESPACE_FOR_HASH_FUNCTIONS
#define NAMESPACE_FOR_HASH_FUNCTIONS util
#endif
namespace NAMESPACE_FOR_HASH_FUNCTIONS {
#if defined(FARMHASH_UINT128_T_DEFINED)
#if defined(__clang__)
#if !defined(uint128_t)
#define uint128_t __uint128_t
#endif
#endif
inline uint64_t Uint128Low64(const uint128_t x) {
return static_cast<uint64_t>(x);
}
inline uint64_t Uint128High64(const uint128_t x) {
return static_cast<uint64_t>(x >> 64);
}
inline uint128_t Uint128(uint64_t lo, uint64_t hi) {
return lo + (((uint128_t)hi) << 64);
}
#else
typedef std::pair<uint64_t, uint64_t> uint128_t;
inline uint64_t Uint128Low64(const uint128_t x) { return x.first; }
inline uint64_t Uint128High64(const uint128_t x) { return x.second; }
inline uint128_t Uint128(uint64_t lo, uint64_t hi) { return uint128_t(lo, hi); }
#endif
// BASIC STRING HASHING
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
size_t Hash(const char* s, size_t len);
// Hash function for a byte array. Most useful in 32-bit binaries.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint32_t Hash32(const char* s, size_t len);
// Hash function for a byte array. For convenience, a 32-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint32_t Hash32WithSeed(const char* s, size_t len, uint32_t seed);
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint64_t Hash64(const char* s, size_t len);
// Hash function for a byte array. For convenience, a 64-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint64_t Hash64WithSeed(const char* s, size_t len, uint64_t seed);
// Hash function for a byte array. For convenience, two seeds are also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint64_t Hash64WithSeeds(const char* s, size_t len,
uint64_t seed0, uint64_t seed1);
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint128_t Hash128(const char* s, size_t len);
// Hash function for a byte array. For convenience, a 128-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint128_t Hash128WithSeed(const char* s, size_t len, uint128_t seed);
// BASIC NON-STRING HASHING
// Hash 128 input bits down to 64 bits of output.
// This is intended to be a reasonably good hash function.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
inline uint64_t Hash128to64(uint128_t x) {
// Murmur-inspired hashing.
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
a ^= (a >> 47);
uint64_t b = (Uint128High64(x) ^ a) * kMul;
b ^= (b >> 47);
b *= kMul;
return b;
}
// FINGERPRINTING (i.e., good, portable, forever-fixed hash functions)
// Fingerprint function for a byte array. Most useful in 32-bit binaries.
uint32_t Fingerprint32(const char* s, size_t len);
// Fingerprint function for a byte array.
uint64_t Fingerprint64(const char* s, size_t len);
// Fingerprint function for a byte array.
uint128_t Fingerprint128(const char* s, size_t len);
// This is intended to be a good fingerprinting primitive.
// See below for more overloads.
inline uint64_t Fingerprint(uint128_t x) {
// Murmur-inspired hashing.
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
a ^= (a >> 47);
uint64_t b = (Uint128High64(x) ^ a) * kMul;
b ^= (b >> 44);
b *= kMul;
b ^= (b >> 41);
b *= kMul;
return b;
}
// This is intended to be a good fingerprinting primitive.
inline uint64_t Fingerprint(uint64_t x) {
// Murmur-inspired hashing.
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t b = x * kMul;
b ^= (b >> 44);
b *= kMul;
b ^= (b >> 41);
b *= kMul;
return b;
}
#ifndef FARMHASH_NO_CXX_STRING
// Convenience functions to hash or fingerprint C++ strings.
// These require that Str::data() return a pointer to the first char
// (as a const char*) and that Str::length() return the string's length;
// they work with std::string, for example.
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline size_t Hash(const Str& s) {
assert(sizeof(s[0]) == 1);
return Hash(s.data(), s.length());
}
// Hash function for a byte array. Most useful in 32-bit binaries.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint32_t Hash32(const Str& s) {
assert(sizeof(s[0]) == 1);
return Hash32(s.data(), s.length());
}
// Hash function for a byte array. For convenience, a 32-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint32_t Hash32WithSeed(const Str& s, uint32_t seed) {
assert(sizeof(s[0]) == 1);
return Hash32WithSeed(s.data(), s.length(), seed);
}
// Hash 128 input bits down to 64 bits of output.
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint64_t Hash64(const Str& s) {
assert(sizeof(s[0]) == 1);
return Hash64(s.data(), s.length());
}
// Hash function for a byte array. For convenience, a 64-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint64_t Hash64WithSeed(const Str& s, uint64_t seed) {
assert(sizeof(s[0]) == 1);
return Hash64WithSeed(s.data(), s.length(), seed);
}
// Hash function for a byte array. For convenience, two seeds are also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint64_t Hash64WithSeeds(const Str& s, uint64_t seed0, uint64_t seed1) {
assert(sizeof(s[0]) == 1);
return Hash64WithSeeds(s.data(), s.length(), seed0, seed1);
}
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint128_t Hash128(const Str& s) {
assert(sizeof(s[0]) == 1);
return Hash128(s.data(), s.length());
}
// Hash function for a byte array. For convenience, a 128-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint128_t Hash128WithSeed(const Str& s, uint128_t seed) {
assert(sizeof(s[0]) == 1);
return Hash128(s.data(), s.length(), seed);
}
// FINGERPRINTING (i.e., good, portable, forever-fixed hash functions)
// Fingerprint function for a byte array. Most useful in 32-bit binaries.
template <typename Str>
inline uint32_t Fingerprint32(const Str& s) {
assert(sizeof(s[0]) == 1);
return Fingerprint32(s.data(), s.length());
}
// Fingerprint 128 input bits down to 64 bits of output.
// Fingerprint function for a byte array.
template <typename Str>
inline uint64_t Fingerprint64(const Str& s) {
assert(sizeof(s[0]) == 1);
return Fingerprint64(s.data(), s.length());
}
// Fingerprint function for a byte array.
template <typename Str>
inline uint128_t Fingerprint128(const Str& s) {
assert(sizeof(s[0]) == 1);
return Fingerprint128(s.data(), s.length());
}
#endif
} // namespace NAMESPACE_FOR_HASH_FUNCTIONS
/* gently define FARMHASH_BIG_ENDIAN when detected big-endian machine */
#if defined(__BIG_ENDIAN__)
#if !defined(FARMHASH_BIG_ENDIAN)
#define FARMHASH_BIG_ENDIAN
#endif
#elif defined(__LITTLE_ENDIAN__)
// nothing for little-endian
#elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER == __ORDER_LITTLE_ENDIAN__)
// nothing for little-endian
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER == __ORDER_BIG_ENDIAN__)
#if !defined(FARMHASH_BIG_ENDIAN)
#define FARMHASH_BIG_ENDIAN
#endif
#elif defined(__linux__) || defined(__CYGWIN__) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
#include <endian.h> // libc6-dev, GLIBC
#if BYTE_ORDER == BIG_ENDIAN
#if !defined(FARMHASH_BIG_ENDIAN)
#define FARMHASH_BIG_ENDIAN
#endif
#endif
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__s390x__)
#include <sys/endian.h>
#if BYTE_ORDER == BIG_ENDIAN
#if !defined(FARMHASH_BIG_ENDIAN)
#define FARMHASH_BIG_ENDIAN
#endif
#endif
#elif defined(_WIN32)
// Windows is (currently) little-endian
#else
#error "Unable to determine endianness!"
#endif /* __BIG_ENDIAN__ */
#endif // FARM_HASH_H_

View File

@ -116,9 +116,12 @@ RicFileHierarchyDialog::RicFileHierarchyDialog(QWidget* parent)
m_effectiveFilter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
m_fileListLabel->setText("Files found");
m_fileListLabel->setVisible(false);
m_fileList->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_fileList->setVisible(false);
m_fileList->setContextMenuPolicy(Qt::CustomContextMenu);
m_fileList->setSortingEnabled(true);
m_browseButton->setText("...");
m_browseButton->setFixedWidth(25);
m_findOrCancelButton->setText(FIND_BUTTON_FIND_TEXT);

View File

@ -63,7 +63,8 @@ bool RicImportEnsembleFeature::isCommandEnabled()
void RicImportEnsembleFeature::onActionTriggered(bool isChecked)
{
RiaApplication* app = RiaApplication::instance();
QStringList fileNames = RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog("Import Ensemble");
QString pathCacheName = "ENSEMBLE_FILES";
QStringList fileNames = RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog("Import Ensemble", pathCacheName);
if (fileNames.isEmpty()) return;

View File

@ -70,7 +70,8 @@ bool RicImportSummaryCasesFeature::isCommandEnabled()
void RicImportSummaryCasesFeature::onActionTriggered(bool isChecked)
{
RiaApplication* app = RiaApplication::instance();
QStringList fileNames = runRecursiveSummaryCaseFileSearchDialog("Import Summary Cases");
QString pathCacheName = "INPUT_FILES";
QStringList fileNames = runRecursiveSummaryCaseFileSearchDialog("Import Summary Cases", pathCacheName);
std::vector<RimSummaryCase*> cases;
if (!fileNames.isEmpty()) createSummaryCasesFromFiles(fileNames, &cases);
@ -217,10 +218,11 @@ void RicImportSummaryCasesFeature::addCasesToGroupIfRelevant(const std::vector<R
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog(const QString& dialogTitle)
QStringList RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog(const QString& dialogTitle,
const QString& pathCacheName)
{
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory("INPUT_FILES");
QString defaultDir = app->lastUsedDialogDirectory(pathCacheName);
RicFileHierarchyDialogResult result = RicFileHierarchyDialog::runRecursiveSearchDialog(nullptr,
dialogTitle,
@ -236,7 +238,7 @@ QStringList RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialo
if (!result.ok) return QStringList();
// Remember the path to next time
app->setLastUsedDialogDirectory("INPUT_FILES", QFileInfo(result.rootDir).absoluteFilePath());
app->setLastUsedDialogDirectory(pathCacheName, QFileInfo(result.rootDir).absoluteFilePath());
return result.files;
}

View File

@ -43,7 +43,7 @@ public:
static void addSummaryCases(const std::vector<RimSummaryCase*> cases);
static void addCasesToGroupIfRelevant(const std::vector<RimSummaryCase*> cases);
static QStringList runRecursiveSummaryCaseFileSearchDialog(const QString& dialogTitle);
static QStringList runRecursiveSummaryCaseFileSearchDialog(const QString& dialogTitle, const QString& pathCacheName);
protected:
// Overrides

View File

@ -61,7 +61,8 @@ bool RicImportSummaryGroupFeature::isCommandEnabled()
void RicImportSummaryGroupFeature::onActionTriggered(bool isChecked)
{
RiaApplication* app = RiaApplication::instance();
QStringList fileNames = RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog("Import Summary Case Group");
QString pathCacheName = "INPUT_FILES";
QStringList fileNames = RicImportSummaryCasesFeature::runRecursiveSummaryCaseFileSearchDialog("Import Summary Case Group", pathCacheName);
if (fileNames.isEmpty()) return;

View File

@ -36,6 +36,10 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryEnsembleCurveSetFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicPasteEnsembleCurveSetFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewEnsembleCurveFilterFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewDerivedEnsembleFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicClearSourceSteppingSummaryCurveFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicSetSourceSteppingSummaryCurveFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicClearSourceSteppingEnsembleCurveSetFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicSetSourceSteppingEnsembleCurveSetFeature.h
)
set (SOURCE_GROUP_SOURCE_FILES
@ -75,6 +79,10 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryEnsembleCurveSetFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicPasteEnsembleCurveSetFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewEnsembleCurveFilterFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewDerivedEnsembleFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicClearSourceSteppingSummaryCurveFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicSetSourceSteppingSummaryCurveFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicClearSourceSteppingEnsembleCurveSetFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicSetSourceSteppingEnsembleCurveSetFeature.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@ -0,0 +1,114 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicClearSourceSteppingEnsembleCurveSetFeature.h"
#include "RimEnsembleCurveSet.h"
#include "RimEnsembleCurveSetCollection.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveCollection.h"
#include "RimSummaryPlot.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicClearSourceSteppingEnsembleCurveSetFeature, "RicClearSourceSteppingEnsembleCurveSetFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicClearSourceSteppingEnsembleCurveSetFeature::isCommandEnabled()
{
std::vector<caf::PdmObject*> objects;
caf::SelectionManager::instance()->objectsByType(&objects);
if (objects.size() == 1)
{
auto c = objects[0];
RimSummaryPlot* summaryPlot = nullptr;
c->firstAncestorOrThisOfTypeAsserted(summaryPlot);
if (summaryPlot)
{
if (summaryPlot->ensembleCurveSetCollection()->curveSetForSourceStepping()
|| summaryPlot->summaryCurveCollection()->curveForSourceStepping())
{
return true;
}
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicClearSourceSteppingEnsembleCurveSetFeature::onActionTriggered(bool isChecked)
{
std::vector<caf::PdmObject*> objects;
caf::SelectionManager::instance()->objectsByType(&objects);
if (objects.size() == 1)
{
auto c = objects[0];
RimSummaryPlot* summaryPlot = nullptr;
c->firstAncestorOrThisOfType(summaryPlot);
if (summaryPlot)
{
clearAllSourceSteppingInSummaryPlot(summaryPlot);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicClearSourceSteppingEnsembleCurveSetFeature::clearAllSourceSteppingInSummaryPlot(const RimSummaryPlot* summaryPlot)
{
RimEnsembleCurveSet* previousCurveSet = summaryPlot->ensembleCurveSetCollection()->curveSetForSourceStepping();
summaryPlot->ensembleCurveSetCollection()->setCurveSetForSourceStepping(nullptr);
RimSummaryCurve* previousCurve = summaryPlot->summaryCurveCollection()->curveForSourceStepping();
summaryPlot->summaryCurveCollection()->setCurveForSourceStepping(nullptr);
if (previousCurveSet)
{
previousCurveSet->updateConnectedEditors();
}
if (previousCurve)
{
previousCurve->updateConnectedEditors();
}
RiuPlotMainWindowTools::refreshToolbars();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicClearSourceSteppingEnsembleCurveSetFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("Clear Source Stepping Curve Set");
actionToSetup->setIcon(QIcon(":/StepUpDown16x16.png"));
}

View File

@ -0,0 +1,41 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
class RimSummaryPlot;
//==================================================================================================
///
//==================================================================================================
class RicClearSourceSteppingEnsembleCurveSetFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
public:
static void clearAllSourceSteppingInSummaryPlot(const RimSummaryPlot* summaryPlot);
protected:
bool isCommandEnabled() override;
void onActionTriggered(bool isChecked) override;
void setupActionLook(QAction* actionToSetup) override;
};

View File

@ -0,0 +1,90 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicClearSourceSteppingSummaryCurveFeature.h"
#include "RicClearSourceSteppingEnsembleCurveSetFeature.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveCollection.h"
#include "RimSummaryPlot.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
#include "RimEnsembleCurveSetCollection.h"
CAF_CMD_SOURCE_INIT(RicClearSourceSteppingSummaryCurveFeature, "RicClearSourceSteppingSummaryCurveFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicClearSourceSteppingSummaryCurveFeature::isCommandEnabled()
{
std::vector<caf::PdmObject*> objects;
caf::SelectionManager::instance()->objectsByType(&objects);
if (objects.size() == 1)
{
auto c = objects[0];
RimSummaryPlot* summaryPlot = nullptr;
c->firstAncestorOrThisOfTypeAsserted(summaryPlot);
if (summaryPlot)
{
if (summaryPlot->ensembleCurveSetCollection()->curveSetForSourceStepping()
|| summaryPlot->summaryCurveCollection()->curveForSourceStepping())
{
return true;
}
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicClearSourceSteppingSummaryCurveFeature::onActionTriggered(bool isChecked)
{
std::vector<RimSummaryCurve*> summaryCurves;
caf::SelectionManager::instance()->objectsByType(&summaryCurves);
if (summaryCurves.size() == 1)
{
auto c = summaryCurves[0];
RimSummaryPlot* summaryPlot = nullptr;
c->firstAncestorOrThisOfType(summaryPlot);
if (summaryPlot)
{
RicClearSourceSteppingEnsembleCurveSetFeature::clearAllSourceSteppingInSummaryPlot(summaryPlot);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicClearSourceSteppingSummaryCurveFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("Clear Source Stepping Curve");
actionToSetup->setIcon(QIcon(":/StepUpDown16x16.png"));
}

View File

@ -0,0 +1,34 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
//==================================================================================================
///
//==================================================================================================
class RicClearSourceSteppingSummaryCurveFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() override;
void onActionTriggered(bool isChecked) override;
void setupActionLook(QAction* actionToSetup) override;
};

View File

@ -19,6 +19,7 @@
#include "RicNewSummaryCurveFeature.h"
#include "RiaApplication.h"
#include "RiaColorTables.h"
#include "RimMainPlotCollection.h"
#include "RimOilField.h"
@ -31,8 +32,6 @@
#include "RiuPlotMainWindow.h"
#include "WellLogCommands/RicWellLogPlotCurveFeatureImpl.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
@ -62,7 +61,9 @@ void RicNewSummaryCurveFeature::onActionTriggered(bool isChecked)
if (plot)
{
RimSummaryCurve* newCurve = new RimSummaryCurve();
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable(plot->curveCount());
// Use same counting as RicNewSummaryEnsembleCurveSetFeature::onActionTriggered
cvf::Color3f curveColor = RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f(plot->singleColorCurveCount());
newCurve->setColor(curveColor);
plot->addCurveAndUpdate(newCurve);

View File

@ -67,12 +67,8 @@ void RicNewSummaryEnsembleCurveSetFeature::onActionTriggered(bool isChecked)
{
RimEnsembleCurveSet* curveSet = new RimEnsembleCurveSet();
// Set single curve set color
auto allCurveSets = plot->ensembleCurveSetCollection()->curveSets();
size_t colorIndex = std::count_if(allCurveSets.begin(), allCurveSets.end(), [](RimEnsembleCurveSet* curveSet)
{
return curveSet->colorMode() == RimEnsembleCurveSet::SINGLE_COLOR;
});
// Use same counting as RicNewSummaryCurveFeature::onActionTriggered
auto colorIndex = plot->singleColorCurveCount();
curveSet->setColor(RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f(colorIndex));
curveSet->legendConfig()->setColorRange(RimEnsembleCurveSetColorManager::cycledEnsembleColorRange(static_cast<int>(colorIndex)));

View File

@ -0,0 +1,98 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicSetSourceSteppingEnsembleCurveSetFeature.h"
#include "RimEnsembleCurveSet.h"
#include "RimEnsembleCurveSetCollection.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
#include "RicClearSourceSteppingEnsembleCurveSetFeature.h"
#include "RimSummaryPlot.h"
CAF_CMD_SOURCE_INIT(RicSetSourceSteppingEnsembleCurveSetFeature, "RicSetSourceSteppingEnsembleCurveSetFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicSetSourceSteppingEnsembleCurveSetFeature::isCommandEnabled()
{
std::vector<RimEnsembleCurveSet*> ensembleCurveSets;
caf::SelectionManager::instance()->objectsByType(&ensembleCurveSets);
if (ensembleCurveSets.size() == 1)
{
auto c = ensembleCurveSets[0];
RimEnsembleCurveSetCollection* coll = nullptr;
c->firstAncestorOrThisOfType(coll);
if (coll)
{
if (coll->curveSetForSourceStepping() != c)
{
return true;
}
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSetSourceSteppingEnsembleCurveSetFeature::onActionTriggered(bool isChecked)
{
std::vector<RimEnsembleCurveSet*> objects;
caf::SelectionManager::instance()->objectsByType(&objects);
if (objects.size() == 1)
{
auto c = objects[0];
RimSummaryPlot* summaryPlot = nullptr;
c->firstAncestorOrThisOfType(summaryPlot);
if (summaryPlot)
{
RicClearSourceSteppingEnsembleCurveSetFeature::clearAllSourceSteppingInSummaryPlot(summaryPlot);
}
RimEnsembleCurveSetCollection* coll = nullptr;
c->firstAncestorOrThisOfType(coll);
if (coll)
{
coll->setCurveSetForSourceStepping(c);
c->updateConnectedEditors();
RiuPlotMainWindowTools::refreshToolbars();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSetSourceSteppingEnsembleCurveSetFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("Set as Source Stepping Curve Set");
actionToSetup->setIcon(QIcon(":/StepUpDown16x16.png"));
}

View File

@ -0,0 +1,34 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
//==================================================================================================
///
//==================================================================================================
class RicSetSourceSteppingEnsembleCurveSetFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() override;
void onActionTriggered(bool isChecked) override;
void setupActionLook(QAction* actionToSetup) override;
};

View File

@ -0,0 +1,98 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicSetSourceSteppingSummaryCurveFeature.h"
#include "RicClearSourceSteppingEnsembleCurveSetFeature.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveCollection.h"
#include "RimSummaryPlot.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicSetSourceSteppingSummaryCurveFeature, "RicSetSourceSteppingSummaryCurveFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicSetSourceSteppingSummaryCurveFeature::isCommandEnabled()
{
std::vector<RimSummaryCurve*> summaryCurves;
caf::SelectionManager::instance()->objectsByType(&summaryCurves);
if (summaryCurves.size() == 1)
{
auto c = summaryCurves[0];
RimSummaryCurveCollection* coll = nullptr;
c->firstAncestorOrThisOfTypeAsserted(coll);
if (coll)
{
if (coll->curveForSourceStepping() != c)
{
return true;
}
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSetSourceSteppingSummaryCurveFeature::onActionTriggered(bool isChecked)
{
std::vector<RimSummaryCurve*> summaryCurves;
caf::SelectionManager::instance()->objectsByType(&summaryCurves);
if (summaryCurves.size() == 1)
{
auto c = summaryCurves[0];
RimSummaryPlot* summaryPlot = nullptr;
c->firstAncestorOrThisOfType(summaryPlot);
if (summaryPlot)
{
RicClearSourceSteppingEnsembleCurveSetFeature::clearAllSourceSteppingInSummaryPlot(summaryPlot);
}
RimSummaryCurveCollection* coll = nullptr;
c->firstAncestorOrThisOfTypeAsserted(coll);
if (coll)
{
coll->setCurveForSourceStepping(c);
c->updateConnectedEditors();
RiuPlotMainWindowTools::refreshToolbars();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSetSourceSteppingSummaryCurveFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("Set as Source Stepping Curve");
actionToSetup->setIcon(QIcon(":/StepUpDown16x16.png"));
}

View File

@ -0,0 +1,34 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Equinor ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
//==================================================================================================
///
//==================================================================================================
class RicSetSourceSteppingSummaryCurveFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() override;
void onActionTriggered(bool isChecked) override;
void setupActionLook(QAction* actionToSetup) override;
};

View File

@ -77,6 +77,14 @@ QString RifEclipseDataTableFormatter::tableRowPrependText() const
return m_tableRowPrependText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RifEclipseDataTableFormatter::tableRowAppendText() const
{
return m_tableRowAppendText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -93,6 +101,14 @@ void RifEclipseDataTableFormatter::setTableRowLineAppendText(const QString& text
m_tableRowAppendText = text;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RifEclipseDataTableFormatter::commentPrefix() const
{
return m_commentPrefix;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -129,7 +145,7 @@ void RifEclipseDataTableFormatter::outputBuffer()
else if (line.lineType == CONTENTS)
{
QString lineText = m_tableRowPrependText;
QString appendText = (line.appendTextSet ? line.appendText : m_tableRowAppendText) + "\n";
QString appendText = (line.appendTextSet ? line.appendText : m_tableRowAppendText);
for (size_t i = 0; i < line.data.size(); ++i)
{
@ -147,7 +163,7 @@ void RifEclipseDataTableFormatter::outputBuffer()
lineText += column;
}
m_out << lineText << appendText;
m_out << lineText << appendText << "\n";
}
}
m_columns.clear();
@ -456,12 +472,13 @@ int RifEclipseDataTableFormatter::measure(size_t num)
//--------------------------------------------------------------------------------------------------
int RifEclipseDataTableFormatter::tableWidth() const
{
int characterCount = 0;
int characterCount = m_tableRowPrependText.length();
for (size_t i = 0u; i < m_columns.size(); ++i)
{
characterCount += formatColumn(" ", i).size();
}
characterCount += m_tableRowAppendText.length();
return characterCount;
}

View File

@ -114,8 +114,10 @@ public:
int columnSpacing() const;
void setColumnSpacing(int spacing);
QString tableRowPrependText() const;
QString tableRowAppendText() const;
void setTableRowPrependText(const QString& text);
void setTableRowLineAppendText(const QString& text);
QString commentPrefix() const;
void setCommentPrefix(const QString& commentPrefix);
RifEclipseDataTableFormatter& keyword(const QString& keyword);
@ -135,6 +137,8 @@ public:
static void addValueTable(QTextStream& stream, const QString& keyword, size_t columns, const std::vector<double>& values);
int tableWidth() const;
static int maxEclipseRowWidth();
private:
int measure(const QString str);
@ -142,9 +146,6 @@ private:
int measure(int num);
int measure(size_t num);
int tableWidth() const;
static int maxEclipseRowWidth();
QString format(double num, RifEclipseOutputTableDoubleFormatting doubleFormat);
QString format(int num);
QString format(size_t num);

View File

@ -520,14 +520,14 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::ensembleStatisticsAddress(con
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifEclipseSummaryAddress::isDependentOnWellName(const RifEclipseSummaryAddress& address)
bool RifEclipseSummaryAddress::isDependentOnWellName(SummaryVarCategory category)
{
// clang-format off
if (address.category() == SUMMARY_WELL ||
address.category() == SUMMARY_WELL_COMPLETION ||
address.category() == SUMMARY_WELL_COMPLETION_LGR ||
address.category() == SUMMARY_WELL_LGR ||
address.category() == SUMMARY_WELL_SEGMENT)
if (category == SUMMARY_WELL ||
category == SUMMARY_WELL_COMPLETION ||
category == SUMMARY_WELL_COMPLETION_LGR ||
category == SUMMARY_WELL_LGR ||
category == SUMMARY_WELL_SEGMENT)
{
return true;
}

View File

@ -144,7 +144,7 @@ public:
static RifEclipseSummaryAddress importedAddress(const std::string& quantityName);
static RifEclipseSummaryAddress ensembleStatisticsAddress(const std::string& quantityName, const std::string& dataQuantityName);
static bool isDependentOnWellName(const RifEclipseSummaryAddress& address);
static bool isDependentOnWellName(SummaryVarCategory category);
// Access methods

View File

@ -1,5 +1,7 @@
#include "RivContourMapProjectionPartMgr.h"
#include "RiaColorTools.h"
#include "RiaFontCache.h"
#include "RiaWeightedMeanCalculator.h"
#include "RivMeshLinesSourceInfo.h"
#include "RivScalarMapperUtils.h"
@ -9,11 +11,13 @@
#include "cafEffectGenerator.h"
#include "cvfDrawableText.h"
#include "cvfGeometryBuilderFaceList.h"
#include "cvfGeometryUtils.h"
#include "cvfMeshEdgeExtractor.h"
#include "cvfPart.h"
#include "cvfPrimitiveSetIndexedUInt.h"
#include "cvfScalarMapper.h"
#include <cmath>
@ -31,6 +35,8 @@ RivContourMapProjectionPartMgr::RivContourMapProjectionPartMgr(RimContourMapProj
//--------------------------------------------------------------------------------------------------
void RivContourMapProjectionPartMgr::appendProjectionToModel(cvf::ModelBasicList* model, const caf::DisplayCoordTransform* displayCoordTransform) const
{
cvf::ScalarMapper* mapper = m_contourMapProjection->legendConfig()->scalarMapper();
cvf::ref<cvf::DrawableGeo> drawable = createProjectionMapDrawable(displayCoordTransform);
if (drawable.notNull() && drawable->boundingBox().isValid())
{
@ -38,7 +44,6 @@ void RivContourMapProjectionPartMgr::appendProjectionToModel(cvf::ModelBasicList
part->setDrawable(drawable.p());
cvf::ref<cvf::Vec2fArray> textureCoords = createTextureCoords();
cvf::ScalarMapper* mapper = m_contourMapProjection->legendConfig()->scalarMapper();
RivScalarMapperUtils::applyTextureResultsToPart(part.p(), textureCoords.p(), mapper, 1.0f, caf::FC_NONE, true, m_parentContourMap->backgroundColor());
part->setSourceInfo(new RivObjectSourceInfo(m_contourMapProjection.p()));
@ -48,22 +53,34 @@ void RivContourMapProjectionPartMgr::appendProjectionToModel(cvf::ModelBasicList
if (m_contourMapProjection->showContourLines())
{
std::vector<cvf::ref<cvf::DrawableGeo>> contourDrawables = createContourPolygons(displayCoordTransform);
for (cvf::ref<cvf::DrawableGeo> contourDrawable : contourDrawables)
std::vector<double> tickValues;
mapper->majorTickValues(&tickValues);
std::vector<std::vector<cvf::ref<cvf::Drawable>>> contourDrawablesForAllLevels = createContourPolygons(displayCoordTransform);
for (size_t i = 0; i < contourDrawablesForAllLevels.size(); ++i)
{
if (contourDrawable.notNull() && contourDrawable->boundingBox().isValid())
std::vector<cvf::ref<cvf::Drawable>> contourDrawables = contourDrawablesForAllLevels[i];
cvf::Color3f backgroundColor(mapper->mapToColor(tickValues[i]));
cvf::Color3f lineColor = RiaColorTools::constrastColor(backgroundColor, true);
for (cvf::ref<cvf::Drawable> contourDrawable : contourDrawables)
{
caf::MeshEffectGenerator meshEffectGen(cvf::Color3::BLACK);
meshEffectGen.setLineWidth(1.0f);
meshEffectGen.createAndConfigurePolygonOffsetRenderState(caf::PO_1);
cvf::ref<cvf::Effect> effect = meshEffectGen.generateCachedEffect();
if (contourDrawable.notNull() && contourDrawable->boundingBox().isValid())
{
caf::MeshEffectGenerator meshEffectGen(lineColor);
meshEffectGen.setLineWidth(1.0f);
meshEffectGen.createAndConfigurePolygonOffsetRenderState(caf::PO_1);
cvf::ref<cvf::Part> part = new cvf::Part;
part->setDrawable(contourDrawable.p());
part->setEffect(effect.p());
part->setSourceInfo(new RivMeshLinesSourceInfo(m_contourMapProjection.p()));
cvf::ref<cvf::Effect> effect = meshEffectGen.generateCachedEffect();
model->addPart(part.p());
cvf::ref<cvf::Part> part = new cvf::Part;
part->setDrawable(contourDrawable.p());
part->setEffect(effect.p());
part->setSourceInfo(new RivMeshLinesSourceInfo(m_contourMapProjection.p()));
model->addPart(part.p());
}
}
}
}
@ -148,13 +165,42 @@ cvf::ref<cvf::Vec2fArray> RivContourMapProjectionPartMgr::createTextureCoords()
return textureCoords;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableText> RivContourMapProjectionPartMgr::createTextLabel(const cvf::Color3f& textColor, const cvf::Color3f& backgroundColor)
{
auto font = RiaFontCache::getFont(RiaFontCache::FONT_SIZE_8);
cvf::ref<cvf::DrawableText> labelDrawable = new cvf::DrawableText();
labelDrawable->setFont(font.p());
labelDrawable->setCheckPosVisible(true);
labelDrawable->setUseDepthBuffer(true);
labelDrawable->setDrawBorder(true);
labelDrawable->setDrawBackground(true);
labelDrawable->setBackgroundColor(backgroundColor);
labelDrawable->setVerticalAlignment(cvf::TextDrawer::BASELINE);
labelDrawable->setTextColor(textColor);
return labelDrawable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableGeo> RivContourMapProjectionPartMgr::createProjectionMapDrawable(const caf::DisplayCoordTransform* displayCoordTransform) const
{
cvf::ref<cvf::Vec3fArray> vertexArray = new cvf::Vec3fArray;
m_contourMapProjection->generateVertices(vertexArray.p(), displayCoordTransform);
std::vector<cvf::Vec3d> vertices = m_contourMapProjection->generateVertices();
if (vertices.empty()) return nullptr;
cvf::ref<cvf::Vec3fArray> vertexArray = new cvf::Vec3fArray(vertices.size());
for (size_t i = 0; i < vertices.size(); ++i)
{
cvf::Vec3f displayVertexPos (displayCoordTransform->transformToDisplayCoord(vertices[i]));
(*vertexArray)[i] = displayVertexPos;
}
cvf::Vec2ui patchSize = m_contourMapProjection->numberOfVerticesIJ();
// Surface
@ -172,33 +218,86 @@ cvf::ref<cvf::DrawableGeo> RivContourMapProjectionPartMgr::createProjectionMapDr
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::ref<cvf::DrawableGeo>> RivContourMapProjectionPartMgr::createContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform) const
std::vector<std::vector<cvf::ref<cvf::Drawable>>> RivContourMapProjectionPartMgr::createContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform) const
{
RimContourMapProjection::ContourPolygons contourPolygons = m_contourMapProjection->generateContourPolygons(displayCoordTransform);
m_contourMapProjection->generateContourPolygons();
const std::vector<RimContourMapProjection::ContourPolygons>& contourPolygons = m_contourMapProjection->contourPolygons();
std::vector<cvf::ref<cvf::DrawableGeo>> contourDrawables;
contourDrawables.reserve(contourPolygons.size());
for (size_t i = 0; i < contourPolygons.size(); ++i)
const cvf::ScalarMapper* mapper = m_contourMapProjection->legendConfig()->scalarMapper();
std::vector<double> tickValues;
mapper->majorTickValues(&tickValues);
std::vector<std::vector<cvf::ref<cvf::Drawable>>> contourDrawablesForAllLevels;
std::vector<cvf::ref<cvf::Drawable>> labelDrawables;
for (int64_t i = (int64_t) contourPolygons.size() - 1; i > 0; --i)
{
cvf::ref<cvf::Vec3fArray> vertexArray = contourPolygons[i];
std::vector<cvf::uint> indices;
indices.reserve(contourPolygons[i]->size());
for (cvf::uint j = 0; j < contourPolygons[i]->size(); ++j)
std::vector<cvf::ref<cvf::Drawable>> contourDrawables;
cvf::Color3f backgroundColor(mapper->mapToColor(tickValues[i]));
cvf::Color3f textColor = RiaColorTools::constrastColor(backgroundColor);
for (size_t j = 0; j < contourPolygons[i].size(); ++j)
{
indices.push_back(j);
if (contourPolygons[i][j].vertices.empty()) continue;
size_t nVertices = contourPolygons[i][j].vertices.size();
size_t nLabels = m_contourMapProjection->showContourLabels() ? std::max((size_t)1, nVertices / 150u) : 0u;
for (size_t l = 0; l < nLabels; ++l)
{
cvf::ref<cvf::DrawableText> label = createTextLabel(textColor, backgroundColor);
cvf::Vec3f labelVertex(displayCoordTransform->transformToDisplayCoord(contourPolygons[i][j].vertices[(nVertices * l) / nLabels]));
labelVertex.z() += 3.0f;
label->addText(contourPolygons[i][j].label, labelVertex);
bool overlaps = false;
cvf::BoundingBox bbox = label->boundingBox();
for (cvf::ref<cvf::Drawable> existingLabel : labelDrawables)
{
if (existingLabel->boundingBox().intersects(bbox))
{
overlaps = true;
break;
}
}
if (!overlaps)
{
labelDrawables.push_back(label);
}
}
cvf::ref<cvf::Vec3fArray> vertexArray = new cvf::Vec3fArray(nVertices);
for (size_t v = 0; v < nVertices; v += 2)
{
cvf::Vec3d displayVertex1 = displayCoordTransform->transformToDisplayCoord(contourPolygons[i][j].vertices[v]);
cvf::Vec3d displayVertex2 = displayCoordTransform->transformToDisplayCoord(contourPolygons[i][j].vertices[v + 1]);
(*vertexArray)[v] = cvf::Vec3f(displayVertex1);
(*vertexArray)[v + 1] = cvf::Vec3f(displayVertex2);
}
std::vector<cvf::uint> indices;
indices.reserve(vertexArray->size());
for (cvf::uint k = 0; k < vertexArray->size(); ++k)
{
indices.push_back(k);
}
cvf::ref<cvf::PrimitiveSetIndexedUInt> indexedUInt = new cvf::PrimitiveSetIndexedUInt(cvf::PrimitiveType::PT_LINES);
cvf::ref<cvf::UIntArray> indexArray = new cvf::UIntArray(indices);
indexedUInt->setIndices(indexArray.p());
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
geo->addPrimitiveSet(indexedUInt.p());
geo->setVertexArray(vertexArray.p());
contourDrawables.push_back(geo);
}
for (cvf::ref<cvf::Drawable> labelDrawable : labelDrawables)
{
contourDrawables.push_back(labelDrawable);
}
cvf::ref<cvf::PrimitiveSetIndexedUInt> indexedUInt = new cvf::PrimitiveSetIndexedUInt(cvf::PrimitiveType::PT_LINES);
cvf::ref<cvf::UIntArray> indexArray = new cvf::UIntArray(indices);
indexedUInt->setIndices(indexArray.p());
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
geo->addPrimitiveSet(indexedUInt.p());
geo->setVertexArray(vertexArray.p());
contourDrawables.push_back(geo);
contourDrawablesForAllLevels.push_back(contourDrawables);
}
return contourDrawables;
return contourDrawablesForAllLevels;
}
//--------------------------------------------------------------------------------------------------
@ -207,14 +306,25 @@ std::vector<cvf::ref<cvf::DrawableGeo>> RivContourMapProjectionPartMgr::createCo
cvf::ref<cvf::DrawableGeo>
RivContourMapProjectionPartMgr::createPickPointVisDrawable(const caf::DisplayCoordTransform* displayCoordTransform) const
{
cvf::ref<cvf::DrawableGeo> geo = nullptr;
std::vector<cvf::Vec3d> pickPointPolygon = m_contourMapProjection->generatePickPointPolygon();
if (pickPointPolygon.empty())
{
return nullptr;
}
cvf::ref<cvf::Vec3fArray> vertexArray = new cvf::Vec3fArray(pickPointPolygon.size());
cvf::ref<cvf::Vec3fArray> pickPointPolygon = m_contourMapProjection->generatePickPointPolygon(displayCoordTransform);
if (pickPointPolygon.notNull() && pickPointPolygon->size() > 0u)
for (size_t i = 0; i < pickPointPolygon.size(); ++i)
{
cvf::Vec3f displayPoint(displayCoordTransform->transformToDisplayCoord(pickPointPolygon[i]));
(*vertexArray)[i] = displayPoint;
}
cvf::ref<cvf::DrawableGeo> geo = nullptr;
if (vertexArray->size() > 0u)
{
std::vector<cvf::uint> indices;
indices.reserve(pickPointPolygon->size());
for (cvf::uint j = 0; j < pickPointPolygon->size(); ++j)
indices.reserve(vertexArray->size());
for (cvf::uint j = 0; j < vertexArray->size(); ++j)
{
indices.push_back(j);
}
@ -226,7 +336,7 @@ cvf::ref<cvf::DrawableGeo>
geo = new cvf::DrawableGeo;
geo->addPrimitiveSet(indexedUInt.p());
geo->setVertexArray(pickPointPolygon.p());
geo->setVertexArray(vertexArray.p());
}
return geo;
}

View File

@ -23,6 +23,7 @@
#include "cvfBase.h"
#include "cvfDrawableGeo.h"
#include "cvfDrawableText.h"
#include "cvfModelBasicList.h"
#include "cvfObject.h"
@ -42,11 +43,12 @@ public:
cvf::ref<cvf::Vec2fArray> createTextureCoords() const;
private:
cvf::ref<cvf::DrawableGeo> createProjectionMapDrawable(const caf::DisplayCoordTransform* displayCoordTransform) const;
std::vector<cvf::ref<cvf::DrawableGeo>> createContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform) const;
cvf::ref<cvf::DrawableGeo> createPickPointVisDrawable(const caf::DisplayCoordTransform* displayCoordTransform) const;
static cvf::ref<cvf::DrawableText> createTextLabel(const cvf::Color3f& textColor, const cvf::Color3f& backgroundColor);
cvf::ref<cvf::DrawableGeo> createProjectionMapDrawable(const caf::DisplayCoordTransform* displayCoordTransform) const;
std::vector<std::vector<cvf::ref<cvf::Drawable>>> createContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform) const;
cvf::ref<cvf::DrawableGeo> createPickPointVisDrawable(const caf::DisplayCoordTransform* displayCoordTransform) const;
private:
caf::PdmPointer<RimContourMapProjection> m_contourMapProjection;
caf::PdmPointer<RimContourMapView> m_parentContourMap;
caf::PdmPointer<RimContourMapProjection> m_contourMapProjection;
caf::PdmPointer<RimContourMapView> m_parentContourMap;
};

View File

@ -98,6 +98,7 @@ RimFishbonesMultipleSubs::RimFishbonesMultipleSubs()
initialiseObsoleteFields();
CAF_PDM_InitFieldNoDefault(&m_valveLocations, "ValveLocations", "Valve Locations", "", "", "");
m_valveLocations = new RimMultipleValveLocations();
m_valveLocations->findField("RangeValveCount")->uiCapability()->setUiName("Number of Subs");
m_valveLocations.uiCapability()->setUiHidden(true);
m_valveLocations.uiCapability()->setUiTreeChildrenHidden(true);

View File

@ -36,7 +36,7 @@ namespace caf {
template<>
void AppEnum<RimMultipleValveLocations::LocationType>::setUp()
{
addItem(RimMultipleValveLocations::VALVE_COUNT, "VALVE_COUNT", "Start/End/Number of Valves");
addItem(RimMultipleValveLocations::VALVE_COUNT, "VALVE_COUNT", "Start/End/Number");
addItem(RimMultipleValveLocations::VALVE_SPACING, "VALVE_SPACING", "Start/End/Spacing");
addItem(RimMultipleValveLocations::VALVE_CUSTOM, "VALVE_CUSTOM", "User Specification");
setDefault(RimMultipleValveLocations::VALVE_COUNT);

View File

@ -237,6 +237,15 @@ void RimWellPathCompletions::setUnitSystemSpecificDefaults()
m_perforationCollection->setUnitSystemSpecificDefaults();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QRegExp RimWellPathCompletions::wellNameForExportRegExp()
{
QRegExp rx("[\\w\\-\\_]{1,8}");
return rx;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -295,9 +304,8 @@ void RimWellPathCompletions::defineEditorAttribute(const caf::PdmFieldHandle* fi
caf::PdmUiLineEditorAttribute* lineEditorAttr = dynamic_cast<caf::PdmUiLineEditorAttribute*>(attribute);
if (field == &m_wellNameForExport && lineEditorAttr)
{
QRegExp rx("[\\w\\-\\_]{1,8}");
QRegExpValidator* validator = new QRegExpValidator(nullptr);
validator->setRegExp(rx);
validator->setRegExp(wellNameForExportRegExp());
lineEditorAttr->validator = validator;
}
}

View File

@ -57,7 +57,7 @@ public:
bool hasCompletions() const;
void setUnitSystemSpecificDefaults();
static QRegExp wellNameForExportRegExp();
protected:
void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName) override;
void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;

View File

@ -486,12 +486,16 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
{
menuBuilder << "RicPasteSummaryCurveFeature";
menuBuilder << "RicPasteSummaryCrossPlotCurveFeature";
menuBuilder << "Separator";
menuBuilder << "RicNewSummaryCurveFeature";
menuBuilder << "RicDuplicateSummaryCurveFeature";
menuBuilder << "RicNewSummaryCrossPlotCurveFeature";
menuBuilder << "RicDuplicateSummaryCrossPlotCurveFeature";
menuBuilder << "Separator";
menuBuilder << "RicSetSourceSteppingSummaryCurveFeature";
menuBuilder << "RicClearSourceSteppingSummaryCurveFeature";
menuBuilder << "Separator";
menuBuilder << "RicCopyReferencesToClipboardFeature";
menuBuilder << "Separator";
menuBuilder << "RicEditSummaryCurveCalculationFeature";
@ -513,6 +517,9 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
else if (dynamic_cast<RimEnsembleCurveSet*>(uiItem))
{
menuBuilder << "RicNewSummaryEnsembleCurveSetFeature";
menuBuilder << "Separator";
menuBuilder << "RicSetSourceSteppingEnsembleCurveSetFeature";
menuBuilder << "RicClearSourceSteppingEnsembleCurveSetFeature";
}
else if (dynamic_cast<RimEnsembleCurveFilterCollection*>(uiItem))
{

View File

@ -24,6 +24,7 @@
#include "RimEclipseResultDefinition.h"
#include "RimProject.h"
#include "RimRegularLegendConfig.h"
#include "RimTextAnnotation.h"
#include "cafContourLines.h"
#include "cafPdmUiDoubleSliderEditor.h"
@ -77,6 +78,7 @@ RimContourMapProjection::RimContourMapProjection()
CAF_PDM_InitFieldNoDefault(&m_resultAggregation, "ResultAggregation", "Result Aggregation", "", "", "");
CAF_PDM_InitField(&m_showContourLines, "ContourLines", true, "Show Contour Lines", "", "", "");
CAF_PDM_InitField(&m_showContourLabels, "ContourLabels", false, "Show Contour Labels", "", "", "");
CAF_PDM_InitField(&m_weightByParameter, "WeightByParameter", false, "Weight by Result Parameter", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_weightingResult, "WeightingResult", "", "", "", "");
@ -84,6 +86,7 @@ RimContourMapProjection::RimContourMapProjection()
m_weightingResult.uiCapability()->setUiTreeChildrenHidden(true);
m_weightingResult = new RimEclipseResultDefinition;
m_weightingResult->findField("MResultType")->uiCapability()->setUiName("Result Type");
setName("Map Projection");
nameField()->uiCapability()->setUiReadOnly(true);
@ -102,11 +105,10 @@ RimContourMapProjection::~RimContourMapProjection()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimContourMapProjection::generateVertices(cvf::Vec3fArray* vertices, const caf::DisplayCoordTransform* displayCoordTransform)
std::vector<cvf::Vec3d> RimContourMapProjection::generateVertices()
{
CVF_ASSERT(vertices);
size_t nVertices = numberOfVertices();
vertices->resize(nVertices);
std::vector<cvf::Vec3d> vertices(nVertices, cvf::Vec3d::ZERO);
#pragma omp parallel for
for (int index = 0; index < static_cast<int>(nVertices); ++index)
@ -117,10 +119,10 @@ void RimContourMapProjection::generateVertices(cvf::Vec3fArray* vertices, const
globalPos.x() -= m_sampleSpacing * 0.5;
globalPos.y() -= m_sampleSpacing * 0.5;
cvf::Vec3d globalVertexPos(globalPos, m_fullBoundingBox.min().z() - 1.0);
cvf::Vec3f displayVertexPos(displayCoordTransform->transformToDisplayCoord(globalVertexPos));
(*vertices)[index] = displayVertexPos;
cvf::Vec3d globalVertexPos(globalPos, m_fullBoundingBox.min().z());
vertices[index] = globalVertexPos;
}
return vertices;
}
@ -128,9 +130,10 @@ void RimContourMapProjection::generateVertices(cvf::Vec3fArray* vertices, const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimContourMapProjection::ContourPolygons RimContourMapProjection::generateContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform)
void RimContourMapProjection::generateContourPolygons()
{
std::vector<cvf::ref<cvf::Vec3fArray>> contourPolygons;
std::vector<ContourPolygons> contourPolygons;
if (minValue() != std::numeric_limits<double>::infinity() &&
maxValue() != -std::numeric_limits<double>::infinity() &&
std::fabs(maxValue() - minValue()) > 1.0e-8)
@ -142,49 +145,51 @@ RimContourMapProjection::ContourPolygons RimContourMapProjection::generateContou
int nContourLevels = static_cast<int>(contourLevels.size());
if (nContourLevels > 2)
{
std::vector<double> fudgedContourLevels = contourLevels;
if (legendConfig()->mappingMode() == RimRegularLegendConfig::LINEAR_CONTINUOUS || legendConfig()->mappingMode() == RimRegularLegendConfig::LINEAR_DISCRETE)
{
// Slight fudge to avoid very jagged contour lines at the very edge
// Shift the contour levels inwards.
contourLevels[0] += (contourLevels[1] - contourLevels[0]) * 0.1;
contourLevels[nContourLevels - 1] -= (contourLevels[nContourLevels - 1] - contourLevels[nContourLevels - 2]) * 0.1;
fudgedContourLevels[0] += (contourLevels[1] - contourLevels[0]) * 0.1;
fudgedContourLevels[nContourLevels - 1] -= (contourLevels[nContourLevels - 1] - contourLevels[nContourLevels - 2]) * 0.1;
}
std::vector<std::vector<cvf::Vec2d>> contourLines;
caf::ContourLines::create(m_aggregatedVertexResults, xVertexPositions(), yVertexPositions(), contourLevels, &contourLines);
std::vector<caf::ContourLines::ClosedPolygons> closedContourLines =
caf::ContourLines::create(m_aggregatedVertexResults, xVertexPositions(), yVertexPositions(), fudgedContourLevels);
contourPolygons.reserve(contourLines.size());
for (size_t i = 0; i < contourLines.size(); ++i)
contourPolygons.resize(closedContourLines.size());
for (size_t i = 0; i < closedContourLines.size(); ++i)
{
if (!contourLines[i].empty())
for (size_t j = 0; j < closedContourLines[i].size(); ++j)
{
cvf::ref<cvf::Vec3fArray> contourPolygon = new cvf::Vec3fArray(contourLines[i].size());
for (size_t j = 0; j < contourLines[i].size(); ++j)
ContourPolygon contourPolygon;
contourPolygon.label = cvf::String(contourLevels[i]);
contourPolygon.vertices.reserve(closedContourLines[i][j].size());
for (size_t k = 0; k < closedContourLines[i][j].size(); ++k)
{
cvf::Vec3d contourPoint3d = cvf::Vec3d(contourLines[i][j], m_fullBoundingBox.min().z());
cvf::Vec3d displayPoint3d = displayCoordTransform->transformToDisplayCoord(contourPoint3d);
(*contourPolygon)[j] = cvf::Vec3f(displayPoint3d);
cvf::Vec3d contourPoint3d = cvf::Vec3d(closedContourLines[i][j][k], m_fullBoundingBox.min().z());
contourPolygon.vertices.push_back(contourPoint3d);
}
contourPolygons.push_back(contourPolygon);
contourPolygons[i].push_back(contourPolygon);
}
}
}
}
}
return contourPolygons;
m_contourPolygons = contourPolygons;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Vec3fArray>
RimContourMapProjection::generatePickPointPolygon(const caf::DisplayCoordTransform* displayCoordTransform)
std::vector<cvf::Vec3d>
RimContourMapProjection::generatePickPointPolygon()
{
cvf::ref<cvf::Vec3fArray> pickPolygon;
std::vector<cvf::Vec3d> points;
if (!m_pickPoint.isUndefined())
{
double zPos = m_fullBoundingBox.min().z();
std::vector<cvf::Vec3d> points;
{
cvf::Vec2d gridorigin(m_fullBoundingBox.min().x(), m_fullBoundingBox.min().y());
@ -209,16 +214,8 @@ RimContourMapProjection::generatePickPointPolygon(const caf::DisplayCoordTransfo
points.push_back(cvf::Vec3d(m_pickPoint - cvf::Vec2d(0.0, 0.5 * m_sampleSpacing), zPos));
points.push_back(cvf::Vec3d(m_pickPoint + cvf::Vec2d(0.0, 0.5 * m_sampleSpacing), zPos));
}
pickPolygon = new cvf::Vec3fArray(points.size());
for (size_t i = 0; i < points.size(); ++i)
{
cvf::Vec3d displayPoint = displayCoordTransform->transformToDisplayCoord(points[i]);
(*pickPolygon)[i] = cvf::Vec3f(displayPoint);
}
}
return pickPolygon;
return points;
}
//--------------------------------------------------------------------------------------------------
@ -285,6 +282,14 @@ void RimContourMapProjection::generateResults()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<RimContourMapProjection::ContourPolygons>& RimContourMapProjection::contourPolygons() const
{
return m_contourPolygons;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -317,6 +322,14 @@ bool RimContourMapProjection::showContourLines() const
return m_showContourLines();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimContourMapProjection::showContourLabels() const
{
return m_showContourLines() && m_showContourLabels();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -659,6 +672,8 @@ void RimContourMapProjection::defineUiOrdering(QString uiConfigName, caf::PdmUiO
caf::PdmUiGroup* mainGroup = uiOrdering.addNewGroup("Projection Settings");
mainGroup->add(&m_relativeSampleSpacing);
mainGroup->add(&m_showContourLines);
mainGroup->add(&m_showContourLabels);
m_showContourLabels.uiCapability()->setUiReadOnly(!m_showContourLines());
mainGroup->add(&m_resultAggregation);
caf::PdmUiGroup* weightingGroup = uiOrdering.addNewGroup("Mean Weighting Options");
@ -1314,6 +1329,7 @@ void RimContourMapProjection::updateGridInformation()
m_mainGrid = eclipseCase()->eclipseCaseData()->mainGrid();
m_sampleSpacing = m_relativeSampleSpacing * m_mainGrid->characteristicIJCellSize();
m_fullBoundingBox = eclipseCase()->activeCellsBoundingBox();
m_fullBoundingBox.expand(m_sampleSpacing * 2.0);
m_mapSize = calculateMapSize();
// Re-jig max point to be an exact multiple of cell size

View File

@ -29,6 +29,7 @@
#include "cvfBoundingBox.h"
#include "cvfGeometryBuilderFaceList.h"
#include "cvfString.h"
#include "cvfVector2.h"
class RigMainGrid;
@ -45,6 +46,12 @@ class RimContourMapProjection : public RimCheckableNamedObject
{
CAF_PDM_HEADER_INIT;
public:
struct ContourPolygon
{
std::vector<cvf::Vec3d> vertices;
cvf::String label;
};
enum ResultAggregationEnum
{
RESULTS_TOP_VALUE,
@ -60,49 +67,52 @@ public:
RESULTS_HC_COLUMN
};
typedef caf::AppEnum<ResultAggregationEnum> ResultAggregation;
typedef std::vector<cvf::ref<cvf::Vec3fArray>> ContourPolygons;
typedef std::vector<ContourPolygon> ContourPolygons;
RimContourMapProjection();
~RimContourMapProjection() override;
void generateVertices(cvf::Vec3fArray* vertices, const caf::DisplayCoordTransform* displayCoordTransform);
ContourPolygons generateContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform);
cvf::ref<cvf::Vec3fArray> generatePickPointPolygon(const caf::DisplayCoordTransform* displayCoordTransform);
void generateResults();
std::vector<cvf::Vec3d> generateVertices();
void generateContourPolygons();
std::vector<cvf::Vec3d> generatePickPointPolygon();
void generateResults();
ResultAggregation resultAggregation() const;
double sampleSpacing() const;
double sampleSpacingFactor() const;
bool showContourLines() const;
const std::vector<ContourPolygons>& contourPolygons() const;
QString resultAggregationText() const;
QString resultDescriptionText() const;
QString weightingParameter() const;
ResultAggregation resultAggregation() const;
double sampleSpacing() const;
double sampleSpacingFactor() const;
bool showContourLines() const;
bool showContourLabels() const;
double maxValue() const;
double minValue() const;
double meanValue() const;
double sumAllValues() const;
QString resultAggregationText() const;
QString resultDescriptionText() const;
QString weightingParameter() const;
cvf::Vec2ui numberOfElementsIJ() const;
cvf::Vec2ui numberOfVerticesIJ() const;
double maxValue() const;
double minValue() const;
double meanValue() const;
double sumAllValues() const;
bool isColumnResult() const;
cvf::Vec2ui numberOfElementsIJ() const;
cvf::Vec2ui numberOfVerticesIJ() const;
double valueAtVertex(uint i, uint j) const;
bool hasResultAtVertex(uint i, uint j) const;
bool isColumnResult() const;
RimRegularLegendConfig* legendConfig() const;
void updateLegend();
double valueAtVertex(uint i, uint j) const;
bool hasResultAtVertex(uint i, uint j) const;
uint numberOfCells() const;
uint numberOfValidCells() const;
size_t numberOfVertices() const;
RimRegularLegendConfig* legendConfig() const;
void updateLegend();
void updatedWeightingResult();
uint numberOfCells() const;
uint numberOfValidCells() const;
size_t numberOfVertices() const;
bool checkForMapIntersection(const cvf::Vec3d& localPoint3d, cvf::Vec2d* contourMapPoint, cvf::Vec2ui* contourMapCell, double* valueAtPoint) const;
void setPickPoint(cvf::Vec2d pickedPoint);
void updatedWeightingResult();
bool checkForMapIntersection(const cvf::Vec3d& localPoint3d, cvf::Vec2d* contourMapPoint, cvf::Vec2ui* contourMapCell, double* valueAtPoint) const;
void setPickPoint(cvf::Vec2d pickedPoint);
protected:
void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
@ -159,8 +169,10 @@ protected:
caf::PdmField<double> m_relativeSampleSpacing;
caf::PdmField<ResultAggregation> m_resultAggregation;
caf::PdmField<bool> m_showContourLines;
caf::PdmField<bool> m_showContourLabels;
caf::PdmField<bool> m_weightByParameter;
caf::PdmChildField<RimEclipseResultDefinition*> m_weightingResult;
cvf::ref<cvf::UByteArray> m_cellGridIdxVisibility;
std::vector<double> m_aggregatedResults;
@ -177,4 +189,5 @@ protected:
cvf::Vec2ui m_mapSize;
cvf::BoundingBox m_fullBoundingBox;
double m_sampleSpacing;
std::vector<ContourPolygons> m_contourPolygons;
};

View File

@ -242,7 +242,6 @@ void RimEclipseResultCase::reloadEclipseGridFile()
{
m_gridAndWellDataIsReadFromFile = false;
m_activeCellInfoIsReadFromFile = false;
m_timeStepFilter->reset();
setReservoirData(nullptr);
openReserviorCase();
}

View File

@ -181,21 +181,6 @@ bool RimTimeStepFilter::updateFilteredTimeStepsFromUi()
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimTimeStepFilter::reset()
{
m_filterType = TS_ALL;
m_filteredTimeSteps.v().clear();
m_filteredTimeStepsUi.v().clear();
m_firstTimeStep = 0;
m_lastTimeStep = 0;
m_interval = 1;
m_dateFormat = QString("yyyy-MM-dd");
m_timeStepNamesFromFile.v().clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -52,9 +52,6 @@ public:
void setTimeStepsFromFile(const std::vector<std::pair<QString, QDateTime>>& timeSteps);
std::vector<size_t> filteredTimeSteps() const;
bool updateFilteredTimeStepsFromUi();
void reset();
private:
std::vector<std::pair<QString, QDateTime>> allTimeSteps() const;
std::vector<int> filteredTimeStepIndicesFromUi() const;

View File

@ -660,6 +660,25 @@ void RimEnsembleCurveSet::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrd
}
uiTreeOrdering.skipRemainingChildren(true);
// Reset dynamic icon
this->setUiIcon(QIcon());
// Get static one
QIcon icon = this->uiIcon();
RimEnsembleCurveSetCollection* coll = nullptr;
this->firstAncestorOrThisOfType(coll);
if (coll && coll->curveSetForSourceStepping() == this)
{
QPixmap combined = icon.pixmap(16, 16);
QPainter painter(&combined);
QPixmap updownpixmap(":/StepUpDownCorner16x16.png");
painter.drawPixmap(0,0,updownpixmap);
icon = QIcon(combined);
}
this->setUiIcon(icon);
}
//--------------------------------------------------------------------------------------------------

View File

@ -20,6 +20,7 @@
#include "RiaApplication.h"
#include "RiaColorTables.h"
#include "RiaStdStringTools.h"
#include "RifReaderEclipseSummary.h"
@ -50,6 +51,13 @@ RimEnsembleCurveSetCollection::RimEnsembleCurveSetCollection()
CAF_PDM_InitField(&m_showCurves, "IsActive", true, "Show Curves", "", "", "");
m_showCurves.uiCapability()->setUiHidden(true);
CAF_PDM_InitFieldNoDefault(&m_ySourceStepping, "YSourceStepping", "", "", "", "");
m_ySourceStepping = new RimSummaryPlotSourceStepping;
m_ySourceStepping->setSourceSteppingType(RimSummaryPlotSourceStepping::Y_AXIS);
m_ySourceStepping.uiCapability()->setUiHidden(true);
m_ySourceStepping.uiCapability()->setUiTreeChildrenHidden(true);
m_ySourceStepping.xmlCapability()->disableIO();
}
//--------------------------------------------------------------------------------------------------
@ -193,6 +201,80 @@ size_t RimEnsembleCurveSetCollection::curveSetCount() const
return m_curveSets.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<caf::PdmFieldHandle*> RimEnsembleCurveSetCollection::fieldsToShowInToolbar()
{
if (m_ySourceStepping)
{
return m_ySourceStepping->fieldsToShowInToolbar();
}
return std::vector<caf::PdmFieldHandle*>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleCurveSetCollection::setCurveSetForSourceStepping(RimEnsembleCurveSet* curveSet)
{
m_curveSetForSourceStepping = curveSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEnsembleCurveSet* RimEnsembleCurveSetCollection::curveSetForSourceStepping() const
{
return m_curveSetForSourceStepping;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimEnsembleCurveSet*> RimEnsembleCurveSetCollection::curveSetsForSourceStepping() const
{
std::vector<RimEnsembleCurveSet*> steppingCurveSets;
if (m_curveSetForSourceStepping)
{
steppingCurveSets.push_back(m_curveSetForSourceStepping);
{
// Add corresponding history/summary curve with or without H
const std::string historyIdentifier = "H";
std::string quantity = m_curveSetForSourceStepping->summaryAddress().quantityName();
std::string candidateName;
if (RiaStdStringTools::endsWith(quantity, historyIdentifier))
{
candidateName = quantity.substr(0, quantity.size() - 1);
}
else
{
candidateName = quantity + historyIdentifier;
}
for (const auto& c : curveSets())
{
if (c->summaryAddress().quantityName() == candidateName)
{
steppingCurveSets.push_back(c);
}
}
}
}
else
{
steppingCurveSets = curveSets();
}
return steppingCurveSets;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -228,6 +310,16 @@ void RimEnsembleCurveSetCollection::fieldChangedByUi(const caf::PdmFieldHandle*
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleCurveSetCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
auto group = uiOrdering.addNewGroup("Data Source");
m_ySourceStepping()->uiOrdering(uiConfigName, *group);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -25,6 +25,8 @@
#include "cafPdmObject.h"
class RimEnsembleCurveSet;
class RimSummaryPlotSourceStepping;
class RimSummaryCurve;
class QwtPlot;
class QwtPlotCurve;
@ -55,9 +57,16 @@ public:
std::vector<RimEnsembleCurveSet*> curveSets() const;
size_t curveSetCount() const;
void deleteAllCurveSets();
void setCurrentSummaryCurveSet(RimEnsembleCurveSet* curveSet);
// Functions related to source stepping
std::vector<caf::PdmFieldHandle*> fieldsToShowInToolbar();
void setCurveSetForSourceStepping(RimEnsembleCurveSet* curve);
RimEnsembleCurveSet* curveSetForSourceStepping() const;
std::vector<RimEnsembleCurveSet*> curveSetsForSourceStepping() const;
private:
caf::PdmFieldHandle* objectToggleField() override;
@ -65,10 +74,15 @@ private:
void fieldChangedByUi(const caf::PdmFieldHandle* changedField,
const QVariant& oldValue, const QVariant& newValue) override;
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
private:
caf::PdmField<bool> m_showCurves;
caf::PdmChildArrayField<RimEnsembleCurveSet*> m_curveSets;
caf::PdmChildField<RimSummaryPlotSourceStepping*> m_ySourceStepping;
caf::PdmPointer<RimEnsembleCurveSet> m_currentEnsembleCurveSet;
caf::PdmPointer<RimEnsembleCurveSet> m_curveSetForSourceStepping;
};

View File

@ -565,6 +565,33 @@ void RimSummaryCurve::updateLegendsInPlot()
plot->updateAllLegendItems();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/)
{
RimPlotCurve::defineUiTreeOrdering(uiTreeOrdering, uiConfigName);
// Reset dynamic icon
this->setUiIcon(QIcon());
// Get static one
QIcon icon = this->uiIcon();
RimSummaryCurveCollection* coll = nullptr;
this->firstAncestorOrThisOfType(coll);
if (coll && coll->curveForSourceStepping() == this)
{
QPixmap combined = icon.pixmap(16, 16);
QPainter painter(&combined);
QPixmap updownpixmap(":/StepUpDownCorner16x16.png");
painter.drawPixmap(0,0,updownpixmap);
icon = QIcon(combined);
}
this->setUiIcon(icon);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -93,6 +93,9 @@ protected:
void updateLegendsInPlot() override;
void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override;
private:
RifSummaryReaderInterface* valuesSummaryReaderX() const;
RifSummaryReaderInterface* valuesSummaryReaderY() const;

View File

@ -19,6 +19,7 @@
#include "RimSummaryCurveCollection.h"
#include "RiaApplication.h"
#include "RiaStdStringTools.h"
#include "RifReaderEclipseSummary.h"
@ -192,6 +193,72 @@ std::vector<RimSummaryCurve*> RimSummaryCurveCollection::curves() const
return m_curves.childObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCurve*> RimSummaryCurveCollection::curvesForSourceStepping(RimSummaryPlotSourceStepping::SourceSteppingType steppingType) const
{
std::vector<RimSummaryCurve*> stepCurves;
if (m_curveForSourceStepping)
{
stepCurves.push_back(m_curveForSourceStepping);
{
// Add corresponding history/summary curve with or without H
const std::string historyIdentifier = "H";
std::string quantity;
if (steppingType == RimSummaryPlotSourceStepping::X_AXIS)
{
quantity = m_curveForSourceStepping->summaryAddressX().quantityName();
}
else if (steppingType == RimSummaryPlotSourceStepping::Y_AXIS)
{
quantity = m_curveForSourceStepping->summaryAddressY().quantityName();
}
std::string candidateName;
if (RiaStdStringTools::endsWith(quantity, historyIdentifier))
{
candidateName = quantity.substr(0, quantity.size() - 1);
}
else
{
candidateName = quantity + historyIdentifier;
}
for (const auto& c : curves())
{
if (steppingType == RimSummaryPlotSourceStepping::X_AXIS)
{
if (c->summaryCaseX() == m_curveForSourceStepping->summaryCaseX() &&
c->summaryAddressX().quantityName() == candidateName)
{
stepCurves.push_back(c);
}
}
else if (steppingType == RimSummaryPlotSourceStepping::Y_AXIS)
{
if (c->summaryCaseY() == m_curveForSourceStepping->summaryCaseY() &&
c->summaryAddressY().quantityName() == candidateName)
{
stepCurves.push_back(c);
}
}
}
}
}
else
{
stepCurves = curves();
}
return stepCurves;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -355,6 +422,22 @@ void RimSummaryCurveCollection::setCurveAsTopZWithinCategory(RimSummaryCurve* cu
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCurveCollection::setCurveForSourceStepping(RimSummaryCurve* curve)
{
m_curveForSourceStepping = curve;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCurve* RimSummaryCurveCollection::curveForSourceStepping() const
{
return m_curveForSourceStepping;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -19,6 +19,8 @@
#pragma once
#include "RimSummaryPlotSourceStepping.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmField.h"
@ -29,7 +31,6 @@ class QwtPlot;
class QwtPlotCurve;
class RimSummaryCase;
class RimSummaryCurve;
class RimSummaryPlotSourceStepping;
class QKeyEvent;
//==================================================================================================
@ -56,6 +57,7 @@ public:
void deleteCurve(RimSummaryCurve* curve);
std::vector<RimSummaryCurve*> curves() const;
std::vector<RimSummaryCurve*> curvesForSourceStepping(RimSummaryPlotSourceStepping::SourceSteppingType steppingType) const;
void deleteCurvesAssosiatedWithCase(RimSummaryCase* summaryCase);
void deleteAllCurves();
@ -68,6 +70,9 @@ public:
void handleKeyPressEvent(QKeyEvent* keyEvent);
void setCurveAsTopZWithinCategory(RimSummaryCurve* curve);
void setCurveForSourceStepping(RimSummaryCurve* curve);
RimSummaryCurve* curveForSourceStepping() const;
private:
caf::PdmFieldHandle* objectToggleField() override;
@ -88,5 +93,6 @@ private:
caf::PdmChildField<RimSummaryPlotSourceStepping*> m_unionSourceStepping;
caf::PdmPointer<RimSummaryCurve> m_currentSummaryCurve;
caf::PdmPointer<RimSummaryCurve> m_curveForSourceStepping;
};

View File

@ -549,6 +549,22 @@ bool RimSummaryPlot::containsResamplableCurves() const
return !m_gridTimeHistoryCurves.empty() || resamplableSummaryCurveCount > 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RimSummaryPlot::singleColorCurveCount() const
{
auto allCurveSets = ensembleCurveSetCollection()->curveSets();
size_t colorIndex = std::count_if(allCurveSets.begin(), allCurveSets.end(), [](RimEnsembleCurveSet* curveSet)
{
return curveSet->colorMode() == RimEnsembleCurveSet::SINGLE_COLOR;
});
colorIndex += curveCount();
return colorIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -132,6 +132,8 @@ public:
void updatePlotInfoLabel();
bool containsResamplableCurves() const;
size_t singleColorCurveCount() const;
// RimViewWindow overrides
public:
QWidget* createViewWidget(QWidget* mainWindowParent) override;

View File

@ -25,6 +25,8 @@
#include "RifSummaryReaderInterface.h"
#include "RimDataSourceSteppingTools.h"
#include "RimEnsembleCurveSet.h"
#include "RimEnsembleCurveSetCollection.h"
#include "RimProject.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseMainCollection.h"
@ -35,6 +37,7 @@
#include "RiuPlotMainWindow.h"
#include "RiaStdStringTools.h"
#include "cafPdmUiComboBoxEditor.h"
#include "cafPdmUiItem.h"
#include "cafPdmUiListEditor.h"
@ -51,11 +54,22 @@ RimSummaryPlotSourceStepping::RimSummaryPlotSourceStepping()
CAF_PDM_InitObject("Summary Curves Modifier", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_summaryCase, "CurveCase", "Case", "", "", "");
CAF_PDM_InitField(&m_includeEnsembleCasesForCaseStepping,
"IncludeEnsembleCasesForCaseStepping",
false,
"Allow Stepping on Ensemble cases",
"",
"",
"");
CAF_PDM_InitFieldNoDefault(&m_wellName, "WellName", "Well Name", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellGroupName, "GroupName", "Group Name", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_region, "Region", "Region", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_quantity, "Quantities", "Quantity", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_ensemble, "Ensemble", "Ensemble", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_placeholderForLabel, "Placeholder", "", "", "", "");
m_placeholderForLabel = "No common identifiers detected";
m_placeholderForLabel.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP);
@ -88,6 +102,22 @@ void RimSummaryPlotSourceStepping::applyPrevCase()
modifyCurrentIndex(&m_summaryCase, -1);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlotSourceStepping::applyNextEnsemble()
{
modifyCurrentIndex(&m_ensemble, 1);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlotSourceStepping::applyPrevEnsemble()
{
modifyCurrentIndex(&m_ensemble, -1);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -162,85 +192,159 @@ void RimSummaryPlotSourceStepping::defineUiOrdering(QString uiConfigName, caf::P
QList<caf::PdmOptionItemInfo> RimSummaryPlotSourceStepping::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly)
{
if (fieldNeedingOptions == &m_placeholderForLabel)
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &m_includeEnsembleCasesForCaseStepping)
{
return QList<caf::PdmOptionItemInfo>();
return caf::PdmObject::calculateValueOptions(fieldNeedingOptions, useOptionsOnly);
}
if (fieldNeedingOptions == &m_summaryCase)
else if (fieldNeedingOptions == &m_placeholderForLabel)
{
QList<caf::PdmOptionItemInfo> options;
RimProject* proj = RiaApplication::instance()->project();
for (auto sumCase : proj->allSummaryCases())
options;
}
else if (fieldNeedingOptions == &m_summaryCase)
{
auto summaryCases = RimSummaryPlotSourceStepping::summaryCasesForSourceStepping();
for (auto sumCase : summaryCases)
{
options.append(caf::PdmOptionItemInfo(sumCase->caseName(), sumCase));
}
return options;
}
else if (fieldNeedingOptions == &m_ensemble)
{
RimProject* proj = RiaApplication::instance()->project();
for (auto ensemble : proj->summaryGroups())
{
if (ensemble->isEnsemble())
{
options.append(caf::PdmOptionItemInfo(ensemble->name(), ensemble));
}
}
std::vector<QString> identifierTexts;
return options;
}
std::vector<RifSummaryReaderInterface*> readers = summaryReadersForCurves();
if (!readers.empty())
{
RiaSummaryCurveAnalyzer* analyzer = analyzerForReader(readers.front());
if (fieldNeedingOptions == &m_wellName)
if (fieldNeedingOptions == &m_quantity)
{
identifierTexts = analyzer->identifierTexts(RifEclipseSummaryAddress::SUMMARY_WELL);
}
else if (fieldNeedingOptions == &m_region)
{
identifierTexts = analyzer->identifierTexts(RifEclipseSummaryAddress::SUMMARY_REGION);
}
else if (fieldNeedingOptions == &m_wellGroupName)
{
identifierTexts = analyzer->identifierTexts(RifEclipseSummaryAddress::SUMMARY_WELL_GROUP);
}
else if (fieldNeedingOptions == &m_quantity)
{
RimSummaryCurveCollection* curveCollection = nullptr;
this->firstAncestorOrThisOfTypeAsserted(curveCollection);
RifEclipseSummaryAddress::SummaryVarCategory category = RifEclipseSummaryAddress::SUMMARY_FIELD;
if (curveCollection->curves().size() > 0)
auto addresses = addressesCurveCollection();
if (!addresses.empty())
{
category = curveCollection->curves()[0]->summaryAddressY().category();
category = addresses.begin()->category();
}
RiaSummaryCurveAnalyzer quantityAnalyzer;
std::map<QString, QString> displayAndValueStrings;
for (auto reader : readers)
{
if (reader != nullptr)
RiaSummaryCurveAnalyzer quantityAnalyzer;
for (auto reader : readers)
{
auto subset = RiaSummaryCurveAnalyzer::addressesForCategory(reader->allResultAddresses(), category);
quantityAnalyzer.appendAdresses(subset);
if (reader != nullptr)
{
auto subset = RiaSummaryCurveAnalyzer::addressesForCategory(reader->allResultAddresses(), category);
quantityAnalyzer.appendAdresses(subset);
}
}
RiaSummaryCurveAnalyzer analyzerForCurves;
analyzerForCurves.appendAdresses(addressesCurveCollection());
if (analyzerForCurves.quantityNamesWithHistory().empty())
{
auto quantities = quantityAnalyzer.quantities();
for (const auto& s : quantities)
{
QString valueString = QString::fromStdString(s);
displayAndValueStrings[valueString] = valueString;
}
}
else
{
auto quantitiesWithHistory = quantityAnalyzer.quantityNamesWithHistory();
for (const auto& s : quantitiesWithHistory)
{
QString valueString = QString::fromStdString(s);
QString displayString = valueString + " (H)";
displayAndValueStrings[displayString] = valueString;
}
auto quantitiesNoHistory = quantityAnalyzer.quantityNamesNoHistory();
for (const auto& s : quantitiesNoHistory)
{
QString valueString = QString::fromStdString(s);
displayAndValueStrings[valueString] = valueString;
}
}
}
for (const auto& quantity : quantityAnalyzer.quantities())
for (const auto& displayAndValue : displayAndValueStrings)
{
identifierTexts.push_back(QString::fromStdString(quantity));
options.append(caf::PdmOptionItemInfo(displayAndValue.first, displayAndValue.second));
}
if (options.isEmpty())
{
options.push_back(caf::PdmOptionItemInfo("None", "None"));
}
}
}
QList<caf::PdmOptionItemInfo> options;
if (identifierTexts.size() > 0)
{
for (const auto& text : identifierTexts)
else
{
options.append(caf::PdmOptionItemInfo(text, text));
RifEclipseSummaryAddress::SummaryVarCategory category = RifEclipseSummaryAddress::SUMMARY_INVALID;
if (fieldNeedingOptions == &m_wellName)
{
category = RifEclipseSummaryAddress::SUMMARY_WELL;
}
else if (fieldNeedingOptions == &m_region)
{
category = RifEclipseSummaryAddress::SUMMARY_REGION;
}
else if (fieldNeedingOptions == &m_wellGroupName)
{
category = RifEclipseSummaryAddress::SUMMARY_WELL_GROUP;
}
std::set<QString> identifierTexts;
if (category != RifEclipseSummaryAddress::SUMMARY_INVALID)
{
for (auto reader : readers)
{
auto analyzer = analyzerForReader(reader);
if (analyzer)
{
for (const auto& t : analyzer->identifierTexts(category))
{
identifierTexts.insert(t);
}
}
}
}
if (!identifierTexts.empty())
{
for (const auto& text : identifierTexts)
{
options.append(caf::PdmOptionItemInfo(text, text));
}
}
else
{
options.push_back(caf::PdmOptionItemInfo("None", "None"));
}
}
}
else
{
options.push_back(caf::PdmOptionItemInfo("None", "None"));
}
return options;
}
@ -252,27 +356,90 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c
const QVariant& oldValue,
const QVariant& newValue)
{
std::vector<RimSummaryCurve*> curves;
RimSummaryCurveCollection* curveCollection = nullptr;
this->firstAncestorOrThisOfTypeAsserted(curveCollection);
this->firstAncestorOrThisOfType(curveCollection);
if (curveCollection)
{
curves = curveCollection->curves();
}
RimEnsembleCurveSetCollection* ensembleCurveColl = nullptr;
this->firstAncestorOrThisOfType(ensembleCurveColl);
if (changedField == &m_includeEnsembleCasesForCaseStepping)
{
if (curveCollection)
{
curveCollection->updateConnectedEditors();
}
if (ensembleCurveColl)
{
ensembleCurveColl->updateConnectedEditors();
}
RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->getOrCreateMainPlotWindow();
bool forceUpdateOfFieldsInToolbar = true;
mainPlotWindow->updateSummaryPlotToolBar(forceUpdateOfFieldsInToolbar);
return;
}
bool triggerLoadDataAndUpdate = false;
std::string oldValueString = oldValue.toString().toStdString();
std::string newValueString = newValue.toString().toStdString();
if (changedField == &m_summaryCase)
{
if (m_summaryCase())
{
for (auto curve : curveCollection->curves())
caf::PdmPointer<caf::PdmObjectHandle> variantHandle = oldValue.value<caf::PdmPointer<caf::PdmObjectHandle>>();
RimSummaryCase* previousCase = dynamic_cast<RimSummaryCase*>(variantHandle.p());
for (auto curve : curves)
{
if (isYAxisStepping())
{
bool doSetAppearance = curve->summaryCaseY()->isObservedData() != m_summaryCase->isObservedData();
curve->setSummaryCaseY(m_summaryCase);
if (doSetAppearance) curve->forceUpdateCurveAppearanceFromCaseType();
if (previousCase == curve->summaryCaseY())
{
bool doSetAppearance = curve->summaryCaseY()->isObservedData() != m_summaryCase->isObservedData();
curve->setSummaryCaseY(m_summaryCase);
if (doSetAppearance) curve->forceUpdateCurveAppearanceFromCaseType();
}
}
if (isXAxisStepping())
{
curve->setSummaryCaseX(m_summaryCase);
if (previousCase == curve->summaryCaseX())
{
curve->setSummaryCaseX(m_summaryCase);
}
}
}
triggerLoadDataAndUpdate = true;
}
m_wellName.uiCapability()->updateConnectedEditors();
m_wellGroupName.uiCapability()->updateConnectedEditors();
m_region.uiCapability()->updateConnectedEditors();
m_quantity.uiCapability()->updateConnectedEditors();
}
else if (changedField == &m_ensemble)
{
if (m_ensemble() && ensembleCurveColl)
{
caf::PdmPointer<caf::PdmObjectHandle> variantHandle = oldValue.value<caf::PdmPointer<caf::PdmObjectHandle>>();
RimSummaryCaseCollection* previousCollection = dynamic_cast<RimSummaryCaseCollection*>(variantHandle.p());
for (auto curveSet : ensembleCurveColl->curveSets())
{
if (curveSet->summaryCaseCollection() == previousCollection)
{
curveSet->setSummaryCaseCollection(m_ensemble);
}
}
@ -286,28 +453,30 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c
}
else if (changedField == &m_wellName)
{
for (auto curve : curveCollection->curves())
for (auto curve : curves)
{
if (isYAxisStepping())
{
RifEclipseSummaryAddress adr = curve->summaryAddressY();
if (RifEclipseSummaryAddress::isDependentOnWellName(adr))
{
adr.setWellName(m_wellName().toStdString());
curve->setSummaryAddressY(adr);
}
updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL, &adr);
curve->setSummaryAddressY(adr);
}
if (isXAxisStepping())
{
RifEclipseSummaryAddress adr = curve->summaryAddressX();
if (RifEclipseSummaryAddress::isDependentOnWellName(adr))
{
adr.setWellName(m_wellName().toStdString());
updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL, &adr);
curve->setSummaryAddressX(adr);
}
}
curve->setSummaryAddressX(adr);
}
if (ensembleCurveColl)
{
for (auto curveSet : ensembleCurveColl->curveSets())
{
auto adr = curveSet->summaryAddress();
updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL, &adr);
curveSet->setSummaryAddress(adr);
}
}
@ -315,28 +484,30 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c
}
else if (changedField == &m_region)
{
for (auto curve : curveCollection->curves())
for (auto curve : curves)
{
if (isYAxisStepping())
{
RifEclipseSummaryAddress adr = curve->summaryAddressY();
if (adr.category() == RifEclipseSummaryAddress::SUMMARY_REGION)
{
adr.setRegion(m_region());
curve->setSummaryAddressY(adr);
}
updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_REGION, &adr);
curve->setSummaryAddressY(adr);
}
if (isXAxisStepping())
{
RifEclipseSummaryAddress adr = curve->summaryAddressX();
if (adr.category() == RifEclipseSummaryAddress::SUMMARY_REGION)
{
adr.setRegion(m_region());
updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_REGION, &adr);
curve->setSummaryAddressX(adr);
}
}
curve->setSummaryAddressX(adr);
}
if (ensembleCurveColl)
{
for (auto curveSet : ensembleCurveColl->curveSets())
{
auto adr = curveSet->summaryAddress();
updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_REGION, &adr);
curveSet->setSummaryAddress(adr);
}
}
@ -344,51 +515,61 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c
}
else if (changedField == &m_quantity)
{
for (auto curve : curveCollection->curves())
for (auto curve : curves)
{
if (isYAxisStepping())
{
RifEclipseSummaryAddress adr = curve->summaryAddressY();
adr.setQuantityName(m_quantity().toStdString());
auto adr = curve->summaryAddressY();
updateHistoryAndSummaryQuantityIfMatching(oldValue, newValue, &adr);
curve->setSummaryAddressY(adr);
}
if (isXAxisStepping())
{
RifEclipseSummaryAddress adr = curve->summaryAddressX();
adr.setQuantityName(m_quantity().toStdString());
auto adr = curve->summaryAddressX();
updateHistoryAndSummaryQuantityIfMatching(oldValue, newValue, &adr);
curve->setSummaryAddressX(adr);
}
}
if (ensembleCurveColl)
{
for (auto curveSet : ensembleCurveColl->curveSets())
{
auto adr = curveSet->summaryAddress();
updateHistoryAndSummaryQuantityIfMatching(oldValue, newValue, &adr);
curveSet->setSummaryAddress(adr);
}
}
triggerLoadDataAndUpdate = true;
}
else if (changedField == &m_wellGroupName)
{
for (auto curve : curveCollection->curves())
for (auto curve : curves)
{
if (isYAxisStepping())
{
RifEclipseSummaryAddress adr = curve->summaryAddressY();
if (adr.category() == RifEclipseSummaryAddress::SUMMARY_WELL_GROUP)
{
adr.setWellGroupName(m_wellGroupName().toStdString());
curve->setSummaryAddressY(adr);
}
updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL_GROUP, &adr);
curve->setSummaryAddressY(adr);
}
if (isXAxisStepping())
{
RifEclipseSummaryAddress adr = curve->summaryAddressX();
if (adr.category() == RifEclipseSummaryAddress::SUMMARY_WELL_GROUP)
{
adr.setWellGroupName(m_wellGroupName().toStdString());
updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL_GROUP, &adr);
curve->setSummaryAddressX(adr);
}
}
curve->setSummaryAddressX(adr);
}
if (ensembleCurveColl)
{
for (auto curveSet : ensembleCurveColl->curveSets())
{
auto adr = curveSet->summaryAddress();
updateAddressIfMatching(oldValue, newValue, RifEclipseSummaryAddress::SUMMARY_WELL_GROUP, &adr);
curveSet->setSummaryAddress(adr);
}
}
@ -403,12 +584,20 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi(const caf::PdmFieldHandle* c
summaryPlot->updatePlotTitle();
summaryPlot->loadDataAndUpdate();
if (ensembleCurveColl)
{
ensembleCurveColl->updateConnectedEditors();
}
RimSummaryCrossPlot* summaryCrossPlot = dynamic_cast<RimSummaryCrossPlot*>(summaryPlot);
if (summaryCrossPlot)
{
// Trigger update of curve collection (and summary toolbar in main window), as the visibility of combo boxes might
// have been changed due to the updates in this function
curveCollection->updateConnectedEditors();
if (curveCollection)
{
curveCollection->updateConnectedEditors();
}
RiuPlotMainWindow* mainPlotWindow = RiaApplication::instance()->mainPlotWindow();
mainPlotWindow->updateSummaryPlotToolBar();
@ -423,18 +612,38 @@ std::vector<RifSummaryReaderInterface*> RimSummaryPlotSourceStepping::summaryRea
{
std::vector<RifSummaryReaderInterface*> readers;
RimSummaryCurveCollection* curveCollection = nullptr;
this->firstAncestorOrThisOfTypeAsserted(curveCollection);
this->firstAncestorOrThisOfType(curveCollection);
for (auto curve : curveCollection->curves())
if (curveCollection)
{
if (isYAxisStepping() && curve->summaryCaseY())
for (auto curve : curveCollection->curves())
{
readers.push_back(curve->summaryCaseY()->summaryReader());
}
if (isYAxisStepping() && curve->summaryCaseY())
{
readers.push_back(curve->summaryCaseY()->summaryReader());
}
if (isXAxisStepping() && curve->summaryCaseX())
if (isXAxisStepping() && curve->summaryCaseX())
{
readers.push_back(curve->summaryCaseX()->summaryReader());
}
}
}
RimEnsembleCurveSetCollection* ensembleCollection = nullptr;
this->firstAncestorOrThisOfType(ensembleCollection);
if (ensembleCollection)
{
auto curveSets = ensembleCollection->curveSets();
for (const RimEnsembleCurveSet* curveSet : curveSets)
{
readers.push_back(curve->summaryCaseX()->summaryReader());
for (auto curve : curveSet->curves())
{
if (isYAxisStepping() && curve->summaryCaseY())
{
readers.push_back(curve->summaryCaseY()->summaryReader());
}
}
}
}
@ -477,19 +686,31 @@ std::set<RifEclipseSummaryAddress> RimSummaryPlotSourceStepping::addressesCurveC
RimSummaryCurveCollection* curveCollection = nullptr;
this->firstAncestorOrThisOfType(curveCollection);
if (!curveCollection) return addresses;
auto curves = curveCollection->curves();
for (auto c : curves)
if (curveCollection)
{
if (isYAxisStepping())
auto curves = curveCollection->curvesForSourceStepping(m_sourceSteppingType);
for (auto c : curves)
{
addresses.insert(c->summaryAddressY());
}
if (isYAxisStepping())
{
addresses.insert(c->summaryAddressY());
}
if (isXAxisStepping())
if (isXAxisStepping())
{
addresses.insert(c->summaryAddressX());
}
}
}
RimEnsembleCurveSetCollection* ensembleCollection = nullptr;
this->firstAncestorOrThisOfType(ensembleCollection);
if (ensembleCollection)
{
auto curveSets = ensembleCollection->curveSetsForSourceStepping();
for (const RimEnsembleCurveSet* curveSet : curveSets)
{
addresses.insert(c->summaryAddressX());
addresses.insert(curveSet->summaryAddress());
}
}
@ -508,7 +729,7 @@ std::set<RimSummaryCase*> RimSummaryPlotSourceStepping::summaryCasesCurveCollect
if (!curveCollection) return sumCases;
auto curves = curveCollection->curves();
auto curves = curveCollection->curvesForSourceStepping(m_sourceSteppingType);
for (auto c : curves)
{
if (isYAxisStepping())
@ -531,10 +752,12 @@ std::set<RimSummaryCase*> RimSummaryPlotSourceStepping::summaryCasesCurveCollect
std::vector<caf::PdmFieldHandle*> RimSummaryPlotSourceStepping::computeVisibleFieldsAndSetFieldVisibility()
{
m_summaryCase.uiCapability()->setUiHidden(true);
m_includeEnsembleCasesForCaseStepping.uiCapability()->setUiHidden(true);
m_wellName.uiCapability()->setUiHidden(true);
m_wellGroupName.uiCapability()->setUiHidden(true);
m_region.uiCapability()->setUiHidden(true);
m_quantity.uiCapability()->setUiHidden(true);
m_ensemble.uiCapability()->setUiHidden(true);
std::vector<caf::PdmFieldHandle*> fields;
@ -549,61 +772,108 @@ std::vector<caf::PdmFieldHandle*> RimSummaryPlotSourceStepping::computeVisibleFi
m_summaryCase.uiCapability()->setUiHidden(false);
fields.push_back(&m_summaryCase);
m_includeEnsembleCasesForCaseStepping.uiCapability()->setUiHidden(false);
}
}
RiaSummaryCurveAnalyzer analyzer;
analyzer.appendAdresses(addressesCurveCollection());
RifEclipseSummaryAddress::SummaryVarCategory category = RifEclipseSummaryAddress::SUMMARY_INVALID;
auto ensembleColl = ensembleCollection();
if (ensembleColl.size() == 1)
{
if (analyzer.categories().size() == 1)
RimProject* proj = RiaApplication::instance()->project();
if (proj->summaryGroups().size() > 1)
{
category = *(analyzer.categories().begin());
m_ensemble = *(ensembleColl.begin());
m_ensemble.uiCapability()->setUiHidden(false);
fields.push_back(&m_ensemble);
}
}
if (category != RifEclipseSummaryAddress::SUMMARY_INVALID)
std::vector<caf::PdmFieldHandle*> fieldsCommonForAllCurves;
{
if (analyzer.wellNames().size() == 1)
{
QString txt = QString::fromStdString(*(analyzer.wellNames().begin()));
m_wellName = txt;
m_wellName.uiCapability()->setUiHidden(false);
RiaSummaryCurveAnalyzer analyzer;
analyzer.appendAdresses(addressesCurveCollection());
fields.push_back(&m_wellName);
RifEclipseSummaryAddress::SummaryVarCategory category = RifEclipseSummaryAddress::SUMMARY_INVALID;
{
if (analyzer.categories().size() == 1)
{
category = *(analyzer.categories().begin());
}
}
if (analyzer.wellGroupNames().size() == 1)
if (category != RifEclipseSummaryAddress::SUMMARY_INVALID)
{
QString txt = QString::fromStdString(*(analyzer.wellGroupNames().begin()));
m_wellGroupName = txt;
m_wellGroupName.uiCapability()->setUiHidden(false);
if (analyzer.wellNames().size() == 1)
{
QString txt = QString::fromStdString(*(analyzer.wellNames().begin()));
m_wellName = txt;
m_wellName.uiCapability()->setUiHidden(false);
fields.push_back(&m_wellGroupName);
fieldsCommonForAllCurves.push_back(&m_wellName);
}
if (analyzer.wellGroupNames().size() == 1)
{
QString txt = QString::fromStdString(*(analyzer.wellGroupNames().begin()));
m_wellGroupName = txt;
m_wellGroupName.uiCapability()->setUiHidden(false);
fieldsCommonForAllCurves.push_back(&m_wellGroupName);
}
if (analyzer.regionNumbers().size() == 1)
{
m_region = *(analyzer.regionNumbers().begin());
m_region.uiCapability()->setUiHidden(false);
fieldsCommonForAllCurves.push_back(&m_region);
}
if (!analyzer.quantityNameForTitle().empty())
{
QString txt = QString::fromStdString(analyzer.quantityNameForTitle());
m_quantity = txt;
m_quantity.uiCapability()->setUiHidden(false);
fieldsCommonForAllCurves.push_back(&m_quantity);
}
}
}
if (analyzer.regionNumbers().size() == 1)
{
m_region = *(analyzer.regionNumbers().begin());
m_region.uiCapability()->setUiHidden(false);
fields.push_back(&m_region);
}
if (analyzer.quantities().size() == 1)
{
QString txt = QString::fromStdString(*(analyzer.quantities().begin()));
m_quantity = txt;
m_quantity.uiCapability()->setUiHidden(false);
fields.push_back(&m_quantity);
}
for (const auto& f : fieldsCommonForAllCurves)
{
fields.push_back(f);
}
return fields;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RimSummaryCaseCollection*> RimSummaryPlotSourceStepping::ensembleCollection() const
{
std::set<RimSummaryCaseCollection*> sumCases;
RimEnsembleCurveSetCollection* curveCollection = nullptr;
this->firstAncestorOrThisOfType(curveCollection);
if (!curveCollection) return sumCases;
auto curves = curveCollection->curveSets();
for (auto c : curves)
{
sumCases.insert(c->summaryCaseCollection());
}
return sumCases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -656,6 +926,119 @@ void RimSummaryPlotSourceStepping::modifyCurrentIndex(caf::PdmValueField* valueF
RimDataSourceSteppingTools::modifyCurrentIndex(valueField, options, indexOffset);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryPlotSourceStepping::updateAddressIfMatching(const QVariant& oldValue,
const QVariant& newValue,
RifEclipseSummaryAddress::SummaryVarCategory category,
RifEclipseSummaryAddress* adr)
{
if (!adr) return false;
if (category == RifEclipseSummaryAddress::SUMMARY_REGION)
{
int oldInt = oldValue.toInt();
int newInt = newValue.toInt();
if (adr->regionNumber() == oldInt)
{
adr->setRegion(newInt);
return true;
}
}
else if (category == RifEclipseSummaryAddress::SUMMARY_WELL_GROUP)
{
std::string oldString = oldValue.toString().toStdString();
std::string newString = newValue.toString().toStdString();
if (adr->wellGroupName() == oldString)
{
adr->setWellGroupName(newString);
return true;
}
}
else if (RifEclipseSummaryAddress::isDependentOnWellName(category))
{
std::string oldString = oldValue.toString().toStdString();
std::string newString = newValue.toString().toStdString();
if (adr->wellName() == oldString)
{
adr->setWellName(newString);
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryPlotSourceStepping::updateHistoryAndSummaryQuantityIfMatching(const QVariant& oldValue,
const QVariant& newValue,
RifEclipseSummaryAddress* adr)
{
if (!adr) return false;
std::string oldString = oldValue.toString().toStdString();
std::string newString = newValue.toString().toStdString();
if (adr->quantityName() == oldString)
{
adr->setQuantityName(newString);
return true;
}
std::string correspondingOldString = RiaSummaryCurveAnalyzer::correspondingHistorySummaryCurveName(oldString);
std::string correspondingNewString = RiaSummaryCurveAnalyzer::correspondingHistorySummaryCurveName(newString);
if (adr->quantityName() == correspondingOldString)
{
adr->setQuantityName(correspondingNewString);
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCase*> RimSummaryPlotSourceStepping::summaryCasesForSourceStepping()
{
std::vector<RimSummaryCase*> cases;
RimProject* proj = RiaApplication::instance()->project();
for (auto sumCase : proj->allSummaryCases())
{
if (sumCase->isObservedData()) continue;
RimSummaryCaseCollection* sumCaseColl = nullptr;
sumCase->firstAncestorOrThisOfType(sumCaseColl);
if (sumCaseColl && sumCaseColl->isEnsemble())
{
if (m_includeEnsembleCasesForCaseStepping())
{
cases.push_back(sumCase);
}
}
else
{
cases.push_back(sumCase);
}
}
return cases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -31,7 +31,9 @@
#include <set>
class RimSummaryCase;
class RimSummaryCurve;
class RifSummaryReaderInterface;
class RimSummaryCaseCollection;
//==================================================================================================
///
@ -56,6 +58,9 @@ public:
void applyNextCase();
void applyPrevCase();
void applyNextEnsemble();
void applyPrevEnsemble();
void applyNextQuantity();
void applyPrevQuantity();
@ -83,6 +88,7 @@ private:
std::set<RifEclipseSummaryAddress> addressesCurveCollection() const;
std::set<RimSummaryCase*> summaryCasesCurveCollection() const;
std::vector<caf::PdmFieldHandle*> computeVisibleFieldsAndSetFieldVisibility();
std::set<RimSummaryCaseCollection*> ensembleCollection() const;
bool isXAxisStepping() const;
bool isYAxisStepping() const;
@ -91,13 +97,29 @@ private:
void modifyCurrentIndex(caf::PdmValueField* valueField, int indexOffset);
static bool updateAddressIfMatching(const QVariant& oldValue,
const QVariant& newValue,
RifEclipseSummaryAddress::SummaryVarCategory category,
RifEclipseSummaryAddress* adr);
static bool updateHistoryAndSummaryQuantityIfMatching(const QVariant& oldValue,
const QVariant& newValue,
RifEclipseSummaryAddress* adr);
std::vector<RimSummaryCase*> summaryCasesForSourceStepping();
private:
caf::PdmPtrField<RimSummaryCase*> m_summaryCase;
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble;
caf::PdmField<QString> m_wellName;
caf::PdmField<QString> m_wellGroupName;
caf::PdmField<int> m_region;
caf::PdmField<QString> m_quantity;
caf::PdmField<QString> m_placeholderForLabel;
caf::PdmField<bool> m_includeEnsembleCasesForCaseStepping;
SourceSteppingType m_sourceSteppingType;
std::pair<RifSummaryReaderInterface*, RiaSummaryCurveAnalyzer> m_curveAnalyzerForReader;

View File

@ -140,6 +140,8 @@
<file>ToggleOnOff16x16.png</file>
<file>ToggleOnOthersOff16x16.png</file>
<file>ExportCompletionsSymbol16x16.png</file>
<file>StepUpDown16x16.png</file>
<file>StepUpDownCorner16x16.png</file>
<file>TextAnnotation16x16.png</file>
<file>Annotations16x16.png</file>
<file>PolylinesFromFile16x16.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -53,6 +53,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaWeightedHarmonicMeanCalculator-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaCellDividingTools-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/Intersect-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifPerforationIntervalReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellPathCompletions-Test.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@ -2,6 +2,9 @@
#include "RifEclipseDataTableFormatter.h"
#include <QString>
#include <QStringList>
TEST(RifEclipseDataTableFormatter, BasicUsage)
{
QString tableText;
@ -73,3 +76,142 @@ TEST(RifEclipseDataTableFormatter, NoPrefix)
std::cout << tableText.toStdString();
}
TEST(RifEclipseDataTableFormatter, LongLine)
{
QString tableText;
QTextStream stream(&tableText);
RifEclipseDataTableFormatter formatter(stream);
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("50 Character Well Name"),
RifEclipseOutputTableColumn("10 Int #1", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #2", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #3", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #4", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #5", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #6", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #7", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #8", RifEclipseOutputTableDoubleFormatting(), RIGHT),
};
formatter.header(header);
QString fiftyCharacterWellName = "01234567890123456789012345678901234567890123456789";
formatter.add(fiftyCharacterWellName);
for (int i = 0; i < 8; ++i)
{
formatter.add(std::numeric_limits<int>::max()); // 10 characters
}
int fullLineLength = formatter.tableRowPrependText().length() + 9 * formatter.columnSpacing() +
50 + 8 * 10 + formatter.tableRowAppendText().length();
int tableWidth = formatter.tableWidth();
EXPECT_EQ(tableWidth, fullLineLength);
EXPECT_GT(tableWidth, RifEclipseDataTableFormatter::maxEclipseRowWidth());
formatter.rowCompleted();
formatter.tableCompleted();
QStringList tableLines = tableText.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
for (QString line : tableLines)
{
std::cout << QString("Line: \"%1\"").arg(line).toStdString() << std::endl;
if (!line.startsWith(formatter.commentPrefix()))
{
EXPECT_LE(line.length(), RifEclipseDataTableFormatter::maxEclipseRowWidth());
}
}
}
TEST(RifEclipseDataTableFormatter, LongLine132)
{
QString tableText;
QTextStream stream(&tableText);
RifEclipseDataTableFormatter formatter(stream);
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("10 Char"),
RifEclipseOutputTableColumn("10 Int #1", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #2", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #3", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #4", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #5", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #6", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #7", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("I", RifEclipseOutputTableDoubleFormatting(), RIGHT),
};
formatter.header(header);
QString tenCharacterWellName = "0123456789";
formatter.add(tenCharacterWellName);
for (int i = 0; i < 7; ++i)
{
formatter.add(std::numeric_limits<int>::max()); // 10 characters
}
formatter.add(11);
int fullLineLength = formatter.tableRowPrependText().length() + 9 * formatter.columnSpacing() + 10 + 7 * 10 + 2 +
formatter.tableRowAppendText().length();
int tableWidth = formatter.tableWidth();
EXPECT_GE(tableWidth, fullLineLength);
EXPECT_EQ(RifEclipseDataTableFormatter::maxEclipseRowWidth(), fullLineLength);
formatter.rowCompleted();
formatter.tableCompleted();
QStringList tableLines = tableText.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
for (QString line : tableLines)
{
std::cout << QString("Line: \"%1\"").arg(line).toStdString() << std::endl;
if (line.startsWith("0"))
{
EXPECT_EQ(line.length(), RifEclipseDataTableFormatter::maxEclipseRowWidth());
}
}
}
TEST(RifEclipseDataTableFormatter, LongLine133)
{
QString tableText;
QTextStream stream(&tableText);
RifEclipseDataTableFormatter formatter(stream);
std::vector<RifEclipseOutputTableColumn> header = {
RifEclipseOutputTableColumn("10 Char"),
RifEclipseOutputTableColumn("10 Int #1", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #2", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #3", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #4", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #5", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #6", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("10 Int #7", RifEclipseOutputTableDoubleFormatting(), RIGHT),
RifEclipseOutputTableColumn("I", RifEclipseOutputTableDoubleFormatting(), RIGHT),
};
formatter.header(header);
QString fiftyCharacterWellName = "0123456789";
formatter.add(fiftyCharacterWellName);
for (int i = 0; i < 7; ++i)
{
formatter.add(std::numeric_limits<int>::max()); // 10 characters
}
formatter.add(111);
int fullLineLength = formatter.tableRowPrependText().length() + 9 * formatter.columnSpacing() + 10 + 7 * 10 + 3 +
formatter.tableRowAppendText().length();
int tableWidth = formatter.tableWidth();
EXPECT_GE(tableWidth, fullLineLength);
EXPECT_LT(RifEclipseDataTableFormatter::maxEclipseRowWidth(), fullLineLength);
formatter.rowCompleted();
formatter.tableCompleted();
QStringList tableLines = tableText.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
for (QString line : tableLines)
{
std::cout << QString("Line: \"%1\"").arg(line).toStdString() << std::endl;
if (line.startsWith("0"))
{
EXPECT_LE(line.length(), RifEclipseDataTableFormatter::maxEclipseRowWidth());
}
}
}

View File

@ -0,0 +1,50 @@
#include "gtest/gtest.h"
#include "RimWellPathCompletions.h"
#include <QRegExpValidator>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST(RimWellPathCompletions, WellNameRegExp)
{
std::vector<QString> validNames = { "RASASD", "gf0sdf", "sd-ASD12", "1-AA_b" };
std::vector<QString> invalidNames = { ".AdSD", "+gf0sdf", "sd ASD12", "ABCDEFGHIJKL" };
QRegExp rx = RimWellPathCompletions::wellNameForExportRegExp();
EXPECT_TRUE(rx.isValid());
for (QString validName : validNames)
{
EXPECT_TRUE(rx.exactMatch(validName));
}
for (QString invalidName : invalidNames)
{
EXPECT_FALSE(rx.exactMatch(invalidName));
}
}
TEST(RimWellPathCompletions, WellNameRegExpValidator)
{
std::vector<QString> validNames = {"RASASD", "gf0sdf", "sd-ASD12", "1-AA_b"};
std::vector<QString> invalidNames = {".AdSD", "+gf0sdf", "sd ASD12", "ABCDEFGHIJKL"};
QString emptyString = "";
QRegExp rx = RimWellPathCompletions::wellNameForExportRegExp();
QRegExpValidator validator (nullptr);
validator.setRegExp(rx);
for (QString validName : validNames)
{
int dummyPos;
EXPECT_EQ(QValidator::Acceptable, validator.validate(validName, dummyPos));
}
for (QString invalidName : invalidNames)
{
int dummyPos;
EXPECT_EQ(QValidator::Invalid, validator.validate(invalidName, dummyPos));
}
int dummyPos;
EXPECT_EQ(QValidator::Intermediate, validator.validate(emptyString, dummyPos));
}

View File

@ -22,6 +22,7 @@
#include "RiaBaseDefs.h"
#include "RiaPreferences.h"
#include "RimEnsembleCurveSetCollection.h"
#include "RimProject.h"
#include "RimSummaryCurveCollection.h"
#include "RimSummaryPlot.h"
@ -43,6 +44,7 @@
#include "cafPdmUiToolBarEditor.h"
#include "cafPdmUiTreeView.h"
#include "cafQTreeViewStateSerializer.h"
#include "cafSelectionManager.h"
#include <QCloseEvent>
#include <QDockWidget>
@ -494,18 +496,39 @@ void RiuPlotMainWindow::updateWellLogPlotToolBar()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPlotMainWindow::updateSummaryPlotToolBar()
void RiuPlotMainWindow::updateSummaryPlotToolBar(bool forceUpdateUi)
{
RimSummaryPlot* summaryPlot = dynamic_cast<RimSummaryPlot*>(m_activePlotViewWindow.p());
if (summaryPlot)
{
std::vector<caf::PdmFieldHandle*> toolBarFields;
toolBarFields = summaryPlot->summaryCurveCollection()->fieldsToShowInToolbar();
RimEnsembleCurveSetCollection* ensembleCurveSetColl = nullptr;
caf::PdmObjectHandle* selectedObj =
dynamic_cast<caf::PdmObjectHandle*>(caf::SelectionManager::instance()->selectedItem());
if (selectedObj)
{
selectedObj->firstAncestorOrThisOfType(ensembleCurveSetColl);
}
if (ensembleCurveSetColl)
{
toolBarFields = ensembleCurveSetColl->fieldsToShowInToolbar();
}
else
{
toolBarFields = summaryPlot->summaryCurveCollection()->fieldsToShowInToolbar();
}
if (!m_summaryPlotToolBarEditor->isEditorDataValid(toolBarFields))
{
m_summaryPlotToolBarEditor->setFields(toolBarFields);
}
else if (forceUpdateUi)
{
m_summaryPlotToolBarEditor->updateUi();
}
m_summaryPlotToolBarEditor->updateUi();
@ -694,6 +717,16 @@ void RiuPlotMainWindow::selectedObjectsChanged()
m_pdmUiPropertyView->showProperties(firstSelectedObject);
if (firstSelectedObject)
{
RimSummaryPlot* summaryPlot = nullptr;
firstSelectedObject->firstAncestorOrThisOfType(summaryPlot);
if (summaryPlot)
{
updateSummaryPlotToolBar();
}
}
if (uiItems.size() == 1 && m_allowActiveViewChangeFromSelection)
{
// Find the reservoir view or the Plot that the selected item is within

View File

@ -81,7 +81,7 @@ public:
void addToTemporaryWidgets(QWidget* widget);
void updateWellLogPlotToolBar();
void updateSummaryPlotToolBar();
void updateSummaryPlotToolBar(bool forceUpdateUi = false);
protected:
void closeEvent(QCloseEvent* event) override;

View File

@ -399,6 +399,24 @@ set_property(TARGET
PROPERTY FOLDER "AppFwk"
)
option (RESINSIGHT_INCLUDE_APPFWK_TESTS "Enable AppFwk Tests" OFF)
if (RESINSIGHT_INCLUDE_APPFWK_TESTS)
# Unit Tests
add_subdirectory(Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests)
set_property(TARGET cafProjectDataModel_UnitTests PROPERTY FOLDER "AppFwkTests")
add_subdirectory(Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests)
set_property(TARGET cafPdmCore_UnitTests PROPERTY FOLDER "AppFwkTests")
add_subdirectory(Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXml_UnitTests)
set_property(TARGET cafPdmXml_UnitTests PROPERTY FOLDER "AppFwkTests")
# Executables
add_subdirectory(Fwk/AppFwk/cafTests/cafTestApplication)
set_property(TARGET cafTestApplication PROPERTY FOLDER "AppFwkTests")
endif()
################################################################################
# Installation settings

View File

@ -22,7 +22,9 @@
/////////////////////////////////////////////////////////////////////////////////
#include "cafContourLines.h"
#include <algorithm>
#include <list>
const int caf::ContourLines::s_castab[3][3][3] =
{
@ -206,6 +208,104 @@ void caf::ContourLines::create(const std::vector<double>& dataXY, const std::vec
} /* j */
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<caf::ContourLines::ClosedPolygons> caf::ContourLines::create(const std::vector<double>& dataXY,
const std::vector<double>& xPositions,
const std::vector<double>& yPositions,
const std::vector<double>& contourLevels)
{
const double eps = 1.0e-4;
std::vector<std::vector<cvf::Vec2d>> contourLineSegments;
caf::ContourLines::create(dataXY, xPositions, yPositions, contourLevels, &contourLineSegments);
std::vector<ClosedPolygons> closedPolygonsPerLevel(contourLevels.size());
for (size_t i = 0; i < contourLevels.size(); ++i)
{
size_t nPoints = contourLineSegments[i].size();
size_t nSegments = nPoints / 2;
if (nSegments >= 3u) // Need at least three segments for a closed polygon
{
std::list<std::pair<cvf::Vec2d, cvf::Vec2d>> unorderedSegments;
for (size_t j = 0; j < contourLineSegments[i].size(); j += 2)
{
unorderedSegments.push_back(std::make_pair(contourLineSegments[i][j], contourLineSegments[i][j + 1]));
}
std::deque<cvf::Vec2d> closedPolygonDeque;
while (!unorderedSegments.empty())
{
bool expandedPolygon = false;
for (auto listIt = unorderedSegments.begin(); listIt != unorderedSegments.end(); ++listIt)
{
if (closedPolygonDeque.empty() || listIt->first == closedPolygonDeque.back())
{
closedPolygonDeque.push_back(listIt->first);
closedPolygonDeque.push_back(listIt->second);
unorderedSegments.erase(listIt);
expandedPolygon = true;
break;
}
else if (listIt->second == closedPolygonDeque.back())
{
closedPolygonDeque.push_back(listIt->second);
closedPolygonDeque.push_back(listIt->first);
unorderedSegments.erase(listIt);
expandedPolygon = true;
break;
}
else if (listIt->first == closedPolygonDeque.front())
{
closedPolygonDeque.push_front(listIt->first);
closedPolygonDeque.push_front(listIt->second);
unorderedSegments.erase(listIt);
expandedPolygon = true;
break;
}
else if (listIt->second == closedPolygonDeque.front())
{
closedPolygonDeque.push_front(listIt->second);
closedPolygonDeque.push_front(listIt->first);
unorderedSegments.erase(listIt);
expandedPolygon = true;
break;
}
}
if (!expandedPolygon || unorderedSegments.empty())
{
if (closedPolygonDeque.back() != closedPolygonDeque.front())
{
closedPolygonDeque.push_back(closedPolygonDeque.back());
closedPolygonDeque.push_back(closedPolygonDeque.front());
}
// Make sure it is counter clockwise. Use Shoelace formula to calculate signed area.
// https://en.wikipedia.org/wiki/Shoelace_formula
double signedArea = 0.0;
for (size_t j = 0; j < closedPolygonDeque.size() - 1; ++j)
{
signedArea += (closedPolygonDeque[j + 1].x() - closedPolygonDeque[j].x()) *
(closedPolygonDeque[j + 1].y() + closedPolygonDeque[j].y());
}
if (signedArea < 0.0)
{
closedPolygonsPerLevel[i].emplace_back(closedPolygonDeque.rbegin(), closedPolygonDeque.rend());
}
else
{
closedPolygonsPerLevel[i].emplace_back(closedPolygonDeque.begin(), closedPolygonDeque.end());
}
closedPolygonDeque.clear();
}
}
}
}
return closedPolygonsPerLevel;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -25,6 +25,7 @@
#include "cvfBase.h"
#include "cvfVector2.h"
#include <deque>
#include <vector>
namespace caf
@ -32,12 +33,20 @@ namespace caf
class ContourLines
{
public:
typedef std::vector<cvf::Vec2d> ClosedPolygon;
typedef std::vector<ClosedPolygon> ClosedPolygons;
static std::vector<ClosedPolygons> create(const std::vector<double>& dataXY,
const std::vector<double>& xPositions,
const std::vector<double>& yPositions,
const std::vector<double>& contourLevels);
private:
static void create(const std::vector<double>& dataXY,
const std::vector<double>& xPositions,
const std::vector<double>& yPositions,
const std::vector<double>& contourLevels,
std::vector<std::vector<cvf::Vec2d>>* polygons);
private:
static double contourRange(const std::vector<double>& contourLevels);
static double invalidValue(const std::vector<double>& contourLevels);
static double saneValue(int index, const std::vector<double>& dataXY, const std::vector<double>& contourLevels);

View File

@ -54,6 +54,120 @@ namespace caf
CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT(PdmUiComboBoxEditor);
/* GIMP RGBA C-Source image dump (StepDown.c) */
static const struct {
unsigned int width;
unsigned int height;
unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
unsigned char pixel_data[16 * 16 * 4 + 1];
} stepDownImageData = {
16, 16, 4,
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000AAA\001\030\030\030\001"
"\037\037\037\001\020\020\020\001\004\004\004\001\016\016\016\001!!!\001\"\"\"\001(((\001\060\060\060\001$$"
"$\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000UUU\014FFF\242\030\030\030\256\037\037\037\256"
"\022\022\022\256\005\005\005\256\021\021\021\256'''\256...\256\061\061\061\256\067\067\067"
"\256&&&\256AAAzTTT\010\000\000\000\000\000\000\000\000xxx\014```\273\033\033\033\377&&&\377\""
"\"\"\377\017\017\017\377\"\"\"\377LLL\377___\377^^^\377^^^\377AAA\376OOOXTT"
"T\001\000\000\000\000\000\000\000\000\000\000\000\000JJJ\071+++\343&&&\377%%%\377\017\017\017\377'''\377"
"WWW\377]]]\377hhh\377WWW\376NNN\300\177\177\177\032\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000KKK\004\066\066\066z\040\040\040\370\"\"\"\377\014\014\014\377$$$\377SSS\377"
"ccc\377bbb\377NNN\362\202\202\202=\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\064\064\064\040===\312\032\032\032\375\017\017\017\377$$$\377WWW\377bbb"
"\377MMM\374LLL\200iii\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000W"
"WW\001AAA\063###\330\007\007\007\377(((\377VVV\377UUU\377WWW\314\217\217\217\040\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000;;;\001\066\066"
"\066}\027\027\027\371(((\377TTT\377FFF\360\\\\\\C\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000TTT\015\025\025\025\036\040\040\040!<<<<???\360\"\"\""
"\377===\377ddd\266GGG\062\026\026\026\061\040\040\040\066\"\"\"\022\000\000\000\000\000\000\000\000"
"\000\000\000\000HHH\015\071\071\071\256\007\007\007\314\015\015\015\316\024\024\024\326\034\034\034"
"\374\022\022\022\377!!!\377###\335###\326\035\035\035\336\032\032\032\343///\220A"
"AA\010\000\000\000\000\000\000\000\000bbb\014QQQ\264%%%\355$$$\363\035\035\035\352\034\034\034\351"
"&&&\353$$$\344)))\346\061\061\061\345\066\066\066\350\062\062\062\335\064\064\064\201"
"???\007\000\000\000\000\000\000\000\000\000\000\000\000SSS\023@@@?\070\070\070E---=,,,<///>\"\"\"\067&&"
"&\070$$$\070---:CCC\060;;;\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000",
};
QIcon createStepDownIcon()
{
QImage img(stepDownImageData.pixel_data,stepDownImageData.width, stepDownImageData.height, QImage::Format_ARGB32 );
QPixmap pxMap;
pxMap = QPixmap::fromImage(img);
return QIcon(pxMap);
}
static const QIcon& stepDownIcon()
{
static QIcon expandDownIcon(createStepDownIcon());
return expandDownIcon;
}
/* GIMP RGBA C-Source image dump (StepUp.c) */
static const struct {
unsigned int width;
unsigned int height;
unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
unsigned char pixel_data[16 * 16 * 4 + 1];
} stepUpImageData = {
16, 16, 4,
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000;;;\015CCC\060---:"
"$$$\070&&&\070\"\"\"\067///>,,,<---=\070\070\070E@@@?SSS\023\000\000\000\000\000\000\000\000\000\000"
"\000\000???\007\064\064\064\201\062\062\062\335\066\066\066\350\061\061\061\345)))\346$$$\344"
"&&&\353\034\034\034\351\035\035\035\352$$$\363%%%\355QQQ\264bbb\014\000\000\000\000\000\000"
"\000\000AAA\010///\220\032\032\032\343\035\035\035\336###\326###\335!!!\377\022\022\022"
"\377\034\034\034\374\024\024\024\326\015\015\015\316\007\007\007\314\071\071\071\256HHH\015"
"\000\000\000\000\000\000\000\000\000\000\000\000\"\"\"\022\040\040\040\066\026\026\026\061GGG\062ddd\266=="
"=\377\"\"\"\377???\360<<<<\040\040\040!\025\025\025\036TTT\015\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\\\\\\CFFF\360TTT\377(((\377\027\027"
"\027\371\066\066\066};;;\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\217\217\217\040WWW\314UUU\377VVV\377(((\377\007\007\007\377###\330"
"AAA\063WWW\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000iii\006LLL\200M"
"MM\374bbb\377WWW\377$$$\377\017\017\017\377\032\032\032\375===\312\064\064\064\040"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\202\202\202=NNN\362bbb\377"
"ccc\377SSS\377$$$\377\014\014\014\377\"\"\"\377\040\040\040\370\066\066\066zKKK\004"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\177\177\177\032NNN\300WWW\376hhh\377]]]\377"
"WWW\377'''\377\017\017\017\377%%%\377&&&\377+++\343JJJ\071\000\000\000\000\000\000\000\000\000"
"\000\000\000TTT\001OOOXAAA\376^^^\377^^^\377___\377LLL\377\"\"\"\377\017\017\017\377"
"\"\"\"\377&&&\377\033\033\033\377```\273xxx\014\000\000\000\000\000\000\000\000TTT\010AAAz&&&"
"\256\067\067\067\256\061\061\061\256...\256'''\256\021\021\021\256\005\005\005\256\022\022"
"\022\256\037\037\037\256\030\030\030\256FFF\242UUU\014\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000$$$\001\060\060\060\001(((\001\"\"\"\001!!!\001\016\016\016\001\004\004\004\001\020\020\020\001\037"
"\037\037\001\030\030\030\001AAA\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000",
};
QIcon createStepUpIcon()
{
QImage img(stepUpImageData.pixel_data,stepUpImageData.width, stepUpImageData.height, QImage::Format_ARGB32 );
QPixmap pxMap;
pxMap = QPixmap::fromImage(img);
return QIcon(pxMap);
}
static const QIcon& stepUpIcon()
{
static QIcon stepUpIcon(createStepUpIcon());
return stepUpIcon;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -129,22 +243,22 @@ void PdmUiComboBoxEditor::configureAndUpdateUi(const QString& uiConfigName)
if (m_comboBox->count() == 0 || m_comboBox->currentIndex() <= 0)
{
QIcon disabledIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowUp).pixmap(16, 16, QIcon::Disabled));
QIcon disabledIcon(stepUpIcon().pixmap(16, 16, QIcon::Disabled));
m_previousItemButton->setIcon(disabledIcon);
}
else
{
m_previousItemButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowUp));
m_previousItemButton->setIcon(stepUpIcon());
}
if (m_comboBox->count() == 0 || m_comboBox->currentIndex() >= m_comboBox->count() - 1)
{
QIcon disabledIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowDown).pixmap(16, 16, QIcon::Disabled));
QIcon disabledIcon(stepDownIcon().pixmap(16, 16, QIcon::Disabled));
m_nextItemButton->setIcon(disabledIcon);
}
else
{
m_nextItemButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowDown));
m_nextItemButton->setIcon(stepDownIcon());
}
// Update button texts