//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void Rim3dOverlayInfoConfig::updateVisCellStatsIfNeeded()
{
    RimEclipseView * eclipseView = dynamic_cast<RimEclipseView*>(m_viewDef.p());
    RimGeoMechView * geoMechView = dynamic_cast<RimGeoMechView*>(m_viewDef.p());

    if (!m_isVisCellStatUpToDate)
    {
        cvf::ref<RigStatisticsCalculator> calc;
        if (geoMechView)
        {
            RigFemResultAddress resAddress = geoMechView->cellResultResultDefinition()->resultAddress();
            calc = new RigFemNativeVisibleCellsStatCalc(geoMechView->geoMechCase()->geoMechData(),
                                                        resAddress,
                                                        geoMechView->currentTotalCellVisibility().p());
          
        }
        else if (eclipseView)
        {
           size_t scalarIndex = eclipseView->cellResult()->scalarResultIndex();
           calc = new RigEclipseNativeVisibleCellsStatCalc(eclipseView->currentGridCellResults()->cellResults(),
                                                           scalarIndex,
                                                           eclipseView->currentTotalCellVisibility().p());
        }

        m_visibleCellStatistics = new RigStatisticsDataCache(calc.p());
        m_isVisCellStatUpToDate = true;
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimEclipsePropertyFilterCollection::updateIconState()
{
    bool activeIcon = true;

    RimEclipseView* view = NULL;
    this->firstAncestorOrThisOfType(view);
    RimViewController* viewController = view->viewController();
    if (viewController && (viewController->isPropertyFilterOveridden() 
                           || viewController->isVisibleCellsOveridden()))
    {
        activeIcon = false;
    }

    if (!isActive)
    {
        activeIcon = false;
    }

    updateUiIconFromState(activeIcon);

    for (size_t i = 0; i < propertyFilters.size(); i++)
    {
        RimEclipsePropertyFilter* cellFilter = propertyFilters[i];
        cellFilter->updateActiveState();
        cellFilter->updateIconState();
    }
}
Beispiel #3
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void Rim3dOverlayInfoConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
    caf::PdmUiGroup* visGroup = uiOrdering.addNewGroup("Visibility");

    visGroup->add(&m_showAnimProgress);
    visGroup->add(&m_showCaseInfo);
    visGroup->add(&m_showResultInfo);
    RimGeoMechView * geoMechView = dynamic_cast<RimGeoMechView*>(m_viewDef.p());
    if (!geoMechView)
    {
        visGroup->add(&m_showVolumeWeightedMean);
    }

    visGroup->add(&m_showHistogram);

    caf::PdmUiGroup* statGroup = uiOrdering.addNewGroup("Statistics Options");
    RimEclipseView * eclipseView = dynamic_cast<RimEclipseView*>(m_viewDef.p());

    if (!eclipseView || !eclipseView->cellResult()->isFlowDiagOrInjectionFlooding())
    {
        statGroup->add(&m_statisticsTimeRange);
    }
    statGroup->add(&m_statisticsCellRange);

    uiOrdering.skipRemainingFields(true);
}
Beispiel #4
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimWellLogExtractionCurve::setPropertiesFromView(Rim3dView* view)
{
    m_case = view ? view->ownerCase() : nullptr;

    RimGeoMechCase* geomCase = dynamic_cast<RimGeoMechCase*>(m_case.value());
    RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>(m_case.value());
    m_eclipseResultDefinition->setEclipseCase(eclipseCase);
    m_geomResultDefinition->setGeoMechCase(geomCase);

    RimEclipseView* eclipseView = dynamic_cast<RimEclipseView*>(view);
    if (eclipseView)
    {
        m_eclipseResultDefinition->simpleCopy(eclipseView->cellResult());

        m_timeStep = eclipseView->currentTimeStep();
    }

    RimGeoMechView* geoMechView = dynamic_cast<RimGeoMechView*>(view);
    if (geoMechView)
    {
        m_geomResultDefinition->setResultAddress(geoMechView->cellResultResultDefinition()->resultAddress());
        m_timeStep = geoMechView->currentTimeStep();
    }

    clearGeneratedSimWellPaths();
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
RigActiveCellInfo* RimCellRangeFilterCollection::activeCellInfo() const
{
    RimEclipseView* eclipseView = this->eclipseView();
    if (eclipseView)
    {
        return eclipseView->currentActiveCellInfo();
    }

    return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableGeo> RivWellFracturePartMgr::createStimPlanMeshDrawable(RimStimPlanFractureTemplate* stimPlanFracTemplate,
                                                                              const RimEclipseView&        activeView)
{
    if (!stimPlanFracTemplate->fractureGrid()) return nullptr;

    auto displayCoordTransform = activeView.displayCoordTransform();
    if (displayCoordTransform.isNull()) return nullptr;

    std::vector<RigFractureCell> stimPlanCells = stimPlanFracTemplate->fractureGrid()->fractureCells();
    std::vector<cvf::Vec3f>      stimPlanMeshVertices;

    QString resultNameFromColors = activeView.fractureColors()->uiResultName();
    QString resultUnitFromColors = activeView.fractureColors()->unit();

    std::vector<double> prCellResults = stimPlanFracTemplate->fractureGridResults(
        resultNameFromColors, resultUnitFromColors, stimPlanFracTemplate->activeTimeStepIndex());

    m_visibleFracturePolygons.clear();
    for (size_t cIdx = 0; cIdx < stimPlanCells.size(); ++cIdx)
    {
        if (prCellResults[cIdx] > 1e-7)
        {
            const RigFractureCell&  stimPlanCell        = stimPlanCells[cIdx];
            std::vector<cvf::Vec3d> stimPlanCellPolygon = stimPlanCell.getPolygon();
            for (const cvf::Vec3d& cellCorner : stimPlanCellPolygon)
            {
                stimPlanMeshVertices.push_back(static_cast<cvf::Vec3f>(cellCorner));
            }
            m_visibleFracturePolygons.push_back(stimPlanCellPolygon);
        }
    }

    if (stimPlanMeshVertices.empty())
    {
        return nullptr;
    }

    cvf::Mat4d              fractureXf = m_rimFracture->transformMatrix();
    std::vector<cvf::Vec3f> stimPlanMeshVerticesDisplayCoords =
        transformToFractureDisplayCoords(stimPlanMeshVertices, fractureXf, *displayCoordTransform);

    cvf::Vec3fArray* stimPlanMeshVertexList;
    stimPlanMeshVertexList = new cvf::Vec3fArray;
    stimPlanMeshVertexList->assign(stimPlanMeshVerticesDisplayCoords);

    cvf::ref<cvf::DrawableGeo> stimPlanMeshGeo = new cvf::DrawableGeo;
    stimPlanMeshGeo->setVertexArray(stimPlanMeshVertexList);
    cvf::ref<cvf::UIntArray> indices = RivFaultGeometryGenerator::lineIndicesFromQuadVertexArray(stimPlanMeshVertexList);
    cvf::ref<cvf::PrimitiveSetIndexedUInt> prim = new cvf::PrimitiveSetIndexedUInt(cvf::PT_LINES);
    prim->setIndices(indices.p());

    stimPlanMeshGeo->addPrimitiveSet(prim.p());

    return stimPlanMeshGeo;
}
Beispiel #7
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
double RimSimWellInView::pipeRadius()
{
    RimEclipseView* reservoirView;
    firstAncestorOrThisOfTypeAsserted(reservoirView);

    RigEclipseCaseData* rigReservoir = reservoirView->eclipseCase()->eclipseCaseData();
    
    double characteristicCellSize = rigReservoir->mainGrid()->characteristicIJCellSize();

    double pipeRadius = reservoirView->wellCollection()->pipeScaleFactor() * this->pipeScaleFactor() * characteristicCellSize;

    return pipeRadius;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::appendFracturePerforationLengthParts(const RimEclipseView& activeView, cvf::ModelBasicList* model)
{
    if (!m_rimFracture->isChecked()) return;

    if (!m_rimFracture->fractureTemplate()) return;
    if (m_rimFracture->fractureTemplate()->orientationType() != RimFractureTemplate::ALONG_WELL_PATH) return;

    auto displayCoordTransform = activeView.displayCoordTransform();
    if (displayCoordTransform.isNull()) return;

    double characteristicCellSize = activeView.ownerCase()->characteristicCellSize();
    double wellPathRadius         = 1.0;

    {
        RimWellPath* rimWellPath = nullptr;
        m_rimFracture->firstAncestorOrThisOfType(rimWellPath);
        if (rimWellPath)
        {
            wellPathRadius = rimWellPath->wellPathRadius(characteristicCellSize);
        }
    }

    {
        RimSimWellInView* simWell = nullptr;
        m_rimFracture->firstAncestorOrThisOfType(simWell);
        if (simWell)
        {
            wellPathRadius = simWell->pipeRadius();
        }
    }

    std::vector<cvf::Vec3d> displayCoords =
        displayCoordTransform->transformToDisplayCoords(m_rimFracture->perforationLengthCenterLineCoords());

    if (!displayCoords.empty())
    {
        cvf::ref<RivObjectSourceInfo> objectSourceInfo  = new RivObjectSourceInfo(m_rimFracture);
        double                        perforationRadius = wellPathRadius * 1.2;
        cvf::Collection<cvf::Part>    parts;

        RivPipeGeometryGenerator geoGenerator;
        geoGenerator.cylinderWithCenterLineParts(
            &parts, displayCoords, RiaColorTables::wellPathComponentColors()[RiaDefines::PERFORATION_INTERVAL], perforationRadius);

        for (auto part : parts)
        {
            part->setSourceInfo(objectSourceInfo.p());
            model->addPart(part.p());
        }
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
RigMainGrid* RimCellRangeFilterCollection::mainGrid() const
{
    RimEclipseView* eclipseView = this->eclipseView();
    if (eclipseView &&
        eclipseView->eclipseCase() &&
        eclipseView->eclipseCase()->reservoirData() &&
        eclipseView->eclipseCase()->reservoirData()->mainGrid())
    {

        return eclipseView->eclipseCase()->reservoirData()->mainGrid();
    }

    return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString RivWellFracturePartMgr::resultInfoText(const RimEclipseView& activeView, cvf::Vec3d domainIntersectionPoint) const
{
    QString text;

    if (m_rimFracture.isNull()) return text;

    auto* ellipseFractureTemplate = dynamic_cast<RimEllipseFractureTemplate*>(m_rimFracture->fractureTemplate());
    auto* stimPlanTemplate        = dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate());

    if (ellipseFractureTemplate)
    {
        text.append("Result value: CONDUCTIVITY ");
        text.append(QString::number(ellipseFractureTemplate->conductivity()) + "\n");
    }
    else if (stimPlanTemplate)
    {
        const RigFractureCell* cell = getFractureCellAtDomainCoord(domainIntersectionPoint);
        if (cell)
        {
            QString resultNameFromColors = activeView.fractureColors()->uiResultName();
            QString resultUnitFromColors = activeView.fractureColors()->unit();

            double resultValue = stimPlanTemplate->resultValueAtIJ(
                resultNameFromColors, resultUnitFromColors, stimPlanTemplate->activeTimeStepIndex(), cell->getI(), cell->getJ());

            QString resultValueText = QString("%1").arg(resultValue);

            QString iText = QString::number(cell->getI());
            QString jText = QString::number(cell->getJ());

            RimStimPlanColors* stimPlanColors = activeView.fractureColors();
            if (stimPlanColors)
            {
                // Conductivity
                text.append("Result value: ");

                QString resultName = stimPlanTemplate->mapUiResultNameToFileResultName(stimPlanColors->uiResultName());
                text.append(resultName + " ");
                text.append(resultValueText + "\n");
            }

            // Cell index
            text.append("Cell Index: ");
            text.append(iText + ", " + jText + "\n");
        }
    }

    return text;
}
Beispiel #11
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
RimEclipseCase* RicPasteFeatureImpl::findEclipseCase(caf::PdmObjectHandle* objectHandle)
{
    if (dynamic_cast<RimEclipseCase*>(objectHandle))
    {
        return dynamic_cast<RimEclipseCase*>(objectHandle);
    }
    else if (dynamic_cast<RimEclipseView*>(objectHandle))
    {
        RimEclipseView* reservoirView = dynamic_cast<RimEclipseView*>(objectHandle);

        return reservoirView->eclipseCase();
    }

    return nullptr;
}
Beispiel #12
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimFault::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
    this->updateUiIconFromToggleField();

    if (&faultColor == changedField || &showFault == changedField)
    {
        RimEclipseView* reservoirView = NULL;
        this->firstAncestorOfType(reservoirView);

        if (reservoirView) 
        {
            reservoirView->scheduleCreateDisplayModelAndRedraw();
        }
    }
}
Beispiel #13
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimEclipseCase::removeResult(const QString& resultName)
{
    size_t i;
    for (i = 0; i < reservoirViews().size(); i++)
    {
        RimEclipseView* reservoirView = reservoirViews()[i];
        CVF_ASSERT(reservoirView);

        RimEclipseCellColors* result = reservoirView->cellResult;
        CVF_ASSERT(result);

        bool rebuildDisplayModel = false;

        // Set cell result variable to none if displaying 
        if (result->resultVariable() == resultName)
        {
            result->setResultVariable(RimDefines::undefinedResultName());
            result->loadResult();

            rebuildDisplayModel = true;
        }

        std::list< caf::PdmPointer< RimEclipsePropertyFilter > >::iterator it;
        RimEclipsePropertyFilterCollection* propFilterCollection = reservoirView->propertyFilterCollection();

        for (size_t filter = 0; filter < propFilterCollection->propertyFilters().size(); filter++)
        {
            RimEclipsePropertyFilter* propertyFilter = propFilterCollection->propertyFilters()[filter];
            if (propertyFilter->resultDefinition->resultVariable() == resultName)
            {
                propertyFilter->resultDefinition->setResultVariable(RimDefines::undefinedResultName());
                propertyFilter->resultDefinition->loadResult();
                propertyFilter->setToDefaultValues();

                rebuildDisplayModel = true;
            }
        }

        if (rebuildDisplayModel)
        {
            reservoirViews()[i]->createDisplayModelAndRedraw();
        }


        // TODO
        // CellEdgeResults are not considered, as they do not support display of input properties yet
    }
}
Beispiel #14
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
bool Rim3dOverlayInfoConfig::hasInvalidStatisticsCombination()
{
    if (m_viewDef->propertyFilterCollection() 
        && m_viewDef->propertyFilterCollection()->hasActiveDynamicFilters() 
        && m_statisticsCellRange() == VISIBLE_CELLS 
        && m_statisticsTimeRange() == ALL_TIMESTEPS )
    {
        RimEclipseView * eclipseView = dynamic_cast<RimEclipseView*>(m_viewDef.p());
        if (!(eclipseView && eclipseView->cellResult()->isFlowDiagOrInjectionFlooding())) // If isFlowDiagOrInjFlooding then skip this check as ALL_TIMESTEPS is overridden to CURRENT behind the scenes
        {
            return true;
        }
    }

    return false;
}
Beispiel #15
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimEclipseCase::initAfterRead()
{
    size_t j;
    for (j = 0; j < reservoirViews().size(); j++)
    {
        RimEclipseView* riv = reservoirViews()[j];
        CVF_ASSERT(riv);

        riv->setEclipseCase(this);
    }

    if (caseUserDescription().isEmpty() && !caseName().isEmpty())
    {
        caseUserDescription = caseName;
    }
}
Beispiel #16
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
RimEclipseView* RimEclipseCase::createAndAddReservoirView()
{
    RimEclipseView* riv = new RimEclipseView();
    riv->setEclipseCase(this);
    riv->cellEdgeResult()->resultVariable = "MULT";
    riv->cellEdgeResult()->enableCellEdgeColors = false;

    caf::PdmDocument::updateUiIconStateRecursively(riv);

    size_t i = reservoirViews().size();
    riv->name = QString("View %1").arg(i + 1);

    reservoirViews().push_back(riv);

    return riv;
}
Beispiel #17
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
bool RiuRelativePermeabilityPlotUpdater::queryDataAndUpdatePlot(const RimEclipseView& eclipseView, size_t gridIndex, size_t gridLocalCellIndex, RiuRelativePermeabilityPlotPanel* plotPanel)
{
    CVF_ASSERT(plotPanel);

    RimEclipseResultCase* eclipseResultCase = dynamic_cast<RimEclipseResultCase*>(eclipseView.eclipseCase());
    RigEclipseCaseData* eclipseCaseData = eclipseResultCase ? eclipseResultCase->eclipseCaseData() : nullptr;
    if (eclipseResultCase && eclipseCaseData && eclipseResultCase->flowDiagSolverInterface())
    {
        size_t activeCellIndex = CellLookupHelper::mapToActiveCellIndex(eclipseCaseData, gridIndex, gridLocalCellIndex);
        if (activeCellIndex != cvf::UNDEFINED_SIZE_T)
        {
            //cvf::Trace::show("Updating RelPerm plot for active cell index: %d", static_cast<int>(activeCellIndex));

            std::vector<RigFlowDiagSolverInterface::RelPermCurve> relPermCurveArr = eclipseResultCase->flowDiagSolverInterface()->calculateRelPermCurves(activeCellIndex);

            // Make sure we load the results that we'll query below
            RigCaseCellResultsData* cellResultsData = eclipseCaseData->results(RiaDefines::MATRIX_MODEL);
            cellResultsData->findOrLoadScalarResult(RiaDefines::DYNAMIC_NATIVE, "SWAT");
            cellResultsData->findOrLoadScalarResult(RiaDefines::DYNAMIC_NATIVE, "SGAS");
            cellResultsData->findOrLoadScalarResult(RiaDefines::STATIC_NATIVE, "SATNUM");

            // Fetch SWAT and SGAS cell values for the selected cell
            const size_t timeStepIndex = static_cast<size_t>(eclipseView.currentTimeStep());
            cvf::ref<RigResultAccessor> swatAccessor = RigResultAccessorFactory::createFromNameAndType(eclipseCaseData, gridIndex, RiaDefines::MATRIX_MODEL, timeStepIndex, "SWAT", RiaDefines::DYNAMIC_NATIVE);
            cvf::ref<RigResultAccessor> sgasAccessor = RigResultAccessorFactory::createFromNameAndType(eclipseCaseData, gridIndex, RiaDefines::MATRIX_MODEL, timeStepIndex, "SGAS", RiaDefines::DYNAMIC_NATIVE);
            cvf::ref<RigResultAccessor> satnumAccessor = RigResultAccessorFactory::createFromNameAndType(eclipseCaseData, gridIndex, RiaDefines::MATRIX_MODEL, timeStepIndex, "SATNUM", RiaDefines::STATIC_NATIVE);
            const double cellSWAT = swatAccessor.notNull() ? swatAccessor->cellScalar(gridLocalCellIndex) : HUGE_VAL;
            const double cellSGAS = sgasAccessor.notNull() ? sgasAccessor->cellScalar(gridLocalCellIndex) : HUGE_VAL;
            const double cellSATNUM = satnumAccessor.notNull() ? satnumAccessor->cellScalar(gridLocalCellIndex) : HUGE_VAL;
            //cvf::Trace::show("cellSWAT = %f  cellSGAS = %f  cellSATNUM = %f", cellSWAT, cellSGAS, cellSATNUM);

            QString cellRefText = constructCellReferenceText(eclipseCaseData, gridIndex, gridLocalCellIndex, cellSATNUM);
            QString caseName = eclipseResultCase->caseUserDescription;

            plotPanel->setPlotData(eclipseCaseData->unitsType(), relPermCurveArr, cellSWAT, cellSGAS, caseName, cellRefText);

            return true;
        }
    }

    return false;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RicPasteEclipseViewsFeature::onActionTriggered(bool isChecked)
{
    PdmObjectHandle* destinationObject = dynamic_cast<PdmObjectHandle*>(SelectionManager::instance()->selectedItem());

    RimEclipseCase* eclipseCase = RicPasteFeatureImpl::findEclipseCase(destinationObject);
    assert(eclipseCase);

    PdmObjectGroup objectGroup;
    RicPasteFeatureImpl::findObjectsFromClipboardRefs(&objectGroup);

    if (objectGroup.objects.size() == 0) return;

    std::vector<caf::PdmPointer<RimEclipseView> > eclipseViews;
    objectGroup.objectsByType(&eclipseViews);

    // Add cases to case group
    for (size_t i = 0; i < eclipseViews.size(); i++)
    {
        RimEclipseView* rimReservoirView = dynamic_cast<RimEclipseView*>(eclipseViews[i]->xmlCapability()->copyByXmlSerialization(PdmDefaultObjectFactory::instance()));
        CVF_ASSERT(rimReservoirView);

        QString nameOfCopy = QString("Copy of ") + rimReservoirView->name;
        rimReservoirView->name = nameOfCopy;
        eclipseCase->reservoirViews().push_back(rimReservoirView);

        rimReservoirView->setEclipseCase(eclipseCase);

        // Resolve references after reservoir view has been inserted into Rim structures
        // Intersections referencing a well path/ simulation well requires this
        // TODO: initAfterReadRecursively can probably be removed
        rimReservoirView->initAfterReadRecursively();
        rimReservoirView->resolveReferencesRecursively();

        rimReservoirView->loadDataAndUpdate();

        caf::PdmDocument::updateUiIconStateRecursively(rimReservoirView);

        eclipseCase->updateConnectedEditors();
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
cvf::ref<RivCrossSectionHexGridIntf> RivCrossSectionPartMgr::createHexGridInterface()
{

    RimEclipseView* eclipseView;
    m_rimCrossSection->firstAnchestorOrThisOfType(eclipseView);
    if (eclipseView)
    {
        RigMainGrid* grid = NULL;
        grid = eclipseView->eclipseCase()->reservoirData()->mainGrid();
        return new RivEclipseCrossSectionGrid(grid, eclipseView->currentActiveCellInfo(), m_rimCrossSection->showInactiveCells());
    }

    RimGeoMechView* geoView;
    m_rimCrossSection->firstAnchestorOrThisOfType(geoView);
    if (geoView)
    {
        RigFemPart* femPart = geoView->geoMechCase()->geoMechData()->femParts()->part(0);
        return new RivFemCrossSectionGrid(femPart);
    }

    return NULL;
}
Beispiel #20
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimSimWellInView::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
    RimEclipseView* reservoirView = nullptr;
    this->firstAncestorOrThisOfType(reservoirView);
    if (reservoirView)
    {
        if (&showWellLabel == changedField ||
            &showWellHead == changedField ||
            &showWellPipe == changedField ||
            &showWellSpheres == changedField ||
            &wellPipeColor == changedField)
        {
            reservoirView->scheduleCreateDisplayModelAndRedraw();
            schedule2dIntersectionViewUpdate();
        }
        else if (&showWell == changedField ||
                 &showWellCells == changedField ||
                 &showWellCellFence == changedField)
             
        {
            reservoirView->scheduleGeometryRegen(VISIBLE_WELL_CELLS);
            reservoirView->scheduleCreateDisplayModelAndRedraw();
            schedule2dIntersectionViewUpdate();
        }
        else if (   &pipeScaleFactor == changedField
                 || &wellHeadScaleFactor == changedField)
        {
            reservoirView->scheduleSimWellGeometryRegen();
            reservoirView->scheduleCreateDisplayModelAndRedraw();
            schedule2dIntersectionViewUpdate();
        }
    }

    RimSimWellInViewCollection* wellColl = nullptr;
    this->firstAncestorOrThisOfType(wellColl);
    if (wellColl)
    {
        wellColl->updateStateForVisibilityCheckboxes();

        RiuMainWindow::instance()->refreshDrawStyleActions();
    }

    if (changedField == &wellPipeColor)
    {
        RimSimWellInViewCollection::updateWellAllocationPlots();
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RicImportInputEclipseCaseOpmFeature::onActionTriggered(bool isChecked)
{
    RiaApplication* app = RiaApplication::instance();
    QString defaultDir = app->lastUsedDialogDirectory("INPUT_FILES");
    QString fileName = QFileDialog::getOpenFileName(RiuMainWindow::instance(), "Import Eclipse Input file", defaultDir, "Eclipse Input Files (*.GRDECL);;All Files (*.*)");

    if (fileName.isEmpty()) return;

    // Remember the path to next time
    app->setLastUsedDialogDirectory("INPUT_FILES", QFileInfo(fileName).absolutePath());

    RimProject* proj = app->project();
    RimEclipseCaseCollection* analysisModels = proj->activeOilField() ? proj->activeOilField()->analysisModels() : NULL;
    if (analysisModels)
    {
        // This code originates from RiaApplication::openInputEclipseCaseFromFileNames

        RimEclipseInputCaseOpm* rimInputReservoir = new RimEclipseInputCaseOpm();
        proj->assignCaseIdToCase(rimInputReservoir);

        rimInputReservoir->importNewEclipseGridAndProperties(fileName);

        analysisModels->cases.push_back(rimInputReservoir);

        RimEclipseView* riv = rimInputReservoir->createAndAddReservoirView();

        riv->cellResult()->setResultType(RimDefines::INPUT_PROPERTY);
        riv->hasUserRequestedAnimation = true;

        riv->loadDataAndUpdate();

        if (!riv->cellResult()->hasResult())
        {
            riv->cellResult()->setResultVariable(RimDefines::undefinedResultName());
        }

        analysisModels->updateConnectedEditors();

        RiuMainWindow::instance()->selectAsCurrentItem(riv->cellResult());
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RicPasteEclipseCasesFeature::addCasesToGridCaseGroup(PdmObjectGroup& objectGroup, RimIdenticalGridCaseGroup* gridCaseGroup)
{
    RimProject* proj = RiaApplication::instance()->project();
    CVF_ASSERT(proj);

    std::vector<RimEclipseResultCase*> resultCases;

    for (size_t i = 0; i < objectGroup.objects.size(); i++)
    {
        RimEclipseResultCase* eclCase = dynamic_cast<RimEclipseResultCase*>(objectGroup.objects[i]);
        if (eclCase)
        {
            RimEclipseResultCase* eclCaseCopy = dynamic_cast<RimEclipseResultCase*>(eclCase->copyByXmlSerialization(PdmDefaultObjectFactory::instance()));
            resultCases.push_back(eclCaseCopy);
        }
    }

    if (resultCases.size() == 0)
    {
        return;
    }

    RimEclipseResultCase* mainResultCase = NULL;
    std::vector< std::vector<int> > mainCaseGridDimensions;

    // Read out main grid and main grid dimensions if present in case group
    if (gridCaseGroup->mainCase())
    {
        mainResultCase = dynamic_cast<RimEclipseResultCase*>(gridCaseGroup->mainCase());
        CVF_ASSERT(mainResultCase);

        mainResultCase->readGridDimensions(mainCaseGridDimensions);
    }

    std::vector<RimEclipseResultCase*> insertedCases;

    // Add cases to case group
    for (size_t i = 0; i < resultCases.size(); i++)
    {
        RimEclipseResultCase* rimResultReservoir = resultCases[i];

        proj->assignCaseIdToCase(rimResultReservoir);

        if (gridCaseGroup->contains(rimResultReservoir))
        {
            continue;
        }

        insertedCases.push_back(rimResultReservoir);
    }

    // Load stuff 
    for (size_t i = 0; i < insertedCases.size(); i++)
    {
        RimEclipseResultCase* rimResultReservoir = insertedCases[i];

        if (!mainResultCase)
        {
            rimResultReservoir->openEclipseGridFile();
            rimResultReservoir->readGridDimensions(mainCaseGridDimensions);

            mainResultCase = rimResultReservoir;
        }
        else
        {
            std::vector< std::vector<int> > caseGridDimensions;
            rimResultReservoir->readGridDimensions(caseGridDimensions);

            bool identicalGrid = RigGridManager::isGridDimensionsEqual(mainCaseGridDimensions, caseGridDimensions);
            if (!identicalGrid)
            {
                continue;
            }

            if (!rimResultReservoir->openAndReadActiveCellData(mainResultCase->reservoirData()))
            {
                CVF_ASSERT(false);
            }
        }

        RimOilField* activeOilField = proj ? proj->activeOilField() : NULL;
        RimEclipseCaseCollection* analysisModels = (activeOilField) ? activeOilField->analysisModels() : NULL;
        if (analysisModels) analysisModels->insertCaseInCaseGroup(gridCaseGroup, rimResultReservoir);

        caf::PdmDocument::updateUiIconStateRecursively(rimResultReservoir);

        gridCaseGroup->updateConnectedEditors();

        for (size_t rvIdx = 0; rvIdx < rimResultReservoir->reservoirViews.size(); rvIdx++)
        {
            RimEclipseView* riv = rimResultReservoir->reservoirViews()[rvIdx];
            riv->loadDataAndUpdate();
        }
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RicfExportSimWellFractureCompletions::execute()
{
    RimProject* project = RiaApplication::instance()->project();
    RicExportCompletionDataSettingsUi* exportSettings = project->dialogData()->exportCompletionData();
    
    exportSettings->timeStep = m_timeStep;
    exportSettings->fileSplit = m_fileSplit;
    exportSettings->compdatExport = m_compdatExport;

    {
        bool foundCase = false;
        for (RimEclipseCase* c : RiaApplication::instance()->project()->activeOilField()->analysisModels->cases())
        {
            if (c->caseId() == m_caseId())
            {
                exportSettings->caseToApply = c;
                foundCase = true;
                break;
            }
        }
        if (!foundCase)
        {
            RiaLogging::error(QString("exportSimWellCompletions: Could not find case with ID %1").arg(m_caseId()));
            return;
        }
    }

    QString exportFolder = RicfCommandFileExecutor::instance()->getExportPath(RicfCommandFileExecutor::COMPLETIONS);
    if (exportFolder.isNull())
    {
        exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath("completions");
    }
    exportSettings->folder = exportFolder;

    std::vector<RimEclipseView*> views;
    for (Rim3dView* v : exportSettings->caseToApply->views())
    {
        RimEclipseView* eclipseView = dynamic_cast<RimEclipseView*>(v);
        if (eclipseView && eclipseView->name() == m_viewName())
        {
            views.push_back(eclipseView);
        }
    }
    if (views.empty())
    {
        RiaLogging::error(QString("exportSimWellCompletions: Could not find any views named \"%1\" in the case with ID %2").arg(m_viewName).arg(m_caseId()));
        return;
    }

    std::vector<RimSimWellInView*> simWells;
    if (m_simWellNames().empty())
    {
        for (RimEclipseView* view : views)
        {
            for (auto simWell : view->wellCollection()->wells)
            {
                if (simWell->showWell())
                {
                    simWells.push_back(simWell);
                }
            }
        }
    }
    else
    {
        for (const QString& wellPathName : m_simWellNames())
        {
            for (RimEclipseView* view : views)
            {
                RimSimWellInView* simWell = view->wellCollection()->findWell(wellPathName);
                if (simWell)
                {
                    simWells.push_back(simWell);
                }
                else
                {
                    RiaLogging::warning(QString("exportSimWellCompletions: Could not find well with name %1 in view \"%2\" on case with ID %2").arg(wellPathName).arg(m_viewName).arg(m_caseId()));
                }
            }
        }
    }

    std::vector<RimWellPath*> wellPaths;

    RicWellPathExportCompletionDataFeatureImpl::exportCompletions(wellPaths, simWells, *exportSettings);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::appendGeometryPartsToModel(cvf::ModelBasicList* model, const RimEclipseView& eclView)
{
    if (!m_rimFracture->isChecked() || !eclView.fractureColors()->isChecked()) return;

    if (!m_rimFracture->fractureTemplate()) return;

    m_visibleFracturePolygons.clear();

    double characteristicCellSize = eclView.ownerCase()->characteristicCellSize();

    cvf::Collection<cvf::Part>   parts;
    RimStimPlanFractureTemplate* stimPlanFracTemplate =
        dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate());

    if (stimPlanFracTemplate)
    {
        if (eclView.fractureColors()->stimPlanResultColorType() == RimStimPlanColors::SINGLE_ELEMENT_COLOR)
        {
            auto part = createStimPlanElementColorSurfacePart(eclView);
            if (part.notNull()) parts.push_back(part.p());
        }
        else
        {
            auto part = createStimPlanColorInterpolatedSurfacePart(eclView);
            if (part.notNull()) parts.push_back(part.p());
        }

        if (eclView.fractureColors()->showStimPlanMesh())
        {
            auto part = createStimPlanMeshPart(eclView);
            if (part.notNull()) parts.push_back(part.p());
        }
    }
    else
    {
        auto part = createEllipseSurfacePart(eclView);
        if (part.notNull()) parts.push_back(part.p());
    }

    double distanceToCenterLine = 1.0;
    {
        RimWellPathCollection* wellPathColl = nullptr;
        m_rimFracture->firstAncestorOrThisOfType(wellPathColl);
        if (wellPathColl)
        {
            distanceToCenterLine = wellPathColl->wellPathRadiusScaleFactor() * characteristicCellSize;
        }

        RimSimWellInView* simWell = nullptr;
        m_rimFracture->firstAncestorOrThisOfType(simWell);
        if (simWell)
        {
            distanceToCenterLine = simWell->pipeRadius();
        }
    }

    // Make sure the distance is slightly smaller than the pipe radius to make the pipe is visible through the fracture
    distanceToCenterLine *= 0.1;

    if (distanceToCenterLine < 0.03)
    {
        distanceToCenterLine = 0.03;
    }

    auto fractureMatrix = m_rimFracture->transformMatrix();

    if (m_rimFracture->fractureTemplate() &&
        m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH)
    {
        cvf::Vec3d partTranslation = distanceToCenterLine * cvf::Vec3d(fractureMatrix.col(2));

        for (auto& part : parts)
        {
            RivWellFracturePartMgr::addPartAtPositiveAndNegativeTranslation(model, part.p(), partTranslation);
        }
    }
    else
    {
        for (auto& part : parts)
        {
            model->addPart(part.p());
        }
    }

    if (m_rimFracture->fractureTemplate())
    {
        // Position the containment mask outside the fracture parts
        // Always duplicate the containment mask parts

        {
            auto maskOfFractureAreasOutsideGrid = createMaskOfFractureOutsideGrid(eclView);
            if (maskOfFractureAreasOutsideGrid.notNull())
            {
                double scaleFactor = 0.03;
                if (m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH)
                {
                    scaleFactor = 2 * distanceToCenterLine;
                }

                cvf::Vec3d partTranslation = scaleFactor * cvf::Vec3d(fractureMatrix.col(2));

                RivWellFracturePartMgr::addPartAtPositiveAndNegativeTranslation(
                    model, maskOfFractureAreasOutsideGrid.p(), partTranslation);
            }
        }

        if (m_rimFracture->fractureTemplate()->fractureContainment()->isEnabled())
        {
            // Position the containment mask outside the fracture parts
            // Always duplicate the containment mask parts

            auto containmentMask = createContainmentMaskPart(eclView);
            if (containmentMask.notNull())
            {
                double scaleFactor = 0.03;
                if (m_rimFracture->fractureTemplate() &&
                    m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH)
                {
                    scaleFactor = 2 * distanceToCenterLine;
                }

                cvf::Vec3d partTranslation = scaleFactor * cvf::Vec3d(fractureMatrix.col(2));

                RivWellFracturePartMgr::addPartAtPositiveAndNegativeTranslation(model, containmentMask.p(), partTranslation);
            }
        }
    }

    appendFracturePerforationLengthParts(eclView, model);
}
//--------------------------------------------------------------------------------------------------
/// Create mask for the parts outside the grid cells of the reservoir
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivWellFracturePartMgr::createMaskOfFractureOutsideGrid(const RimEclipseView& activeView)
{
    cvf::Mat4d frMx = m_rimFracture->transformMatrix();

    std::vector<cvf::Vec3f> maskTriangles;

    auto displCoordTrans = activeView.displayCoordTransform();

    for (const auto& visibleFracturePolygon : m_visibleFracturePolygons)
    {
        std::vector<cvf::Vec3d> borderOfFractureCellPolygonLocalCsd;
        cvf::BoundingBox        frBBox;

        for (const auto& pv : visibleFracturePolygon)
        {
            cvf::Vec3d pvd(pv);
            borderOfFractureCellPolygonLocalCsd.push_back(pvd);
            pvd.transformPoint(frMx);
            frBBox.add(pvd);
        }

        std::vector<std::vector<cvf::Vec3d>> clippedPolygons;

        std::vector<size_t> cellCandidates;
        activeView.mainGrid()->findIntersectingCells(frBBox, &cellCandidates);
        if (cellCandidates.empty())
        {
            clippedPolygons.push_back(borderOfFractureCellPolygonLocalCsd);
        }
        else
        {
            // Check if fracture polygon is fully inside the grid

            bool allPointsInsideGrid = true;
            for (const auto& v : borderOfFractureCellPolygonLocalCsd)
            {
                auto         pointInDomainCoords = v.getTransformedPoint(frMx);
                bool         pointInsideGrid     = false;
                RigMainGrid* mainGrid            = activeView.mainGrid();

                std::array<cvf::Vec3d, 8> corners;
                for (size_t cellIndex : cellCandidates)
                {
                    mainGrid->cellCornerVertices(cellIndex, corners.data());

                    if (RigHexIntersectionTools::isPointInCell(pointInDomainCoords, corners.data()))
                    {
                        pointInsideGrid = true;
                        break;
                    }
                }

                if (!pointInsideGrid)
                {
                    allPointsInsideGrid = false;
                    break;
                }
            }

            if (!allPointsInsideGrid)
            {
                std::vector<std::vector<cvf::Vec3d>> allEclCellPolygons;
                for (size_t resCellIdx : cellCandidates)
                {
                    // Calculate Eclipse cell intersection with fracture plane

                    std::array<cvf::Vec3d, 8> corners;
                    activeView.mainGrid()->cellCornerVertices(resCellIdx, corners.data());

                    std::vector<std::vector<cvf::Vec3d>> eclCellPolygons;
                    bool hasIntersection = RigHexIntersectionTools::planeHexIntersectionPolygons(corners, frMx, eclCellPolygons);

                    if (!hasIntersection || eclCellPolygons.empty()) continue;

                    // Transform eclCell - plane intersection onto fracture

                    cvf::Mat4d invertedTransformMatrix = frMx.getInverted();
                    for (std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons)
                    {
                        for (cvf::Vec3d& v : eclCellPolygon)
                        {
                            v.transformPoint(invertedTransformMatrix);
                        }

                        allEclCellPolygons.push_back(eclCellPolygon);
                    }
                }

                {
                    std::vector<std::vector<cvf::Vec3d>> polys =
                        RigCellGeometryTools::subtractPolygons(borderOfFractureCellPolygonLocalCsd, allEclCellPolygons);

                    for (const auto& polygon : polys)
                    {
                        clippedPolygons.push_back(polygon);
                    }
                }
            }
        }

        for (auto& clippedPolygon : clippedPolygons)
        {
            for (auto& point : clippedPolygon)
            {
                point.transformPoint(frMx);
            }
        }

        // Create triangles from the clipped polygons
        cvf::Vec3d fractureNormal = cvf::Vec3d(frMx.col(2));

        for (const auto& clippedPolygon : clippedPolygons)
        {
            cvf::EarClipTesselator tess;
            tess.setNormal(fractureNormal);
            cvf::Vec3dArray cvfNodes(clippedPolygon);
            tess.setGlobalNodeArray(cvfNodes);
            std::vector<size_t> polyIndexes;
            for (size_t idx = 0; idx < clippedPolygon.size(); ++idx)
                polyIndexes.push_back(idx);
            tess.setPolygonIndices(polyIndexes);

            std::vector<size_t> triangleIndices;
            tess.calculateTriangles(&triangleIndices);

            for (size_t idx : triangleIndices)
            {
                maskTriangles.push_back(cvf::Vec3f(displCoordTrans->transformToDisplayCoord(clippedPolygon[idx])));
            }
        }
    }

    if (maskTriangles.size() >= 3)
    {
        cvf::ref<cvf::DrawableGeo> maskTriangleGeo = new cvf::DrawableGeo;
        maskTriangleGeo->setVertexArray(new cvf::Vec3fArray(maskTriangles));

        cvf::ref<cvf::PrimitiveSetDirect> primitives = new cvf::PrimitiveSetDirect(cvf::PT_TRIANGLES);
        primitives->setIndexCount(maskTriangles.size());
        maskTriangleGeo->addPrimitiveSet(primitives.p());
        maskTriangleGeo->computeNormals();

        cvf::ref<cvf::Part> containmentMaskPart = new cvf::Part(0, "FractureContainmentMaskPart");
        containmentMaskPart->setDrawable(maskTriangleGeo.p());
        containmentMaskPart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture));

        cvf::Color4f maskColor = cvf::Color4f(cvf::Color3f(cvf::Color3::GRAY));

        caf::SurfaceEffectGenerator surfaceGen(maskColor, caf::PO_NONE);
        cvf::ref<cvf::Effect>       eff = surfaceGen.generateCachedEffect();
        containmentMaskPart->setEffect(eff.p());

        return containmentMaskPart;
    }

    return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivWellFracturePartMgr::createContainmentMaskPart(const RimEclipseView& activeView)
{
    std::vector<cvf::Vec3d> borderPolygonLocalCS = fractureBorderPolygon();
    cvf::Mat4d              frMx                 = m_rimFracture->transformMatrix();

    cvf::BoundingBox        frBBox;
    std::vector<cvf::Vec3d> borderPolygonLocalCsd;
    for (const auto& pv : borderPolygonLocalCS)
    {
        cvf::Vec3d pvd(pv);
        borderPolygonLocalCsd.push_back(pvd);
        pvd.transformPoint(frMx);
        frBBox.add(pvd);
    }

    std::vector<size_t> cellCandidates;
    activeView.mainGrid()->findIntersectingCells(frBBox, &cellCandidates);

    auto displCoordTrans = activeView.displayCoordTransform();

    std::vector<cvf::Vec3f> maskTriangles;

    RimEclipseCase* eclipseCase = nullptr;
    activeView.firstAncestorOrThisOfType(eclipseCase);
    auto reservoirCellIndicesOpenForFlow = RimFractureContainmentTools::reservoirCellIndicesOpenForFlow(eclipseCase, m_rimFracture);

    for (size_t resCellIdx : cellCandidates)
    {
        if (!m_rimFracture->isEclipseCellOpenForFlow(activeView.mainGrid(), reservoirCellIndicesOpenForFlow, resCellIdx))
        {
            // Calculate Eclipse cell intersection with fracture plane

            std::array<cvf::Vec3d, 8> corners;
            activeView.mainGrid()->cellCornerVertices(resCellIdx, corners.data());

            std::vector<std::vector<cvf::Vec3d>> eclCellPolygons;
            bool hasIntersection = RigHexIntersectionTools::planeHexIntersectionPolygons(corners, frMx, eclCellPolygons);

            if (!hasIntersection || eclCellPolygons.empty()) continue;

            // Transform eclCell - plane intersection onto fracture

            cvf::Mat4d invertedTransformMatrix = frMx.getInverted();
            for (std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons)
            {
                for (cvf::Vec3d& v : eclCellPolygon)
                {
                    v.transformPoint(invertedTransformMatrix);
                }
            }

            cvf::Vec3d fractureNormal = cvf::Vec3d(frMx.col(2));
            for (const std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons)
            {
                // Clip Eclipse cell polygon with fracture border

                std::vector<std::vector<cvf::Vec3d>> clippedPolygons =
                    RigCellGeometryTools::intersectPolygons(eclCellPolygon, borderPolygonLocalCsd);
                for (auto& clippedPolygon : clippedPolygons)
                {
                    for (auto& v : clippedPolygon)
                    {
                        v.transformPoint(frMx);
                    }
                }

                // Create triangles from the clipped polygons

                for (auto& clippedPolygon : clippedPolygons)
                {
                    cvf::EarClipTesselator tess;
                    tess.setNormal(fractureNormal);
                    cvf::Vec3dArray cvfNodes(clippedPolygon);
                    tess.setGlobalNodeArray(cvfNodes);
                    std::vector<size_t> polyIndexes;
                    for (size_t idx = 0; idx < clippedPolygon.size(); ++idx)
                        polyIndexes.push_back(idx);
                    tess.setPolygonIndices(polyIndexes);

                    std::vector<size_t> triangleIndices;
                    tess.calculateTriangles(&triangleIndices);

                    for (size_t idx : triangleIndices)
                    {
                        maskTriangles.push_back(cvf::Vec3f(displCoordTrans->transformToDisplayCoord(clippedPolygon[idx])));
                    }
                }
            }
        }
    }

    if (maskTriangles.size() >= 3)
    {
        cvf::ref<cvf::DrawableGeo> maskTriangleGeo = new cvf::DrawableGeo;
        maskTriangleGeo->setVertexArray(new cvf::Vec3fArray(maskTriangles));

        cvf::ref<cvf::PrimitiveSetDirect> primitives = new cvf::PrimitiveSetDirect(cvf::PT_TRIANGLES);
        primitives->setIndexCount(maskTriangles.size());
        maskTriangleGeo->addPrimitiveSet(primitives.p());
        maskTriangleGeo->computeNormals();

        cvf::ref<cvf::Part> containmentMaskPart = new cvf::Part(0, "FractureContainmentMaskPart");
        containmentMaskPart->setDrawable(maskTriangleGeo.p());
        containmentMaskPart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture));

        cvf::Color4f maskColor = cvf::Color4f(cvf::Color3f(cvf::Color3::GRAY));

        caf::SurfaceEffectGenerator surfaceGen(maskColor, caf::PO_NONE);
        cvf::ref<cvf::Effect>       eff = surfaceGen.generateCachedEffect();
        containmentMaskPart->setEffect(eff.p());

        return containmentMaskPart;
    }

    return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivWellFracturePartMgr::createStimPlanElementColorSurfacePart(const RimEclipseView& activeView)
{
    CVF_ASSERT(m_rimFracture);
    RimStimPlanFractureTemplate* stimPlanFracTemplate =
        dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate());
    CVF_ASSERT(stimPlanFracTemplate);

    if (!stimPlanFracTemplate->fractureGrid()) return nullptr;

    auto displayCoordTransform = activeView.displayCoordTransform();
    if (displayCoordTransform.isNull()) return nullptr;

    std::vector<cvf::Vec3f>   stimPlanMeshVertices;
    cvf::ref<cvf::Vec2fArray> textureCoords = new cvf::Vec2fArray;
    const cvf::ScalarMapper*  scalarMapper  = nullptr;

    {
        std::vector<RigFractureCell> stimPlanCells = stimPlanFracTemplate->fractureGrid()->fractureCells();

        RimRegularLegendConfig* legendConfig = nullptr;
        if (activeView.fractureColors() && activeView.fractureColors()->isChecked() &&
            activeView.fractureColors()->activeLegend())
        {
            legendConfig = activeView.fractureColors()->activeLegend();

            scalarMapper = legendConfig->scalarMapper();

            QString resultNameFromColors = activeView.fractureColors()->uiResultName();
            QString resultUnitFromColors = activeView.fractureColors()->unit();

            std::vector<double> prCellResults = stimPlanFracTemplate->fractureGridResults(
                resultNameFromColors, resultUnitFromColors, stimPlanFracTemplate->activeTimeStepIndex());

            textureCoords->reserve(prCellResults.size() * 4);

            for (size_t cIdx = 0; cIdx < stimPlanCells.size(); ++cIdx)
            {
                if (prCellResults[cIdx] > 1e-7)
                {
                    const RigFractureCell&  stimPlanCell        = stimPlanCells[cIdx];
                    std::vector<cvf::Vec3d> stimPlanCellPolygon = stimPlanCell.getPolygon();
                    for (const cvf::Vec3d& cellCorner : stimPlanCellPolygon)
                    {
                        stimPlanMeshVertices.push_back(static_cast<cvf::Vec3f>(cellCorner));
                        textureCoords->add(scalarMapper->mapToTextureCoord(prCellResults[cIdx]));
                    }
                }
            }

            textureCoords->squeeze();
        }
        else
        {
            for (const auto& stimPlanCell : stimPlanCells)
            {
                for (const auto& cellCorner : stimPlanCell.getPolygon())
                {
                    stimPlanMeshVertices.push_back(static_cast<cvf::Vec3f>(cellCorner));
                }
            }
        }
    }

    if (stimPlanMeshVertices.empty())
    {
        return nullptr;
    }

    cvf::Mat4d              fractureXf = m_rimFracture->transformMatrix();
    std::vector<cvf::Vec3f> nodeDisplayCoords =
        transformToFractureDisplayCoords(stimPlanMeshVertices, fractureXf, *displayCoordTransform);

    std::vector<cvf::uint> triIndicesToInclude;

    size_t cellCount = stimPlanMeshVertices.size() / 4;
    for (cvf::uint i = 0; i < cellCount; i++)
    {
        triIndicesToInclude.push_back(i * 4 + 0);
        triIndicesToInclude.push_back(i * 4 + 1);
        triIndicesToInclude.push_back(i * 4 + 2);

        triIndicesToInclude.push_back(i * 4 + 0);
        triIndicesToInclude.push_back(i * 4 + 2);
        triIndicesToInclude.push_back(i * 4 + 3);
    }

    // Show selected result on the surface geometry and filter out triangles that have result values near 0
    if (scalarMapper)
    {
        if (triIndicesToInclude.empty())
        {
            return nullptr;
        }

        cvf::ref<cvf::DrawableGeo> geo = buildDrawableGeoFromTriangles(triIndicesToInclude, nodeDisplayCoords);
        geo->setTextureCoordArray(textureCoords.p());

        cvf::ref<cvf::Part> surfacePart =
            createScalarMapperPart(geo.p(), scalarMapper, m_rimFracture, activeView.isLightingDisabled());

        return surfacePart;
    }
    else
    {
        // No result is mapped, show the entire StimPlan surface with default color

        return createSingleColorSurfacePart(triIndicesToInclude, nodeDisplayCoords, activeView.fractureColors()->defaultColor());
    }
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivWellFracturePartMgr::createStimPlanColorInterpolatedSurfacePart(const RimEclipseView& activeView)
{
    CVF_ASSERT(m_rimFracture);
    RimStimPlanFractureTemplate* stimPlanFracTemplate =
        dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate());
    CVF_ASSERT(stimPlanFracTemplate);

    auto displayCoordTransform = activeView.displayCoordTransform();
    if (displayCoordTransform.isNull()) return nullptr;

    // Note that the filtering and result mapping code below couples closely to the triangulation and vertex layout returned by
    // triangleGeometry() If this ever changes, the entire code must be revisited
    std::vector<cvf::uint>  triangleIndices;
    std::vector<cvf::Vec3f> nodeDisplayCoords;
    {
        std::vector<cvf::Vec3f> nodeCoords;
        stimPlanFracTemplate->fractureTriangleGeometry(&nodeCoords, &triangleIndices);

        if (triangleIndices.empty() || nodeCoords.empty())
        {
            return nullptr;
        }

        cvf::Mat4d fractureXf = m_rimFracture->transformMatrix();
        nodeDisplayCoords     = transformToFractureDisplayCoords(nodeCoords, fractureXf, *displayCoordTransform);
    }

    RimRegularLegendConfig* legendConfig = nullptr;
    if (activeView.fractureColors() && activeView.fractureColors()->isChecked())
    {
        legendConfig = activeView.fractureColors()->activeLegend();
    }

    // Show selected result on the surface geometry and filter out triangles that have result values near 0
    if (legendConfig)
    {
        // Construct array with per node result values that correspond to the node coordinates of the triangle mesh
        // Since some time steps don't have result vales, we initialize the array to well known values before populating it
        std::vector<double> perNodeResultValues(nodeDisplayCoords.size(), HUGE_VAL);
        {
            size_t idx = 0;

            const std::vector<std::vector<double>> dataToPlot =
                stimPlanFracTemplate->resultValues(activeView.fractureColors()->uiResultName(),
                                                   activeView.fractureColors()->unit(),
                                                   stimPlanFracTemplate->activeTimeStepIndex());
            for (const std::vector<double>& dataAtY : dataToPlot)
            {
                for (double val : dataAtY)
                {
                    perNodeResultValues[idx++] = val;
                }
            }
        }
        CVF_ASSERT(perNodeResultValues.size() == nodeDisplayCoords.size());

        std::vector<cvf::uint> triIndicesToInclude;
        for (size_t i = 0; i < triangleIndices.size(); i += 6)
        {
            // Include all triangles where at least one of the vertices in the triangle pair has a value above threshold
            bool includeThisTrianglePair = false;
            for (size_t j = 0; j < 6; j++)
            {
                if (perNodeResultValues[triangleIndices[i + j]] > 1e-7)
                {
                    includeThisTrianglePair = true;
                }
            }

            if (includeThisTrianglePair)
            {
                for (size_t j = 0; j < 6; j++)
                {
                    triIndicesToInclude.push_back(triangleIndices[i + j]);
                }
            }
        }

        if (triIndicesToInclude.empty())
        {
            return nullptr;
        }

        cvf::ref<cvf::DrawableGeo> geo          = buildDrawableGeoFromTriangles(triIndicesToInclude, nodeDisplayCoords);
        const cvf::ScalarMapper*   scalarMapper = legendConfig->scalarMapper();
        CVF_ASSERT(scalarMapper);

        cvf::ref<cvf::Vec2fArray> textureCoords = new cvf::Vec2fArray(nodeDisplayCoords.size());
        textureCoords->setAll(cvf::Vec2f(0.5f, 1.0f));
        for (size_t i = 0; i < perNodeResultValues.size(); i++)
        {
            const double val = perNodeResultValues[i];
            if (val < HUGE_VAL && val == val)
            {
                textureCoords->set(i, scalarMapper->mapToTextureCoord(val));
            }
        }
        geo->setTextureCoordArray(textureCoords.p());

        cvf::ref<cvf::Part> surfacePart =
            createScalarMapperPart(geo.p(), scalarMapper, m_rimFracture, activeView.isLightingDisabled());

        return surfacePart;
    }
    else
    {
        // No result is mapped, show the entire StimPlan surface with default color

        return createSingleColorSurfacePart(triangleIndices, nodeDisplayCoords, activeView.fractureColors()->defaultColor());
    }
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivWellFracturePartMgr::createEllipseSurfacePart(const RimEclipseView& activeView)
{
    auto displayCoordTransform = activeView.displayCoordTransform();
    if (displayCoordTransform.isNull()) return nullptr;

    if (m_rimFracture)
    {
        std::vector<cvf::uint>  triangleIndices;
        std::vector<cvf::Vec3f> nodeDisplayCoords;

        {
            std::vector<cvf::Vec3f> nodeCoords;
            m_rimFracture->fractureTemplate()->fractureTriangleGeometry(&nodeCoords, &triangleIndices);

            cvf::Mat4d fractureXf = m_rimFracture->transformMatrix();
            nodeDisplayCoords     = transformToFractureDisplayCoords(nodeCoords, fractureXf, *displayCoordTransform);
        }

        if (triangleIndices.empty() || nodeDisplayCoords.empty())
        {
            return nullptr;
        }

        cvf::ref<cvf::DrawableGeo> geo = buildDrawableGeoFromTriangles(triangleIndices, nodeDisplayCoords);
        CVF_ASSERT(geo.notNull());

        cvf::ref<cvf::Part> surfacePart = new cvf::Part(0, "FractureSurfacePart_ellipse");
        surfacePart->setDrawable(geo.p());
        surfacePart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture));

        cvf::Color4f fractureColor = cvf::Color4f(activeView.fractureColors()->defaultColor());

        RimRegularLegendConfig* legendConfig = nullptr;
        if (activeView.fractureColors() && activeView.fractureColors()->isChecked())
        {
            legendConfig = activeView.fractureColors()->activeLegend();
        }

        if (legendConfig && legendConfig->scalarMapper())
        {
            cvf::Color3ub resultColor = cvf::Color3ub(RiaColorTables::undefinedCellColor());

            if (activeView.fractureColors()->uiResultName() == RiaDefines::conductivityResultName())
            {
                RimEllipseFractureTemplate* ellipseFractureTemplate =
                    dynamic_cast<RimEllipseFractureTemplate*>(m_rimFracture->fractureTemplate());
                if (ellipseFractureTemplate)
                {
                    double conductivity = ellipseFractureTemplate->conductivity();
                    resultColor         = legendConfig->scalarMapper()->mapToColor(conductivity);
                }
            }

            fractureColor.set(cvf::Color3f::fromByteColor(resultColor.r(), resultColor.g(), resultColor.b()));
        }

        caf::SurfaceEffectGenerator surfaceGen(fractureColor, caf::PO_1);
        cvf::ref<cvf::Effect>       eff = surfaceGen.generateCachedEffect();
        surfacePart->setEffect(eff.p());

        return surfacePart;
    }

    return nullptr;
}
Beispiel #30
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimEclipseCellColors* cellResultColors)
{
    CVF_ASSERT(cellResultColors);

    updateNNCColors(cellResultColors);

    RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultColors->porosityModel());
    RimEclipseView* eclipseView = cellResultColors->reservoirView();
    RigCaseData* eclipseCase = eclipseView->eclipseCase()->reservoirData();

    // Faults
    if (m_nativeFaultFaces.notNull())
    {
        if (cellResultColors->isTernarySaturationSelected())
        {
            RivTernaryTextureCoordsCreator texturer(cellResultColors, cellResultColors->ternaryLegendConfig(),
                timeStepIndex,
                m_grid->gridIndex(),
                m_nativeFaultGenerator->quadToCellFaceMapper());

            texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p());

            const RivTernaryScalarMapper* mapper = cellResultColors->ternaryLegendConfig()->scalarMapper();
            RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode(), eclipseView->isLightingDisabled());
        }
        else
        {
            RivTextureCoordsCreator texturer(cellResultColors, 
                timeStepIndex, 
                m_grid->gridIndex(),  
                m_nativeFaultGenerator->quadToCellFaceMapper());

            if (!texturer.isValid())
            {
                return;
            }

            texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p());

            const cvf::ScalarMapper* mapper = cellResultColors->legendConfig()->scalarMapper();
            RivScalarMapperUtils::applyTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode(), eclipseView->isLightingDisabled());
        }
    }

    if (m_oppositeFaultFaces.notNull())
    {
        if (cellResultColors->isTernarySaturationSelected())
        {
            RivTernaryTextureCoordsCreator texturer(cellResultColors, cellResultColors->ternaryLegendConfig(),
                timeStepIndex,
                m_grid->gridIndex(),
                m_oppositeFaultGenerator->quadToCellFaceMapper());

            texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p());

            const RivTernaryScalarMapper* mapper = cellResultColors->ternaryLegendConfig()->scalarMapper();
            RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode(), eclipseView->isLightingDisabled());
        }
        else
        {
            RivTextureCoordsCreator texturer(cellResultColors,
                timeStepIndex,
                m_grid->gridIndex(),
                m_oppositeFaultGenerator->quadToCellFaceMapper());

            if (!texturer.isValid())
            {
                return;
            }

            texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p());

            const cvf::ScalarMapper* mapper = cellResultColors->legendConfig()->scalarMapper();
            RivScalarMapperUtils::applyTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode(), eclipseView->isLightingDisabled());
        }
    }
}