#2344 Tensor Vectors: Vector visualization code

This commit is contained in:
Rebecca Cox
2018-02-08 16:43:12 +01:00
parent 778119bf62
commit bd0d23520b
15 changed files with 774 additions and 32 deletions

View File

@@ -2031,6 +2031,62 @@ const std::vector<float>& RigFemPartResultsCollection::resultValues(const RigFem
return scalarResults->frameData(frameIndex);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<caf::Ten3f> RigFemPartResultsCollection::tensors(const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex)
{
CVF_ASSERT(resVarAddr.resultPosType == RIG_ELEMENT_NODAL || resVarAddr.resultPosType == RIG_INTEGRATION_POINT);
std::vector<caf::Ten3f> outputTensors;
RigFemResultAddress address11(resVarAddr.resultPosType, resVarAddr.fieldName, "");
RigFemResultAddress address22(resVarAddr.resultPosType, resVarAddr.fieldName, "");
RigFemResultAddress address33(resVarAddr.resultPosType, resVarAddr.fieldName, "");
RigFemResultAddress address12(resVarAddr.resultPosType, resVarAddr.fieldName, "");
RigFemResultAddress address13(resVarAddr.resultPosType, resVarAddr.fieldName, "");
RigFemResultAddress address23(resVarAddr.resultPosType, resVarAddr.fieldName, "");
if (resVarAddr.fieldName == "SE" || resVarAddr.fieldName == "ST")
{
address11.componentName = "S11";
address22.componentName = "S22";
address33.componentName = "S33";
address12.componentName = "S12";
address13.componentName = "S13";
address23.componentName = "S23";
}
else if (resVarAddr.fieldName == "E")
{
address11.componentName = "E11";
address22.componentName = "E22";
address33.componentName = "E33";
address12.componentName = "E12";
address13.componentName = "E13";
address23.componentName = "E23";
}
else
return outputTensors;
const std::vector<float>& v11 = resultValues(address11, partIndex, frameIndex);
const std::vector<float>& v22 = resultValues(address22, partIndex, frameIndex);
const std::vector<float>& v33 = resultValues(address33, partIndex, frameIndex);
const std::vector<float>& v12 = resultValues(address12, partIndex, frameIndex);
const std::vector<float>& v13 = resultValues(address13, partIndex, frameIndex);
const std::vector<float>& v23 = resultValues(address23, partIndex, frameIndex);
size_t valCount = v11.size();
outputTensors.resize(valCount);
for (size_t vIdx = 0; vIdx < valCount; ++vIdx)
{
caf::Ten3f tensor(v11[vIdx], v22[vIdx], v33[vIdx], v12[vIdx], v23[vIdx], v13[vIdx]);
outputTensors[vIdx] = tensor;
}
return outputTensors;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -2151,6 +2207,61 @@ const std::vector<size_t>& RigFemPartResultsCollection::scalarValuesHistogram(co
return this->statistics(resVarAddr)->cellScalarValuesHistogram(frameIndex);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFemPartResultsCollection::minMaxScalarValuesOverAllTensorComponents(const RigFemResultAddress& resVarAddr, int frameIndex, double* localMin, double* localMax)
{
double currentMin = HUGE_VAL;
double currentMax = -HUGE_VAL;
double min;
double max;
std::vector<RigFemResultAddress> addresses;
for (size_t i = 0; i < 6; ++i)
{
addresses.push_back(RigFemResultAddress(resVarAddr.resultPosType, resVarAddr.fieldName, ""));
}
if (resVarAddr.fieldName == "SE" || resVarAddr.fieldName == "ST")
{
addresses[0].componentName = "S11";
addresses[1].componentName = "S22";
addresses[2].componentName = "S33";
addresses[3].componentName = "S12";
addresses[4].componentName = "S13";
addresses[5].componentName = "S23";
}
else if (resVarAddr.fieldName == "E")
{
addresses[0].componentName = "E11";
addresses[1].componentName = "E22";
addresses[2].componentName = "E33";
addresses[3].componentName = "E12";
addresses[4].componentName = "E13";
addresses[5].componentName = "E23";
}
else return;
for (auto address : addresses)
{
this->statistics(address)->minMaxCellScalarValues(frameIndex, min, max);
if (min < currentMin)
{
currentMin = min;
}
if (max > currentMax)
{
currentMax = max;
}
}
*localMin = currentMin;
*localMax = currentMax;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -21,6 +21,8 @@
#include "RigFemResultAddress.h"
#include "cafTensor3.h"
#include "cvfCollection.h"
#include "cvfObject.h"
@@ -64,7 +66,8 @@ public:
bool assertResultsLoaded(const RigFemResultAddress& resVarAddr);
void deleteResult(const RigFemResultAddress& resVarAddr);
const std::vector<float>& resultValues(const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex);
const std::vector<float>& resultValues(const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex);
std::vector<caf::Ten3f> tensors(const RigFemResultAddress& resVarAddr, int partIndex, int frameIndex);
int partCount() const;
int frameCount();
@@ -82,6 +85,8 @@ public:
const std::vector<size_t>& scalarValuesHistogram(const RigFemResultAddress& resVarAddr);
const std::vector<size_t>& scalarValuesHistogram(const RigFemResultAddress& resVarAddr, int frameIndex);
void minMaxScalarValuesOverAllTensorComponents(const RigFemResultAddress& resVarAddr, int frameIndex, double* localMin, double* localMax);
private:
RigFemScalarResultFrames* findOrLoadScalarResult(int partIndex,
const RigFemResultAddress& resVarAddr);

View File

@@ -182,6 +182,14 @@ void RivFemPartPartMgr::appendPartsToModel(cvf::ModelBasicList* model)
if(m_surfaceGridLines.notNull()) model->addPart(m_surfaceGridLines.p());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RivFemPartGeometryGenerator* RivFemPartPartMgr::surfaceGenerator() const
{
return &m_surfaceGenerator;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -57,6 +57,8 @@ public:
void updateCellResultColor(size_t timeStepIndex, RimGeoMechCellColors* cellResultColors);
void appendPartsToModel(cvf::ModelBasicList* model);
const RivFemPartGeometryGenerator* surfaceGenerator() const;
private:
void generatePartGeometry(RivFemPartGeometryGenerator& geoBuilder);

View File

@@ -139,3 +139,11 @@ void RivGeoMechPartMgr::appendGridPartsToModel(cvf::ModelBasicList* model, const
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const cvf::Collection<RivFemPartPartMgr> RivGeoMechPartMgr::femPartMgrs() const
{
return m_femPartPartMgrs;
}

View File

@@ -61,6 +61,7 @@ public:
void appendGridPartsToModel(cvf::ModelBasicList* model, const std::vector<size_t>& partIndices);
void appendGridPartsToModel(cvf::ModelBasicList* model);
const cvf::Collection<RivFemPartPartMgr> femPartMgrs() const;
private:
cvf::Collection<RivFemPartPartMgr> m_femPartPartMgrs;

View File

@@ -140,7 +140,7 @@ void RivGeoMechVizLogic::scheduleRegenOfDirectlyDependentGeometry(RivCellSetEnum
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RivGeoMechPartMgrCache::Key> RivGeoMechVizLogic::keysToVisiblePartMgrs(int timeStepIndex)
std::vector<RivGeoMechPartMgrCache::Key> RivGeoMechVizLogic::keysToVisiblePartMgrs(int timeStepIndex) const
{
std::vector<RivGeoMechPartMgrCache::Key> visiblePartMgrs;
if (m_geomechView->viewController() && m_geomechView->viewController()->isVisibleCellsOveridden())
@@ -163,6 +163,14 @@ std::vector<RivGeoMechPartMgrCache::Key> RivGeoMechVizLogic::keysToVisiblePartMg
return visiblePartMgrs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const cvf::ref<RivGeoMechPartMgrCache> RivGeoMechVizLogic::partMgrCache() const
{
return m_partMgrCache;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -43,17 +43,18 @@ public:
explicit RivGeoMechVizLogic(RimGeoMechView * geomView);
virtual ~RivGeoMechVizLogic();
void appendNoAnimPartsToModel(cvf::ModelBasicList* model);
void appendPartsToModel(int timeStepIndex, cvf::ModelBasicList* model);
void updateCellResultColor(int timeStepIndex, RimGeoMechCellColors* cellResultColors);
void updateStaticCellColors(int timeStepIndex);
void scheduleGeometryRegen(RivCellSetEnum geometryType);
void calculateCurrentTotalCellVisibility(cvf::UByteArray* totalVisibility, int timeStepIndex);
void appendNoAnimPartsToModel(cvf::ModelBasicList* model);
void appendPartsToModel(int timeStepIndex, cvf::ModelBasicList* model);
void updateCellResultColor(int timeStepIndex, RimGeoMechCellColors* cellResultColors);
void updateStaticCellColors(int timeStepIndex);
void scheduleGeometryRegen(RivCellSetEnum geometryType);
void calculateCurrentTotalCellVisibility(cvf::UByteArray* totalVisibility, int timeStepIndex);
std::vector<RivGeoMechPartMgrCache::Key> keysToVisiblePartMgrs(int timeStepIndex) const;
const cvf::ref<RivGeoMechPartMgrCache> partMgrCache() const;
private:
std::vector<RivGeoMechPartMgrCache::Key> keysToVisiblePartMgrs(int timeStepIndex);
RivGeoMechPartMgr* getUpdatedPartMgr(RivGeoMechPartMgrCache::Key partMgrKey);
void scheduleRegenOfDirectlyDependentGeometry(RivCellSetEnum geometryType);
RivGeoMechPartMgr* getUpdatedPartMgr(RivGeoMechPartMgrCache::Key partMgrKey);
void scheduleRegenOfDirectlyDependentGeometry(RivCellSetEnum geometryType);
cvf::ref<RivGeoMechPartMgrCache> m_partMgrCache;
RimGeoMechView* m_geomechView;

View File

@@ -40,6 +40,7 @@ ${CEE_CURRENT_LIST_DIR}RivPartPriority.h
${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.h
${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.h
${CEE_CURRENT_LIST_DIR}RivFishbonesSubsPartMgr.h
${CEE_CURRENT_LIST_DIR}RivTensorResultPartMgr.h
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)
@@ -80,6 +81,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellSpheresPartMgr.cpp
${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.cpp
${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.cpp
${CEE_CURRENT_LIST_DIR}RivFishbonesSubsPartMgr.cpp
${CEE_CURRENT_LIST_DIR}RivTensorResultPartMgr.cpp
)
if (RESINSIGHT_ENABLE_PROTOTYPE_FEATURE_FRACTURES)

View File

@@ -0,0 +1,359 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RivTensorResultPartMgr.h"
#include "RiaApplication.h"
#include "RimGeoMechCase.h"
#include "RimGeoMechView.h"
#include "RimTensorResults.h"
#include "RiuViewer.h"
#include "RigFemPartCollection.h"
#include "RigFemPartGrid.h"
#include "RigFemResultAddress.h"
#include "RigFemPartResultsCollection.h"
#include "RigFemTypes.h"
#include "RigGeoMechCaseData.h"
#include "RivFemPartGeometryGenerator.h"
#include "RivGeoMechPartMgr.h"
#include "RivGeoMechPartMgrCache.h"
#include "RivGeoMechVizLogic.h"
#include "cafDisplayCoordTransform.h"
#include "cafEffectGenerator.h"
#include "cafPdmFieldCvfColor.h"
#include "cafTensor3.h"
#include "cvfArrowGenerator.h"
#include "cvfDrawableGeo.h"
#include "cvfDrawableVectors.h"
#include "cvfGeometryBuilderFaceList.h"
#include "cvfGeometryBuilderTriangles.h"
#include "cvfGeometryUtils.h"
#include "cvfModelBasicList.h"
#include "cvfObject.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfPart.h"
#include "cvfShaderProgram.h"
#include "cvfStructGridGeometryGenerator.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivTensorResultPartMgr::RivTensorResultPartMgr(RimGeoMechView* reservoirView)
{
m_rimReservoirView = reservoirView;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivTensorResultPartMgr::~RivTensorResultPartMgr() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivTensorResultPartMgr::appendDynamicGeometryPartsToModel(cvf::ModelBasicList* model, size_t frameIndex) const
{
if (m_rimReservoirView.isNull()) return;
if (!m_rimReservoirView->geoMechCase()) return;
if (!m_rimReservoirView->geoMechCase()->geoMechData()) return;
if (!m_rimReservoirView->tensorResults()->showTensors()) return;
RigFemPartCollection* femParts = m_rimReservoirView->geoMechCase()->geoMechData()->femParts();
if (!femParts) return;
std::vector<TensorVisualization> tensorVisualizations;
RigFemResultAddress address = m_rimReservoirView->tensorResults()->selectedTensorResult();
if (!isTensorAddress(address)) return;
RigFemPartResultsCollection* resultCollection = m_rimReservoirView->geoMechCase()->geoMechData()->femPartResults();
if (!resultCollection) return;
RimTensorResults::TensorColors tensorColor = m_rimReservoirView->tensorResults()->vectorColors();
cvf::Color3f color1;
cvf::Color3f color2;
cvf::Color3f color3;
if (tensorColor == RimTensorResults::WHITE_GRAY_BLACK)
{
color1 = cvf::Color3f(cvf::Color3::WHITE);
color2 = cvf::Color3f(cvf::Color3::GRAY);
color3 = cvf::Color3f(cvf::Color3::BLACK);
}
else if (tensorColor == RimTensorResults::MAGENTA_BROWN_BLACK)
{
color1 = cvf::Color3f(cvf::Color3::MAGENTA);
color2 = cvf::Color3f(cvf::Color3::BROWN);
color3 = cvf::Color3f(cvf::Color3::BLACK);
}
else
{
color1 = cvf::Color3f(cvf::Color3::BLACK);
color2 = cvf::Color3f(cvf::Color3::BLACK);
color3 = cvf::Color3f(cvf::Color3::BLACK);
}
for (int partIdx = 0; partIdx < femParts->partCount(); partIdx++)
{
std::vector<caf::Ten3f> tensors = resultCollection->tensors(address, partIdx, (int)frameIndex);
const RigFemPart* part = femParts->part(partIdx);
size_t elmCount = part->elementCount();
std::vector<caf::Ten3f> elmTensors;
elmTensors.resize(elmCount);
for (int elmIdx = 0; elmIdx < elmCount; elmIdx++)
{
if (RigFemTypes::elmentNodeCount(part->elementType(elmIdx)) == 8)
{
caf::Ten3f tensorSumOfElmNodes = tensors[part->elementNodeResultIdx(elmIdx, 0)];
for (int i = 1; i < 8; i++)
{
tensorSumOfElmNodes = tensorSumOfElmNodes + tensors[part->elementNodeResultIdx(elmIdx, i)];
}
elmTensors[elmIdx] = tensorSumOfElmNodes * (1.0 / 8.0);
}
}
std::array<std::vector<float>, 3> elmPrincipals;
std::vector<std::array<cvf::Vec3f, 3>> elmPrincipalDirections;
elmPrincipals[0].resize(elmCount);
elmPrincipals[1].resize(elmCount);
elmPrincipals[2].resize(elmCount);
elmPrincipalDirections.resize(elmCount);
for (size_t nIdx = 0; nIdx < elmCount; ++nIdx)
{
cvf::Vec3f principalDirs[3];
cvf::Vec3f principalValues = elmTensors[nIdx].calculatePrincipals(principalDirs);
elmPrincipals[0][nIdx] = principalValues[0];
elmPrincipals[1][nIdx] = principalValues[1];
elmPrincipals[2][nIdx] = principalValues[2];
elmPrincipalDirections[nIdx][0] = principalDirs[0];
elmPrincipalDirections[nIdx][1] = principalDirs[1];
elmPrincipalDirections[nIdx][2] = principalDirs[2];
}
RigFemPartNodes nodes = part->nodes();
double min;
double max;
resultCollection->minMaxScalarValuesOverAllTensorComponents(address, (int)frameIndex, &min, &max);
if (max == 0) max = 1;
float arrowResultScaling = 0.5 * m_rimReservoirView->tensorResults()->sizeScale() * part->characteristicElementSize() / cvf::Math::abs(max);
float arrowConstantScaling = 0.5 * m_rimReservoirView->tensorResults()->sizeScale() * part->characteristicElementSize();
std::vector<RivGeoMechPartMgrCache::Key> partKeys =
m_rimReservoirView->vizLogic()->keysToVisiblePartMgrs((int)frameIndex);
cvf::ref<RivGeoMechPartMgrCache> partMgrCache = m_rimReservoirView->vizLogic()->partMgrCache();
for (const RivGeoMechPartMgrCache::Key& partKey : partKeys)
{
const RivGeoMechPartMgr* partMgr = partMgrCache->partMgr(partKey);
for (auto mgr : partMgr->femPartMgrs())
{
const RivFemPartGeometryGenerator* surfaceGenerator = mgr->surfaceGenerator();
const std::vector<size_t>& quadVerticesToNodeIdxMapping = surfaceGenerator->quadVerticesToNodeIdxMapping();
const std::vector<size_t>& quadVerticesToElmIdx = surfaceGenerator->quadVerticesToGlobalElmIdx();
for (int quadIdx = 0; quadIdx < quadVerticesToNodeIdxMapping.size(); quadIdx = quadIdx + 4)
{
cvf::Vec3f center = nodes.coordinates.at(quadVerticesToNodeIdxMapping[quadIdx]) +
nodes.coordinates.at(quadVerticesToNodeIdxMapping[quadIdx + 2]);
cvf::Vec3d center3d(center / 2);
cvf::Vec3d displayCoord = m_rimReservoirView->displayCoordTransform()->transformToDisplayCoord(center3d);
size_t elmIdx = quadVerticesToElmIdx[quadIdx];
cvf::Vec3f result1;
cvf::Vec3f result2;
cvf::Vec3f result3;
if (m_rimReservoirView->tensorResults()->scaleMethod() == RimTensorResults::RESULT)
{
result1.set(elmPrincipalDirections[elmIdx][0] * arrowResultScaling * elmPrincipals[0][elmIdx]);
result2.set(elmPrincipalDirections[elmIdx][1] * arrowResultScaling * elmPrincipals[1][elmIdx]);
result3.set(elmPrincipalDirections[elmIdx][2] * arrowResultScaling * elmPrincipals[2][elmIdx]);
}
else
{
result1.set(elmPrincipalDirections[elmIdx][0] * arrowConstantScaling);
result2.set(elmPrincipalDirections[elmIdx][1] * arrowConstantScaling);
result3.set(elmPrincipalDirections[elmIdx][2] * arrowConstantScaling);
}
if (m_rimReservoirView->tensorResults()->showPrincipal1())
{
if (cvf::Math::abs(elmPrincipals[0][elmIdx]) > m_rimReservoirView->tensorResults()->threshold())
{
bool isPressure = true;
if (elmPrincipals[0][elmIdx] < 0)
{
isPressure = false;
}
tensorVisualizations.push_back(TensorVisualization(cvf::Vec3f(displayCoord), result1, color1, isPressure));
tensorVisualizations.push_back(TensorVisualization(cvf::Vec3f(displayCoord), -result1, color1, isPressure));
}
}
if (m_rimReservoirView->tensorResults()->showPrincipal2())
{
bool isPressure = true;
if (elmPrincipals[1][elmIdx] < 0)
{
isPressure = false;
}
if (cvf::Math::abs(elmPrincipals[1][elmIdx]) > m_rimReservoirView->tensorResults()->threshold())
{
tensorVisualizations.push_back(TensorVisualization(cvf::Vec3f(displayCoord), result2, color2, isPressure));
tensorVisualizations.push_back(TensorVisualization(cvf::Vec3f(displayCoord), -result2, color2, isPressure));
}
}
if (m_rimReservoirView->tensorResults()->showPrincipal3())
{
bool isPressure = true;
if (elmPrincipals[2][elmIdx] < 0)
{
isPressure = false;
}
if (cvf::Math::abs(elmPrincipals[2][elmIdx]) > m_rimReservoirView->tensorResults()->threshold())
{
tensorVisualizations.push_back(TensorVisualization(cvf::Vec3f(displayCoord), result3, color3, isPressure));
tensorVisualizations.push_back(TensorVisualization(cvf::Vec3f(displayCoord), -result3, color3, isPressure));
}
}
}
}
}
}
if (!tensorVisualizations.empty())
{
cvf::ref<cvf::Part> partIdx = createPart(tensorVisualizations);
model->addPart(partIdx.p());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivTensorResultPartMgr::createPart(std::vector<TensorVisualization>& tensorVisualizations) const
{
cvf::ref<cvf::Vec3fArray> vertices = new cvf::Vec3fArray;
cvf::ref<cvf::Vec3fArray> vecRes = new cvf::Vec3fArray;
cvf::ref<cvf::Color3fArray> colors = new cvf::Color3fArray;
size_t numVecs = tensorVisualizations.size();
vertices->reserve(numVecs);
vecRes->reserve(numVecs);
colors->reserve(numVecs);
for (TensorVisualization tensorVisualization : tensorVisualizations)
{
if (tensorVisualization.isPressure)
{
vertices->add(tensorVisualization.vertex - tensorVisualization.result);
}
else
{
vertices->add(tensorVisualization.vertex);
}
vecRes->add(tensorVisualization.result);
colors->add(tensorVisualization.color);
}
cvf::ref<cvf::DrawableVectors> vectorDrawable;
if (RiaApplication::instance()->useShaders())
{
// NOTE: Drawable vectors must be rendered using shaders when the rest of the application is rendered using shaders
// Drawing vectors using fixed function when rest of the application uses shaders causes visual artifacts
vectorDrawable = new cvf::DrawableVectors("u_transformationMatrix", "u_color");
}
else
{
vectorDrawable = new cvf::DrawableVectors();
}
// Create the arrow glyph for the vector drawer
cvf::GeometryBuilderTriangles arrowBuilder;
cvf::ArrowGenerator gen;
gen.setShaftRelativeRadius(0.020f);
gen.setHeadRelativeRadius(0.05f);
gen.setHeadRelativeLength(0.1f);
gen.setNumSlices(30);
gen.generate(&arrowBuilder);
vectorDrawable->setVectors(vertices.p(), vecRes.p());
vectorDrawable->setColors(colors.p());
vectorDrawable->setGlyph(arrowBuilder.trianglesUShort().p(), arrowBuilder.vertices().p());
cvf::ref<cvf::Part> part = new cvf::Part;
part->setDrawable(vectorDrawable.p());
cvf::ref<cvf::Effect> eff = new cvf::Effect;
if (RiaApplication::instance()->useShaders())
{
if (m_rimReservoirView->viewer())
{
cvf::ref<cvf::OpenGLContext> oglContext = m_rimReservoirView->viewer()->cvfOpenGLContext();
cvf::OpenGLResourceManager* resourceManager = oglContext->resourceManager();
cvf::ref<cvf::ShaderProgram> vectorProgram = resourceManager->getLinkedVectorDrawerShaderProgram(oglContext.p());
eff->setShaderProgram(vectorProgram.p());
}
}
part->setEffect(eff.p());
return part;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RivTensorResultPartMgr::isTensorAddress(RigFemResultAddress address)
{
if (!(address.resultPosType == RIG_ELEMENT_NODAL || address.resultPosType == RIG_INTEGRATION_POINT))
{
return false;
}
if (!(address.fieldName == "SE"
|| address.fieldName == "ST"
|| address.fieldName == "E"))
{
return false;
}
return true;
}

View File

@@ -0,0 +1,67 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cvfBase.h"
#include "cvfColor3.h"
#include "cvfObject.h"
#include "cvfVector3.h"
#include "cafPdmPointer.h"
#include <array>
#include <vector>
namespace cvf
{
class Part;
class ModelBasicList;
}
class RigFemResultAddress;
class RimGeoMechView;
class RivTensorResultPartMgr : public cvf::Object
{
public:
RivTensorResultPartMgr(RimGeoMechView* reservoirView);
~RivTensorResultPartMgr();
void appendDynamicGeometryPartsToModel(cvf::ModelBasicList* model, size_t frameIndex) const;
private:
struct TensorVisualization
{
TensorVisualization(cvf::Vec3f vertex, cvf::Vec3f result, cvf::Color3f color, bool isPressure)
: vertex(vertex), result(result), color(color), isPressure(isPressure) {};
cvf::Vec3f vertex;
cvf::Vec3f result;
cvf::Color3f color;
bool isPressure;
};
private:
cvf::ref<cvf::Part> createPart(std::vector<TensorVisualization>& tensorVisualizations) const;
static bool isTensorAddress(RigFemResultAddress address);
private:
caf::PdmPointer<RimGeoMechView> m_rimReservoirView;
};

View File

@@ -48,6 +48,7 @@
#include "RivGeoMechPartMgrCache.h"
#include "RivGeoMechVizLogic.h"
#include "RivSingleCellPartGenerator.h"
#include "RivTensorResultPartMgr.h"
#include "cafCadNavigation.h"
#include "cafCeetronPlusNavigation.h"
@@ -93,6 +94,7 @@ RimGeoMechView::RimGeoMechView(void)
m_scaleTransform = new cvf::Transform();
m_vizLogic = new RivGeoMechVizLogic(this);
m_tensorPartMgr = new RivTensorResultPartMgr(this);
}
//--------------------------------------------------------------------------------------------------
@@ -212,6 +214,7 @@ void RimGeoMechView::createDisplayModel()
cvf::ref<cvf::ModelBasicList> mainSceneGridVizModel = new cvf::ModelBasicList;
mainSceneGridVizModel->setName("GridModel");
m_vizLogic->appendNoAnimPartsToModel(mainSceneGridVizModel.p());
mainSceneGridVizModel->updateBoundingBoxesRecursive();
mainScene->addModel(mainSceneGridVizModel.p());
@@ -287,6 +290,19 @@ void RimGeoMechView::updateCurrentTimeStep()
frameScene->addModel(wellPathModelBasicList.p());
}
{
// Tensors
cvf::String name = "Tensor";
this->removeModelByName(frameScene, name);
cvf::ref<cvf::ModelBasicList> frameParts = new cvf::ModelBasicList;
frameParts->setName(name);
m_tensorPartMgr->appendDynamicGeometryPartsToModel(frameParts.p(), m_currentTimeStep);
frameParts->updateBoundingBoxesRecursive();
frameScene->addModel(frameParts.p());
}
}
}
@@ -428,6 +444,22 @@ void RimGeoMechView::updateLegendTextAndRanges(RimLegendConfig* legendConfig, in
legendConfig->setTitle(legendTitle);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const cvf::ref<RivGeoMechVizLogic> RimGeoMechView::vizLogic() const
{
return m_vizLogic;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RimTensorResults* RimGeoMechView::tensorResults() const
{
return m_tensorResults;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -43,6 +43,7 @@ class RiuViewer;
class RivGeoMechPartMgr;
class RivGeoMechVizLogic;
class RimLegendConfig;
class RivTensorResultPartMgr;
namespace cvf {
class CellRangeFilter;
@@ -88,6 +89,9 @@ public:
void updateLegendTextAndRanges(RimLegendConfig* legendConfig, int timeStepIndex);
const cvf::ref<RivGeoMechVizLogic> vizLogic() const;
const RimTensorResults* tensorResults() const;
protected:
virtual void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override;
virtual void onLoadDataAndUpdate() override;
@@ -119,5 +123,6 @@ private:
cvf::ref<RivGeoMechVizLogic> m_vizLogic;
cvf::ref<cvf::Transform> m_scaleTransform;
cvf::ref<RivTensorResultPartMgr> m_tensorPartMgr;
};

View File

@@ -18,13 +18,40 @@
#include "RimTensorResults.h"
#include "RigFemResultAddress.h"
#include "RimGeoMechResultDefinition.h"
#include "RimGeoMechView.h"
#include "cafAppEnum.h"
#include "cafPdmUiListEditor.h"
CAF_PDM_SOURCE_INIT(RimTensorResults, "RimTensorResults");
namespace caf
{
template<>
void AppEnum< RimTensorResults::TensorColors >::setUp()
{
addItem(RimTensorResults::WHITE_GRAY_BLACK , "WHITE_GRAY_BLACK", "White, Gray, Black");
addItem(RimTensorResults::MAGENTA_BROWN_BLACK, "MAGENTA_BROWN_BLACK", "Magenta, Brown, Black");
addItem(RimTensorResults::RESULT_COLORS, "RESULT_COLORS", "Result Colors");
setDefault(RimTensorResults::WHITE_GRAY_BLACK);
}
template<>
void AppEnum< RimTensorResults::ScaleMethod >::setUp()
{
addItem(RimTensorResults::RESULT, "RESULT", "Result");
addItem(RimTensorResults::CONSTANT, "CONSTANT", "Constant");
setDefault(RimTensorResults::RESULT);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -52,16 +79,17 @@ RimTensorResults::RimTensorResults()
CAF_PDM_InitField(&m_principal2, "Principal2", true, "Principal 2", "", "", "");
CAF_PDM_InitField(&m_principal3, "Principal3", true, "Principal 3", "", "", "");
CAF_PDM_InitField(&m_threshold, "Threshold", 0.0, "Threshold", "", "", "");
CAF_PDM_InitField(&m_threshold, "Threshold", 0.0f, "Threshold", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_vectorColor, "VectorColor", "Color", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_scaleMethod, "ScaleMethod", "Scale Method", "", "", "");
CAF_PDM_InitField(&m_sizeScale, "SizeScale", 1.0, "Size Scale", "", "", "");
CAF_PDM_InitField(&m_sizeScale, "SizeScale", 1.0f, "Size Scale", "", "", "");
m_resultFieldNameUiField.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
m_resultFieldNameUiField.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP);
m_resultPositionTypeUiField = RIG_ELEMENT_NODAL;
m_resultPositionType = RIG_ELEMENT_NODAL;
m_resultPositionTypeUiField = m_resultPositionType;
}
//--------------------------------------------------------------------------------------------------
@@ -72,6 +100,78 @@ RimTensorResults::~RimTensorResults()
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFemResultAddress RimTensorResults::selectedTensorResult() const
{
return RigFemResultAddress(m_resultPositionType(), m_resultFieldName().toStdString(), "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimTensorResults::showTensors() const
{
return m_showTensors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimTensorResults::showPrincipal1() const
{
return m_principal1();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimTensorResults::showPrincipal2() const
{
return m_principal2();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimTensorResults::showPrincipal3() const
{
return m_principal3();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RimTensorResults::threshold() const
{
return m_threshold();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RimTensorResults::sizeScale() const
{
return m_sizeScale();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimTensorResults::TensorColors RimTensorResults::vectorColors() const
{
return m_vectorColor();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimTensorResults::ScaleMethod RimTensorResults::scaleMethod() const
{
return m_scaleMethod();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -106,7 +206,12 @@ void RimTensorResults::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
if (changedField == &m_resultFieldNameUiField)
{
m_resultPositionType = m_resultPositionTypeUiField;
m_resultFieldName = m_resultFieldNameUiField;
}
RimGeoMechView* view;
firstAncestorOrThisOfType(view);
view->loadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
@@ -145,17 +250,6 @@ QList<caf::PdmOptionItemInfo> RimTensorResults::calculateValueOptions(const caf:
}
}
else if (fieldNeedingOptions == &m_vectorColor)
{
options.push_back(caf::PdmOptionItemInfo("White, Gray, Black", nullptr));
options.push_back(caf::PdmOptionItemInfo("Magenta, Brown, Black", nullptr));
options.push_back(caf::PdmOptionItemInfo("Result Colors", nullptr));
}
else if (fieldNeedingOptions == &m_scaleMethod)
{
options.push_back(caf::PdmOptionItemInfo("Result", nullptr));
options.push_back(caf::PdmOptionItemInfo("Constant", nullptr));
}
return options;
}
@@ -191,4 +285,19 @@ void RimTensorResults::initAfterRead()
{
m_resultPositionTypeUiField = m_resultPositionType;
m_resultFieldNameUiField = m_resultFieldName();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimTensorResults::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute)
{
if (field == &m_resultFieldNameUiField)
{
caf::PdmUiListEditorAttribute* listEditAttr = dynamic_cast<caf::PdmUiListEditorAttribute*>(attribute);
if (listEditAttr)
{
listEditAttr->m_heightHint = 50;
}
}
}

View File

@@ -27,6 +27,7 @@
#include <vector>
class RigFemResultAddress;
//==================================================================================================
///
@@ -36,10 +37,34 @@ class RimTensorResults : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
enum TensorColors
{
WHITE_GRAY_BLACK,
MAGENTA_BROWN_BLACK,
RESULT_COLORS
};
enum ScaleMethod
{
RESULT,
CONSTANT
};
public:
RimTensorResults();
virtual ~RimTensorResults();
RigFemResultAddress selectedTensorResult() const;
bool showTensors() const;
bool showPrincipal1() const;
bool showPrincipal2() const;
bool showPrincipal3() const;
float threshold() const;
float sizeScale() const;
TensorColors vectorColors() const;
ScaleMethod scaleMethod() const;
private:
std::vector<std::string> getResultMetaDataForUIFieldSetting();
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
@@ -47,9 +72,9 @@ private:
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
virtual void initAfterRead() override;
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override;
private:
caf::PdmField<bool> m_showTensors;
caf::PdmField<caf::AppEnum<RigFemResultPosEnum>> m_resultPositionType;
@@ -62,11 +87,10 @@ private:
caf::PdmField<bool> m_principal2;
caf::PdmField<bool> m_principal3;
caf::PdmField<double> m_threshold;
caf::PdmField<float> m_threshold;
caf::PdmField<QString> m_vectorColor;
caf::PdmField<QString> m_scaleMethod;
caf::PdmField<double> m_sizeScale;
caf::PdmField<caf::AppEnum<TensorColors>> m_vectorColor;
caf::PdmField<caf::AppEnum<ScaleMethod>> m_scaleMethod;
caf::PdmField<float> m_sizeScale;
};