ResInsight/ApplicationLibCode/ModelVisualization/RivWellHeadPartMgr.cpp
2021-05-26 13:28:45 +02:00

418 lines
15 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
// Copyright (C) 2011-2012 Ceetron AS
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RivWellHeadPartMgr.h"
#include "RiaGuiApplication.h"
#include "RigActiveCellInfo.h"
#include "RigCell.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "RigSimWellData.h"
#include "RigWellResultPoint.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimSimWellInView.h"
#include "RimSimWellInViewCollection.h"
#include "RivPartPriority.h"
#include "RivPipeGeometryGenerator.h"
#include "RivSectionFlattner.h"
#include "RivSimWellPipeSourceInfo.h"
#include "RivTextLabelSourceInfo.h"
#include "cafDisplayCoordTransform.h"
#include "cafEffectGenerator.h"
#include "cvfArrowGenerator.h"
#include "cvfDrawableGeo.h"
#include "cvfDrawableText.h"
#include "cvfGeometryBuilderFaceList.h"
#include "cvfModelBasicList.h"
#include "cvfPart.h"
#include "cvfTransform.h"
#include "cvfqtUtils.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivWellHeadPartMgr::RivWellHeadPartMgr( RimSimWellInView* well )
: m_rimWell( well )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivWellHeadPartMgr::~RivWellHeadPartMgr()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellHeadPartMgr::buildWellHeadParts( size_t frameIndex,
const caf::DisplayCoordTransform* displayXf,
bool doFlatten,
double xOffset )
{
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 );
if ( doFlatten )
{
whEndPos.x() = xOffset;
whEndPos.y() = 0.0;
whStartPos.x() = xOffset;
whStartPos.y() = 0.0;
whEndPos = displayXf->scaleToDisplaySize( whEndPos );
whStartPos = displayXf->scaleToDisplaySize( whStartPos );
whEndPos.z() += characteristicCellSize;
}
else
{
whEndPos = displayXf->transformToDisplayCoord( whEndPos );
whStartPos = displayXf->transformToDisplayCoord( whStartPos );
whEndPos.z() += characteristicCellSize;
}
}
if ( !well->simWellData()->hasWellResult( frameIndex ) ) return;
const RigWellResultFrame* wellResultFrame = well->simWellData()->wellResultFrame( frameIndex );
double pipeRadius = m_rimWell->pipeRadius();
int pipeCrossSectionVxCount = m_rimWell->pipeCrossSectionVertexCount();
if ( wellResultFrame->m_isOpen )
{
// Use slightly larger well head arrow when well is open
pipeRadius *= 1.1;
}
// Upper part of simulation well pipe is defined to use branch index 0
cvf::ref<RivSimWellPipeSourceInfo> sourceInfo = new RivSimWellPipeSourceInfo( m_rimWell, 0 );
cvf::Vec3d arrowPosition = whEndPos;
arrowPosition.z() += pipeRadius;
// Well head pipe geometry
{
cvf::ref<cvf::Vec3dArray> wellHeadPipeCoords = new cvf::Vec3dArray;
wellHeadPipeCoords->resize( 2 );
wellHeadPipeCoords->set( 0, whStartPos );
wellHeadPipeCoords->set( 1, whEndPos );
cvf::ref<RivPipeGeometryGenerator> pipeGeomGenerator = new RivPipeGeometryGenerator;
pipeGeomGenerator->setPipeCenterCoords( wellHeadPipeCoords.p() );
pipeGeomGenerator->setCrossSectionVertexCount( pipeCrossSectionVxCount );
pipeGeomGenerator->setRadius( pipeRadius );
cvf::ref<cvf::DrawableGeo> pipeSurface = pipeGeomGenerator->createPipeSurface();
cvf::ref<cvf::DrawableGeo> centerLineDrawable = pipeGeomGenerator->createCenterLine();
if ( pipeSurface.notNull() )
{
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "RivWellHeadPartMgr: surface " + cvfqt::Utils::toString( well->name() ) );
part->setDrawable( pipeSurface.p() );
caf::SurfaceEffectGenerator surfaceGen( cvf::Color4f( well->wellPipeColor() ), caf::PO_1 );
if ( viewWithSettings() && viewWithSettings()->isLightingDisabled() )
{
surfaceGen.enableLighting( false );
}
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
part->setEffect( eff.p() );
part->setSourceInfo( sourceInfo.p() );
m_wellHeadPipeSurfacePart = part;
}
if ( centerLineDrawable.notNull() )
{
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "RivWellHeadPartMgr: centerline " + cvfqt::Utils::toString( well->name() ) );
part->setDrawable( centerLineDrawable.p() );
caf::MeshEffectGenerator meshGen( well->wellPipeColor() );
cvf::ref<cvf::Effect> eff = meshGen.generateCachedEffect();
part->setEffect( eff.p() );
part->setSourceInfo( sourceInfo.p() );
m_wellHeadPipeCenterPart = part;
part->updateBoundingBox();
CVF_ASSERT( part->boundingBox().isValid() );
}
}
double arrowLength =
characteristicCellSize * simWellInViewCollection()->wellHeadScaleFactor() * m_rimWell->wellHeadScaleFactor();
if ( wellResultFrame->m_isOpen )
{
// Use slightly larger well head arrow when well is open
arrowLength = 1.1 * arrowLength;
}
cvf::Vec3d textPosition = arrowPosition;
textPosition.z() += 1.2 * arrowLength;
cvf::Mat4f matr;
if ( wellResultFrame->m_productionType != RiaDefines::WellProductionType::PRODUCER )
{
matr = cvf::Mat4f::fromRotation( cvf::Vec3f( 1.0f, 0.0f, 0.0f ), cvf::Math::toRadians( 180.0f ) );
}
double ijScaleFactor = arrowLength / 6;
if ( wellResultFrame->m_isOpen )
{
ijScaleFactor *= 1.1;
}
matr( 0, 0 ) *= ijScaleFactor;
matr( 1, 1 ) *= ijScaleFactor;
matr( 2, 2 ) *= arrowLength;
if ( wellResultFrame->m_productionType != RiaDefines::WellProductionType::PRODUCER )
{
arrowPosition.z() += arrowLength;
}
matr.setTranslation( cvf::Vec3f( arrowPosition ) );
cvf::GeometryBuilderFaceList builder;
cvf::ArrowGenerator gen;
gen.setShaftRelativeRadius( 0.5f );
gen.setHeadRelativeRadius( 1.0f );
gen.setHeadRelativeLength( 0.4f );
gen.setNumSlices( pipeCrossSectionVxCount );
gen.generate( &builder );
cvf::ref<cvf::Vec3fArray> vertices = builder.vertices();
cvf::ref<cvf::UIntArray> faceList = builder.faceList();
size_t i;
for ( i = 0; i < vertices->size(); i++ )
{
cvf::Vec3f v = vertices->get( i );
v.transformPoint( matr );
vertices->set( i, v );
}
cvf::ref<cvf::DrawableGeo> geo1 = new cvf::DrawableGeo;
geo1->setVertexArray( vertices.p() );
geo1->setFromFaceList( *faceList );
geo1->computeNormals();
{
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "RivWellHeadPartMgr: arrow " + cvfqt::Utils::toString( well->name() ) );
part->setDrawable( geo1.p() );
cvf::Color4f headColor( cvf::Color3::GRAY );
RimSimWellInViewCollection* wellColl = nullptr;
if ( m_rimWell )
{
m_rimWell->firstAncestorOrThisOfType( wellColl );
}
if ( wellColl && wellColl->showConnectionStatusColors() )
{
if ( wellResultFrame->m_isOpen )
{
if ( wellResultFrame->m_productionType == RiaDefines::WellProductionType::PRODUCER )
{
headColor = cvf::Color4f( cvf::Color3::GREEN );
}
else if ( wellResultFrame->m_productionType == RiaDefines::WellProductionType::OIL_INJECTOR )
{
headColor = cvf::Color4f( cvf::Color3::ORANGE );
}
else if ( wellResultFrame->m_productionType == RiaDefines::WellProductionType::GAS_INJECTOR )
{
headColor = cvf::Color4f( cvf::Color3::RED );
}
else if ( wellResultFrame->m_productionType == RiaDefines::WellProductionType::WATER_INJECTOR )
{
headColor = cvf::Color4f( cvf::Color3::BLUE );
}
}
}
else
{
headColor = cvf::Color4f( m_rimWell->wellPipeColor() );
}
caf::SurfaceEffectGenerator surfaceGen( headColor, caf::PO_1 );
if ( viewWithSettings() && viewWithSettings()->isLightingDisabled() )
{
surfaceGen.enableLighting( false );
}
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
part->setEffect( eff.p() );
part->setSourceInfo( sourceInfo.p() );
m_wellHeadArrowPart = part;
}
// Show labels for well heads only when well disks are disabled:
// well disk labels are preferred since they have more info.
if ( well->showWellLabel() && !well->name().isEmpty() && !well->showWellDisks() )
{
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( false );
drawableText->setVerticalAlignment( cvf::TextDrawer::CENTER );
drawableText->setTextColor( simWellInViewCollection()->wellLabelColor() );
cvf::String cvfString = cvfqt::Utils::toString( m_rimWell->name() );
cvf::Vec3f textCoord( textPosition );
drawableText->addText( cvfString, textCoord );
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "RivWellHeadPartMgr: text " + cvfString );
part->setDrawable( drawableText.p() );
cvf::ref<cvf::Effect> eff = new cvf::Effect;
part->setEffect( eff.p() );
part->setPriority( RivPartPriority::PartType::Text );
part->setSourceInfo( new RivTextLabelSourceInfo( m_rimWell, cvfString, textCoord ) );
m_wellHeadLabelPart = part;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellHeadPartMgr::clearAllGeometry()
{
m_wellHeadArrowPart = nullptr;
m_wellHeadLabelPart = nullptr;
m_wellHeadPipeCenterPart = nullptr;
m_wellHeadPipeSurfacePart = nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellHeadPartMgr::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;
buildWellHeadParts( frameIndex, displayXf, false, 0.0 );
// Always add pipe part of well head
if ( m_wellHeadPipeCenterPart.notNull() ) model->addPart( m_wellHeadPipeCenterPart.p() );
if ( m_wellHeadPipeSurfacePart.notNull() ) model->addPart( m_wellHeadPipeSurfacePart.p() );
if ( m_rimWell->showWellLabel() && m_wellHeadLabelPart.notNull() )
{
model->addPart( m_wellHeadLabelPart.p() );
}
if ( m_rimWell->showWellHead() && m_wellHeadArrowPart.notNull() )
{
model->addPart( m_wellHeadArrowPart.p() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellHeadPartMgr::appendFlattenedDynamicGeometryPartsToModel( cvf::ModelBasicList* model,
size_t frameIndex,
const caf::DisplayCoordTransform* displayXf,
double xOffset )
{
if ( m_rimWell.isNull() ) return;
if ( !viewWithSettings() ) return;
if ( !m_rimWell->isWellPipeVisible( frameIndex ) ) return;
buildWellHeadParts( frameIndex, displayXf, true, xOffset );
// Always add pipe part of well head
if ( m_wellHeadPipeCenterPart.notNull() ) model->addPart( m_wellHeadPipeCenterPart.p() );
if ( m_wellHeadPipeSurfacePart.notNull() ) model->addPart( m_wellHeadPipeSurfacePart.p() );
if ( m_rimWell->showWellLabel() && m_wellHeadLabelPart.notNull() )
{
model->addPart( m_wellHeadLabelPart.p() );
}
if ( m_rimWell->showWellHead() && m_wellHeadArrowPart.notNull() )
{
model->addPart( m_wellHeadArrowPart.p() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Rim3dView* RivWellHeadPartMgr::viewWithSettings()
{
Rim3dView* view = nullptr;
if ( m_rimWell ) m_rimWell->firstAncestorOrThisOfType( view );
return view;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSimWellInViewCollection* RivWellHeadPartMgr::simWellInViewCollection()
{
RimSimWellInViewCollection* wellCollection = nullptr;
if ( m_rimWell ) m_rimWell->firstAncestorOrThisOfType( wellCollection );
return wellCollection;
}