mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Bubble plot (#5452)
Bubble plot issues #5209 #2285 #5308 Co-authored-by: Kristian Bendiksen <kristian.bendiksen@gmail.com>
This commit is contained in:
@@ -55,6 +55,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RivPolylinesAnnotationSourceInfo.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivPolylineGenerator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivMeasurementPartMgr.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivTextLabelSourceInfo.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivDiskGeometryGenerator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivWellDiskPartMgr.h
|
||||
)
|
||||
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -108,6 +110,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RivPolylinesAnnotationSourceInfo.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivPolylineGenerator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivMeasurementPartMgr.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivTextLabelSourceInfo.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivDiskGeometryGenerator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivWellDiskPartMgr.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
|
||||
141
ApplicationCode/ModelVisualization/RivDiskGeometryGenerator.cpp
Normal file
141
ApplicationCode/ModelVisualization/RivDiskGeometryGenerator.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- 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 "RivDiskGeometryGenerator.h"
|
||||
|
||||
#include "cvfArray.h"
|
||||
#include "cvfBase.h"
|
||||
#include "cvfMath.h"
|
||||
|
||||
#include "cvfGeometryBuilder.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RivDiskGeometryGenerator::RivDiskGeometryGenerator()
|
||||
: m_relativeRadius( 0.085f )
|
||||
, m_relativeLength( 0.25f )
|
||||
, m_numSlices( 20 )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivDiskGeometryGenerator::setRelativeRadius( float relativeRadius )
|
||||
{
|
||||
m_relativeRadius = relativeRadius;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivDiskGeometryGenerator::setRelativeLength( float relativeLength )
|
||||
{
|
||||
m_relativeLength = relativeLength;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivDiskGeometryGenerator::setNumSlices( unsigned int numSlices )
|
||||
{
|
||||
m_numSlices = numSlices;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Create a disc centered at origin with its normal along positive z-axis
|
||||
///
|
||||
/// \param radius Outer radius of the disc
|
||||
/// \param numSlices The number of subdivisions around the z-axis. Must be >= 4
|
||||
/// \param builder Geometry builder to use when creating geometry
|
||||
///
|
||||
/// Creates a disc on the z = 0 plane, centered at origin and with its surface normal pointing
|
||||
/// along the positive z-axis.
|
||||
///
|
||||
/// The disk is subdivided around the z axis into numSlices (as in pizza slices).
|
||||
///
|
||||
/// Each slice is a triangle which does not share any vertices with other slices. This
|
||||
/// is the main different between cvf::GeometryUtils::createDisc. This method generates 3x
|
||||
/// more vertices, but the result is easier to use if you need to color each slice separately.
|
||||
///
|
||||
/// The sourceNodes that will be produced by this method:
|
||||
///
|
||||
/// The following triangle connectivities will be produced:
|
||||
/// (0,1,2) (3,4,5) (6,7,8) ...
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void createDisc( double radius, size_t numSlices, cvf::GeometryBuilder* builder )
|
||||
{
|
||||
CVF_ASSERT( numSlices >= 4 );
|
||||
CVF_ASSERT( builder );
|
||||
|
||||
double da = 2 * cvf::PI_D / numSlices;
|
||||
|
||||
// Find the start point on the circle for each slice
|
||||
cvf::Vec3fArray points;
|
||||
points.reserve( numSlices );
|
||||
for ( size_t i = 0; i < numSlices; i++ )
|
||||
{
|
||||
// Precompute this one (A = i*da;)
|
||||
double sinA = cvf::Math::sin( i * da );
|
||||
double cosA = cvf::Math::cos( i * da );
|
||||
|
||||
cvf::Vec3f point = cvf::Vec3f::ZERO;
|
||||
point.x() = static_cast<float>( -sinA * radius );
|
||||
point.y() = static_cast<float>( cosA * radius );
|
||||
points.add( point );
|
||||
}
|
||||
|
||||
// Create independent vertices per slice
|
||||
cvf::Vec3fArray verts;
|
||||
verts.reserve( numSlices * 3 );
|
||||
for ( size_t i = 0; i < numSlices; i++ )
|
||||
{
|
||||
verts.add( cvf::Vec3f::ZERO );
|
||||
verts.add( points[i] );
|
||||
if ( i == numSlices - 1 )
|
||||
{
|
||||
// Last slice complete the circle.
|
||||
verts.add( points[0] );
|
||||
}
|
||||
else
|
||||
verts.add( points[i + 1] );
|
||||
}
|
||||
|
||||
cvf::uint baseNodeIdx = builder->addVertices( verts );
|
||||
|
||||
// Build the triangles for each slice
|
||||
for ( cvf::uint i = 0; i < static_cast<cvf::uint>( numSlices ); i++ )
|
||||
{
|
||||
cvf::uint v1 = baseNodeIdx + ( i * 3 ) + 0;
|
||||
cvf::uint v2 = baseNodeIdx + ( i * 3 ) + 1;
|
||||
cvf::uint v3 = baseNodeIdx + ( i * 3 ) + 2;
|
||||
|
||||
builder->addTriangle( v1, v2, v3 );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivDiskGeometryGenerator::generate( cvf::GeometryBuilder* builder )
|
||||
{
|
||||
const unsigned int numPolysZDir = 1;
|
||||
createDisc( m_relativeRadius, m_numSlices, builder );
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- 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
|
||||
|
||||
namespace cvf
|
||||
{
|
||||
class GeometryBuilder;
|
||||
}
|
||||
|
||||
class RivDiskGeometryGenerator
|
||||
{
|
||||
public:
|
||||
RivDiskGeometryGenerator();
|
||||
|
||||
void setRelativeRadius( float relativeRadius );
|
||||
void setRelativeLength( float relativeLength );
|
||||
|
||||
void setNumSlices( unsigned int numSlices );
|
||||
|
||||
void generate( cvf::GeometryBuilder* builder );
|
||||
|
||||
private:
|
||||
float m_relativeRadius;
|
||||
float m_relativeLength;
|
||||
|
||||
unsigned int m_numSlices;
|
||||
};
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "RivSimWellPipesPartMgr.h"
|
||||
#include "RivWellConnectionsPartMgr.h"
|
||||
#include "RivWellDiskPartMgr.h"
|
||||
#include "RivWellHeadPartMgr.h"
|
||||
#include "RivWellSpheresPartMgr.h"
|
||||
|
||||
@@ -63,6 +64,7 @@ void RivReservoirSimWellsPartMgr::clearGeometryCache()
|
||||
m_wellPipesPartMgrs.clear();
|
||||
m_wellHeadPartMgrs.clear();
|
||||
m_wellSpheresPartMgrs.clear();
|
||||
m_wellDiskPartMgrs.clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -112,6 +114,25 @@ void RivReservoirSimWellsPartMgr::appendDynamicGeometryPartsToModel( cvf::ModelB
|
||||
m_reservoirView->displayCoordTransform().p() );
|
||||
}
|
||||
|
||||
// Well disks
|
||||
if ( m_reservoirView->wellCollection()->wells.size() != m_wellDiskPartMgrs.size() )
|
||||
{
|
||||
clearGeometryCache();
|
||||
|
||||
for ( size_t i = 0; i < m_reservoirView->wellCollection()->wells.size(); ++i )
|
||||
{
|
||||
RivWellDiskPartMgr* wellDiskMgr = new RivWellDiskPartMgr( m_reservoirView->wellCollection()->wells[i] );
|
||||
m_wellDiskPartMgrs.push_back( wellDiskMgr );
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t wIdx = 0; wIdx != m_wellDiskPartMgrs.size(); ++wIdx )
|
||||
{
|
||||
m_wellDiskPartMgrs[wIdx]->appendDynamicGeometryPartsToModel( model,
|
||||
frameIndex,
|
||||
m_reservoirView->displayCoordTransform().p() );
|
||||
}
|
||||
|
||||
// Well spheres
|
||||
|
||||
if ( m_reservoirView->wellCollection()->wells.size() != m_wellSpheresPartMgrs.size() )
|
||||
|
||||
@@ -33,6 +33,7 @@ class RimEclipseView;
|
||||
class RivSimWellPipesPartMgr;
|
||||
class RivWellHeadPartMgr;
|
||||
class RivWellSpheresPartMgr;
|
||||
class RivWellDiskPartMgr;
|
||||
class RivWellConnectionsPartMgr;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -59,5 +60,6 @@ private:
|
||||
cvf::Collection<RivSimWellPipesPartMgr> m_wellPipesPartMgrs;
|
||||
cvf::Collection<RivWellHeadPartMgr> m_wellHeadPartMgrs;
|
||||
cvf::Collection<RivWellSpheresPartMgr> m_wellSpheresPartMgrs;
|
||||
cvf::Collection<RivWellDiskPartMgr> m_wellDiskPartMgrs;
|
||||
cvf::Collection<RivWellConnectionsPartMgr> m_wellConnPartMgrs;
|
||||
};
|
||||
|
||||
568
ApplicationCode/ModelVisualization/RivWellDiskPartMgr.cpp
Normal file
568
ApplicationCode/ModelVisualization/RivWellDiskPartMgr.cpp
Normal file
@@ -0,0 +1,568 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019- 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 "RivWellDiskPartMgr.h"
|
||||
|
||||
#include "RiaColorTools.h"
|
||||
#include "RiaGuiApplication.h"
|
||||
|
||||
#include "RigActiveCellInfo.h"
|
||||
#include "RigCell.h"
|
||||
#include "RigSimWellData.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimSimWellInView.h"
|
||||
#include "RimSimWellInViewCollection.h"
|
||||
|
||||
#include "RivDiskGeometryGenerator.h"
|
||||
#include "RivPartPriority.h"
|
||||
#include "RivSectionFlattner.h"
|
||||
#include "RivSimWellPipeSourceInfo.h"
|
||||
#include "RivTextLabelSourceInfo.h"
|
||||
|
||||
#include "cafDisplayCoordTransform.h"
|
||||
#include "cafEffectGenerator.h"
|
||||
|
||||
#include "cvfDrawableGeo.h"
|
||||
#include "cvfDrawableText.h"
|
||||
#include "cvfEffect.h"
|
||||
#include "cvfGeometryBuilderDrawableGeo.h"
|
||||
#include "cvfGeometryBuilderFaceList.h"
|
||||
#include "cvfGeometryBuilderTriangles.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
#include "cvfModelBasicList.h"
|
||||
#include "cvfPart.h"
|
||||
#include "cvfRenderState_FF.h"
|
||||
#include "cvfShaderProgram.h"
|
||||
#include "cvfShaderProgramGenerator.h"
|
||||
#include "cvfShaderSourceProvider.h"
|
||||
#include "cvfShaderSourceRepository.h"
|
||||
#include "cvfTransform.h"
|
||||
#include "cvfUniform.h"
|
||||
#include "cvfqtUtils.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RivWellDiskPartMgr::RivWellDiskPartMgr( RimSimWellInView* well )
|
||||
: m_rimWell( well )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RivWellDiskPartMgr::~RivWellDiskPartMgr() {}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivWellDiskPartMgr::buildWellDiskParts( size_t frameIndex, const caf::DisplayCoordTransform* displayXf )
|
||||
{
|
||||
clearAllGeometry();
|
||||
|
||||
if ( !viewWithSettings() ) return;
|
||||
|
||||
RimSimWellInView* well = m_rimWell;
|
||||
|
||||
double characteristicCellSize = viewWithSettings()->ownerCase()->characteristicCellSize();
|
||||
|
||||
cvf::Vec3d whEndPos;
|
||||
cvf::Vec3d whStartPos;
|
||||
{
|
||||
well->wellHeadTopBottomPosition( static_cast<int>( frameIndex ), &whEndPos, &whStartPos );
|
||||
|
||||
whEndPos = displayXf->transformToDisplayCoord( whEndPos );
|
||||
whEndPos.z() += characteristicCellSize;
|
||||
}
|
||||
|
||||
if ( !well->simWellData()->hasWellResult( frameIndex ) ) return;
|
||||
|
||||
auto productionType = well->simWellData()->wellResultFrame( frameIndex ).m_productionType;
|
||||
|
||||
double pipeRadius = m_rimWell->pipeRadius();
|
||||
unsigned int numSectors = 100;
|
||||
|
||||
// Upper part of simulation well pipe is defined to use branch index 0
|
||||
cvf::ref<RivSimWellPipeSourceInfo> sourceInfo = new RivSimWellPipeSourceInfo( m_rimWell, 0 );
|
||||
|
||||
// Well disk geometry
|
||||
double arrowLength = characteristicCellSize * simWellInViewCollection()->wellHeadScaleFactor() *
|
||||
m_rimWell->wellHeadScaleFactor();
|
||||
|
||||
cvf::Vec3d diskPosition = whEndPos;
|
||||
diskPosition.z() += pipeRadius + arrowLength * 2.0;
|
||||
|
||||
cvf::Vec3d textPosition = diskPosition;
|
||||
textPosition.z() += 0.1;
|
||||
|
||||
double ijScaleFactor = arrowLength / 6;
|
||||
|
||||
cvf::ref<cvf::DrawableGeo> geo1 = new cvf::DrawableGeo;
|
||||
{
|
||||
cvf::Mat4f matr;
|
||||
|
||||
matr( 0, 0 ) *= ijScaleFactor;
|
||||
matr( 1, 1 ) *= ijScaleFactor;
|
||||
matr( 2, 2 ) *= ijScaleFactor;
|
||||
|
||||
matr.setTranslation( cvf::Vec3f( diskPosition ) );
|
||||
|
||||
cvf::GeometryBuilderFaceList builder;
|
||||
{
|
||||
RivDiskGeometryGenerator gen;
|
||||
gen.setRelativeRadius( 2.5f * ( m_rimWell->diskScale() ) );
|
||||
gen.setRelativeLength( 0.1f );
|
||||
gen.setNumSlices( numSectors );
|
||||
gen.generate( &builder );
|
||||
}
|
||||
|
||||
cvf::ref<cvf::Vec3fArray> vertices = builder.vertices();
|
||||
cvf::ref<cvf::UIntArray> faceList = builder.faceList();
|
||||
|
||||
for ( size_t i = 0; i < vertices->size(); i++ )
|
||||
{
|
||||
cvf::Vec3f v = vertices->get( i );
|
||||
v.transformPoint( matr );
|
||||
vertices->set( i, v );
|
||||
}
|
||||
|
||||
geo1->setVertexArray( vertices.p() );
|
||||
geo1->setFromFaceList( *faceList );
|
||||
geo1->computeNormals();
|
||||
}
|
||||
|
||||
// Create the fixed function effect
|
||||
{
|
||||
m_fixedFuncEffect = new cvf::Effect;
|
||||
|
||||
cvf::ref<cvf::RenderStateMaterial_FF> mat = new cvf::RenderStateMaterial_FF( cvf::Color3::BLUE );
|
||||
mat->enableColorMaterial( true );
|
||||
m_fixedFuncEffect->setRenderState( mat.p() );
|
||||
|
||||
cvf::ref<cvf::RenderStateLighting_FF> lighting = new cvf::RenderStateLighting_FF;
|
||||
m_fixedFuncEffect->setRenderState( lighting.p() );
|
||||
}
|
||||
|
||||
// Create effect with shader program
|
||||
{
|
||||
m_shaderEffect = new cvf::Effect;
|
||||
|
||||
cvf::ShaderProgramGenerator gen( "PerVertexColor", cvf::ShaderSourceProvider::instance() );
|
||||
gen.addVertexCode( cvf::ShaderSourceRepository::vs_Standard );
|
||||
|
||||
gen.addFragmentCode( cvf::ShaderSourceRepository::src_VaryingColorGlobalAlpha );
|
||||
gen.addFragmentCode( cvf::ShaderSourceRepository::fs_Unlit );
|
||||
m_shaderProg = gen.generate();
|
||||
|
||||
m_shaderProg->setDefaultUniform( new cvf::UniformFloat( "u_alpha", 1.0f ) );
|
||||
|
||||
m_shaderEffect->setShaderProgram( m_shaderProg.p() );
|
||||
}
|
||||
|
||||
cvf::ref<cvf::Effect> effectToUse = RiaGuiApplication::instance()->useShaders() ? m_shaderEffect : m_fixedFuncEffect;
|
||||
|
||||
const cvf::Color3ub colorTable[] = {cvf::Color3ub( cvf::Color3::DARK_GREEN ),
|
||||
cvf::Color3ub( cvf::Color3::DARK_RED ),
|
||||
cvf::Color3ub( cvf::Color3::DARK_BLUE )};
|
||||
|
||||
size_t vertexCount = geo1->vertexCount();
|
||||
cvf::ref<cvf::Color3ubArray> colorArray = new cvf::Color3ubArray;
|
||||
colorArray->resize( vertexCount );
|
||||
colorArray->setAll( cvf::Color3::WHITE );
|
||||
CVF_ASSERT( vertexCount == numSectors * 3 );
|
||||
|
||||
std::vector<std::pair<cvf::String, cvf::Vec3f>> labelsWithPosition;
|
||||
|
||||
int numberPrecision = 2;
|
||||
|
||||
double accumulatedPropertyValue = 0.0;
|
||||
|
||||
QString labelText = m_rimWell->name();
|
||||
RigWellDiskData diskData = m_rimWell->wellDiskData();
|
||||
if ( diskData.isSingleProperty() )
|
||||
{
|
||||
// Set color for the triangle vertices
|
||||
for ( size_t i = 0; i < numSectors * 3; i++ )
|
||||
{
|
||||
cvf::Color3ub c = cvf::Color3::OLIVE;
|
||||
colorArray->set( i, c );
|
||||
}
|
||||
|
||||
accumulatedPropertyValue = diskData.singlePropertyValue();
|
||||
|
||||
if ( simWellInViewCollection()->showWellDiskQuantityLables() )
|
||||
{
|
||||
const double singleProperty = diskData.singlePropertyValue();
|
||||
labelText += QString( "\n%2" ).arg( singleProperty, 0, 'g', numberPrecision );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const double oil = diskData.oil();
|
||||
const double gas = diskData.gas();
|
||||
const double water = diskData.water();
|
||||
|
||||
const double total = diskData.total();
|
||||
const double oilFraction = oil / total;
|
||||
const double gasFraction = gas / total;
|
||||
const double waterFraction = water / total;
|
||||
|
||||
accumulatedPropertyValue = total;
|
||||
|
||||
const double threshold = 1e-6;
|
||||
if ( total > threshold )
|
||||
{
|
||||
double aggregatedFraction = 0.0;
|
||||
|
||||
{
|
||||
auto p = createTextAndLocation( oilFraction / 2.0, diskPosition, ijScaleFactor, oil, numberPrecision );
|
||||
labelsWithPosition.push_back( p );
|
||||
aggregatedFraction += oilFraction;
|
||||
}
|
||||
|
||||
{
|
||||
auto p = createTextAndLocation( aggregatedFraction + gasFraction / 2.0,
|
||||
diskPosition,
|
||||
ijScaleFactor,
|
||||
gas,
|
||||
numberPrecision );
|
||||
labelsWithPosition.push_back( p );
|
||||
aggregatedFraction += gasFraction;
|
||||
}
|
||||
|
||||
{
|
||||
auto p = createTextAndLocation( aggregatedFraction + waterFraction / 2.0,
|
||||
diskPosition,
|
||||
ijScaleFactor,
|
||||
water,
|
||||
numberPrecision );
|
||||
|
||||
labelsWithPosition.push_back( p );
|
||||
aggregatedFraction += waterFraction;
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < numSectors; i++ )
|
||||
{
|
||||
int colorIdx = 0;
|
||||
|
||||
// Find the color for this sector
|
||||
double lim = ( i + 1 ) / static_cast<double>( numSectors );
|
||||
if ( lim <= oilFraction )
|
||||
{
|
||||
colorIdx = 0;
|
||||
}
|
||||
else if ( lim <= oilFraction + gasFraction )
|
||||
{
|
||||
colorIdx = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
colorIdx = 2;
|
||||
}
|
||||
|
||||
// Set color for the triangle vertices
|
||||
for ( int t = 0; t < 3; t++ )
|
||||
{
|
||||
cvf::Color3ub c = colorTable[colorIdx];
|
||||
colorArray->set( i * 3 + t, c );
|
||||
}
|
||||
}
|
||||
}
|
||||
geo1->setColorArray( colorArray.p() );
|
||||
|
||||
double threshold = 0.1;
|
||||
if ( accumulatedPropertyValue > threshold )
|
||||
{
|
||||
{
|
||||
cvf::ref<cvf::Part> part = new cvf::Part;
|
||||
part->setName( "RivWellDiskPartMgr: disk " + cvfqt::Utils::toString( well->name() ) );
|
||||
part->setDrawable( geo1.p() );
|
||||
|
||||
part->setEffect( effectToUse.p() );
|
||||
part->setSourceInfo( sourceInfo.p() );
|
||||
|
||||
m_wellDiskPart = part;
|
||||
}
|
||||
|
||||
// Add visual indicator for well type: producer or injector
|
||||
if ( productionType == RigWellResultFrame::PRODUCER )
|
||||
{
|
||||
const uint numPolysZDir = 1;
|
||||
float bottomRadius = 0.5f;
|
||||
float topRadius = 0.5f;
|
||||
float height = 0.1f;
|
||||
float topOffsetX = 0.0f;
|
||||
float topOffsetY = 0.0f;
|
||||
|
||||
cvf::GeometryBuilderFaceList builder;
|
||||
cvf::GeometryUtils::createObliqueCylinder( bottomRadius,
|
||||
topRadius,
|
||||
height,
|
||||
topOffsetX,
|
||||
topOffsetY,
|
||||
20,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
numPolysZDir,
|
||||
&builder );
|
||||
|
||||
cvf::ref<cvf::Vec3fArray> vertices = builder.vertices();
|
||||
cvf::ref<cvf::UIntArray> faceList = builder.faceList();
|
||||
|
||||
cvf::Mat4f matr;
|
||||
matr( 0, 0 ) *= ijScaleFactor;
|
||||
matr( 1, 1 ) *= ijScaleFactor;
|
||||
matr( 2, 2 ) *= ijScaleFactor;
|
||||
matr.setTranslation( cvf::Vec3f( diskPosition ) );
|
||||
|
||||
for ( size_t i = 0; i < vertices->size(); i++ )
|
||||
{
|
||||
cvf::Vec3f v = vertices->get( i );
|
||||
v.transformPoint( matr );
|
||||
vertices->set( i, v );
|
||||
}
|
||||
|
||||
caf::SurfaceEffectGenerator surfaceGen( cvf::Color4f( cvf::Color3::BLACK ), caf::PO_1 );
|
||||
surfaceGen.enableLighting( false );
|
||||
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
|
||||
|
||||
cvf::ref<cvf::DrawableGeo> injectorGeo = new cvf::DrawableGeo;
|
||||
injectorGeo->setVertexArray( vertices.p() );
|
||||
injectorGeo->setFromFaceList( *faceList );
|
||||
injectorGeo->computeNormals();
|
||||
|
||||
cvf::ref<cvf::Part> part = new cvf::Part;
|
||||
part->setName( "RivWellDiskPartMgr: producer " + cvfqt::Utils::toString( well->name() ) );
|
||||
part->setDrawable( injectorGeo.p() );
|
||||
|
||||
part->setEffect( eff.p() );
|
||||
part->setSourceInfo( sourceInfo.p() );
|
||||
|
||||
m_wellDiskInjectorPart = part;
|
||||
}
|
||||
else if ( productionType == RigWellResultFrame::OIL_INJECTOR ||
|
||||
productionType == RigWellResultFrame::GAS_INJECTOR ||
|
||||
productionType == RigWellResultFrame::WATER_INJECTOR )
|
||||
{
|
||||
cvf::GeometryBuilderFaceList builder;
|
||||
cvf::Vec3f pos( 0.0, 0.0, 0.0 );
|
||||
|
||||
// Construct a cross using to "bars"
|
||||
cvf::GeometryUtils::createBox( pos, 0.2f, 0.8f, 0.1f, &builder );
|
||||
cvf::GeometryUtils::createBox( pos, 0.8f, 0.2f, 0.1f, &builder );
|
||||
|
||||
cvf::ref<cvf::Vec3fArray> vertices = builder.vertices();
|
||||
cvf::ref<cvf::UIntArray> faceList = builder.faceList();
|
||||
|
||||
cvf::Mat4f matr;
|
||||
matr( 0, 0 ) *= ijScaleFactor;
|
||||
matr( 1, 1 ) *= ijScaleFactor;
|
||||
matr( 2, 2 ) *= ijScaleFactor;
|
||||
matr.setTranslation( cvf::Vec3f( diskPosition ) );
|
||||
|
||||
for ( size_t i = 0; i < vertices->size(); i++ )
|
||||
{
|
||||
cvf::Vec3f v = vertices->get( i );
|
||||
v.transformPoint( matr );
|
||||
vertices->set( i, v );
|
||||
}
|
||||
|
||||
cvf::Color4f injectorMarkerColor = getWellInjectionColor( productionType );
|
||||
caf::SurfaceEffectGenerator surfaceGen( injectorMarkerColor, caf::PO_1 );
|
||||
surfaceGen.enableLighting( false );
|
||||
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
|
||||
|
||||
cvf::ref<cvf::DrawableGeo> injectorGeo = new cvf::DrawableGeo;
|
||||
injectorGeo->setVertexArray( vertices.p() );
|
||||
injectorGeo->setFromFaceList( *faceList );
|
||||
injectorGeo->computeNormals();
|
||||
|
||||
cvf::ref<cvf::Part> part = new cvf::Part;
|
||||
part->setName( "RivWellDiskPartMgr: injector " + cvfqt::Utils::toString( well->name() ) );
|
||||
part->setDrawable( injectorGeo.p() );
|
||||
|
||||
part->setEffect( eff.p() );
|
||||
part->setSourceInfo( sourceInfo.p() );
|
||||
|
||||
m_wellDiskInjectorPart = part;
|
||||
}
|
||||
}
|
||||
|
||||
bool showTextLabels = simWellInViewCollection()->showWellDiskQuantityLables() ||
|
||||
( well->showWellLabel() && well->showWellDisks() && !well->name().isEmpty() );
|
||||
|
||||
if ( showTextLabels )
|
||||
{
|
||||
cvf::Font* font = RiaGuiApplication::instance()->defaultWellLabelFont();
|
||||
|
||||
cvf::ref<cvf::DrawableText> drawableText = new cvf::DrawableText;
|
||||
drawableText->setFont( font );
|
||||
drawableText->setCheckPosVisible( false );
|
||||
drawableText->setDrawBorder( false );
|
||||
|
||||
drawableText->setDrawBackground( simWellInViewCollection()->showWellDiskLabelBackground() );
|
||||
drawableText->setVerticalAlignment( cvf::TextDrawer::CENTER );
|
||||
|
||||
auto textColor = simWellInViewCollection()->wellLabelColor();
|
||||
drawableText->setTextColor( textColor );
|
||||
|
||||
auto bgColor = RiaColorTools::contrastColor( textColor );
|
||||
drawableText->setBackgroundColor( bgColor );
|
||||
|
||||
cvf::String cvfString = cvfqt::Utils::toString( labelText );
|
||||
|
||||
cvf::Vec3f textCoord( textPosition );
|
||||
drawableText->addText( cvfString, textCoord );
|
||||
|
||||
if ( simWellInViewCollection()->showWellDiskQuantityLables() )
|
||||
{
|
||||
for ( const auto& t : labelsWithPosition )
|
||||
{
|
||||
drawableText->addText( t.first, t.second );
|
||||
}
|
||||
}
|
||||
|
||||
cvf::ref<cvf::Part> part = new cvf::Part;
|
||||
part->setName( "RivWellDiskPartMgr: text " + cvfString );
|
||||
part->setDrawable( drawableText.p() );
|
||||
|
||||
cvf::ref<cvf::Effect> eff = new cvf::Effect;
|
||||
|
||||
part->setEffect( eff.p() );
|
||||
part->setPriority( RivPartPriority::PartType::Text );
|
||||
|
||||
m_wellDiskLabelPart = part;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<cvf::String, cvf::Vec3f> RivWellDiskPartMgr::createTextAndLocation( const double aggregatedFraction,
|
||||
cvf::Vec3d diskPosition,
|
||||
double ijScaleFactor,
|
||||
const double fraction,
|
||||
int precision )
|
||||
{
|
||||
double sinA = cvf::Math::sin( aggregatedFraction * 2.0 * cvf::PI_F );
|
||||
double cosA = cvf::Math::cos( aggregatedFraction * 2.0 * cvf::PI_F );
|
||||
|
||||
cvf::Vec3f v = cvf::Vec3f( diskPosition );
|
||||
|
||||
double radius = 2.5f * ( m_rimWell->diskScale() );
|
||||
radius *= ijScaleFactor;
|
||||
radius *= 1.1; // Put label outside the disk
|
||||
|
||||
v.x() = v.x() + static_cast<float>( -sinA * radius );
|
||||
v.y() = v.y() + static_cast<float>( cosA * radius );
|
||||
|
||||
auto s = QString::number( fraction, 'g', precision );
|
||||
cvf::String text = cvf::String( s.toStdString() );
|
||||
|
||||
auto p = std::make_pair( text, v );
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivWellDiskPartMgr::clearAllGeometry()
|
||||
{
|
||||
m_wellDiskPart = nullptr;
|
||||
m_wellDiskLabelPart = nullptr;
|
||||
m_wellDiskInjectorPart = nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivWellDiskPartMgr::appendDynamicGeometryPartsToModel( cvf::ModelBasicList* model,
|
||||
size_t frameIndex,
|
||||
const caf::DisplayCoordTransform* displayXf )
|
||||
{
|
||||
if ( m_rimWell.isNull() ) return;
|
||||
if ( !viewWithSettings() ) return;
|
||||
|
||||
if ( !m_rimWell->isWellPipeVisible( frameIndex ) ) return;
|
||||
if ( !m_rimWell->isValidDisk() ) return;
|
||||
|
||||
buildWellDiskParts( frameIndex, displayXf );
|
||||
|
||||
if ( m_rimWell->showWellDisks() && m_wellDiskLabelPart.notNull() )
|
||||
{
|
||||
model->addPart( m_wellDiskLabelPart.p() );
|
||||
}
|
||||
|
||||
if ( m_rimWell->showWellDisks() && m_wellDiskPart.notNull() )
|
||||
{
|
||||
model->addPart( m_wellDiskPart.p() );
|
||||
}
|
||||
|
||||
if ( m_rimWell->showWellDisks() && m_wellDiskInjectorPart.notNull() )
|
||||
{
|
||||
model->addPart( m_wellDiskInjectorPart.p() );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Rim3dView* RivWellDiskPartMgr::viewWithSettings()
|
||||
{
|
||||
Rim3dView* view = nullptr;
|
||||
if ( m_rimWell ) m_rimWell->firstAncestorOrThisOfType( view );
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimSimWellInViewCollection* RivWellDiskPartMgr::simWellInViewCollection()
|
||||
{
|
||||
RimSimWellInViewCollection* wellCollection = nullptr;
|
||||
if ( m_rimWell ) m_rimWell->firstAncestorOrThisOfType( wellCollection );
|
||||
|
||||
return wellCollection;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::Color4f RivWellDiskPartMgr::getWellInjectionColor( RigWellResultFrame::WellProductionType productionType )
|
||||
{
|
||||
if ( productionType == RigWellResultFrame::OIL_INJECTOR )
|
||||
{
|
||||
return cvf::Color4f( cvf::Color3::ORANGE );
|
||||
}
|
||||
else if ( productionType == RigWellResultFrame::GAS_INJECTOR )
|
||||
{
|
||||
return cvf::Color4f( cvf::Color3::RED );
|
||||
}
|
||||
else if ( productionType == RigWellResultFrame::WATER_INJECTOR )
|
||||
{
|
||||
return cvf::Color4f( cvf::Color3::BLUE );
|
||||
}
|
||||
|
||||
return cvf::Color4f( cvf::Color3::BLACK );
|
||||
}
|
||||
81
ApplicationCode/ModelVisualization/RivWellDiskPartMgr.h
Normal file
81
ApplicationCode/ModelVisualization/RivWellDiskPartMgr.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2019 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 "RigWellResultPoint.h"
|
||||
|
||||
#include "cafPdmPointer.h"
|
||||
|
||||
#include "cvfObject.h"
|
||||
#include "cvfString.h"
|
||||
|
||||
namespace cvf
|
||||
{
|
||||
class Part;
|
||||
class ModelBasicList;
|
||||
class Effect;
|
||||
class ShaderProgram;
|
||||
class Color4f;
|
||||
} // namespace cvf
|
||||
|
||||
namespace caf
|
||||
{
|
||||
class DisplayCoordTransform;
|
||||
}
|
||||
|
||||
class Rim3dView;
|
||||
class RimSimWellInView;
|
||||
class RimSimWellInViewCollection;
|
||||
|
||||
class RivWellDiskPartMgr : public cvf::Object
|
||||
{
|
||||
public:
|
||||
RivWellDiskPartMgr( RimSimWellInView* well );
|
||||
~RivWellDiskPartMgr() override;
|
||||
|
||||
void appendDynamicGeometryPartsToModel( cvf::ModelBasicList* model,
|
||||
size_t frameIndex,
|
||||
const caf::DisplayCoordTransform* displayXf );
|
||||
|
||||
private:
|
||||
void buildWellDiskParts( size_t frameIndex, const caf::DisplayCoordTransform* displayXf );
|
||||
|
||||
std::pair<cvf::String, cvf::Vec3f> createTextAndLocation( const double aggregatedFraction,
|
||||
cvf::Vec3d diskPosition,
|
||||
double ijScaleFactor,
|
||||
const double fraction,
|
||||
int precision );
|
||||
|
||||
void clearAllGeometry();
|
||||
Rim3dView* viewWithSettings();
|
||||
RimSimWellInViewCollection* simWellInViewCollection();
|
||||
|
||||
static cvf::Color4f getWellInjectionColor( RigWellResultFrame::WellProductionType productionType );
|
||||
|
||||
private:
|
||||
caf::PdmPointer<RimSimWellInView> m_rimWell;
|
||||
|
||||
cvf::ref<cvf::Part> m_wellDiskPart;
|
||||
cvf::ref<cvf::Part> m_wellDiskLabelPart;
|
||||
cvf::ref<cvf::Part> m_wellDiskInjectorPart;
|
||||
|
||||
cvf::ref<cvf::ShaderProgram> m_shaderProg;
|
||||
cvf::ref<cvf::Effect> m_fixedFuncEffect;
|
||||
cvf::ref<cvf::Effect> m_shaderEffect;
|
||||
};
|
||||
@@ -287,7 +287,9 @@ void RivWellHeadPartMgr::buildWellHeadParts( size_t f
|
||||
m_wellHeadArrowPart = part;
|
||||
}
|
||||
|
||||
if ( well->showWellLabel() && !well->name().isEmpty() )
|
||||
// Show labels for well heads only when well disks are disabled:
|
||||
// well disk labels are prefered since they have more info.
|
||||
if ( well->showWellLabel() && !well->name().isEmpty() && !well->showWellDisks() )
|
||||
{
|
||||
cvf::Font* font = RiaGuiApplication::instance()->defaultWellLabelFont();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user