///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2015- Statoil ASA // Copyright (C) 2015- Ceetron Solutions 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 // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RiuViewerCommands.h" #include "RiaApplication.h" #include "RiaColorTables.h" #include "RiaDefines.h" #include "RicEclipsePropertyFilterNewExec.h" #include "RicGeoMechPropertyFilterNewExec.h" #include "RicPickEventHandler.h" #include "RicContourMapPickEventHandler.h" #include "WellLogCommands/Ric3dWellLogCurvePickEventHandler.h" #include "WellPathCommands/RicIntersectionPickEventHandler.h" #include "WellPathCommands/RicWellPathPickEventHandler.h" #include "RigEclipseCaseData.h" #include "RigFault.h" #include "RigFemPartCollection.h" #include "RigFemPartGrid.h" #include "RigGeoMechCaseData.h" #include "RigMainGrid.h" #include "RigVirtualPerforationTransmissibilities.h" #include "Rim2dIntersectionView.h" #include "RimCellEdgeColors.h" #include "RimContextCommandBuilder.h" #include "RimEclipseCase.h" #include "RimEclipseCellColors.h" #include "RimEclipseFaultColors.h" #include "RimEclipseView.h" #include "RimEllipseFractureTemplate.h" #include "RimFaultInView.h" #include "RimFaultInViewCollection.h" #include "RimFracture.h" #include "RimGeoMechCase.h" #include "RimGeoMechCellColors.h" #include "RimGeoMechView.h" #include "RimIntersection.h" #include "RimIntersectionBox.h" #include "RimLegendConfig.h" #include "RimPerforationInterval.h" #include "RimSimWellInView.h" #include "RimStimPlanFractureTemplate.h" #include "RimViewController.h" #include "RimWellPath.h" #include "RiuMainWindow.h" #include "RiuResultTextBuilder.h" #include "RiuSelectionManager.h" #include "RiuViewer.h" #include "RiuPickItemInfo.h" #include "RivFemPartGeometryGenerator.h" #include "RivFemPickSourceInfo.h" #include "RivIntersectionBoxSourceInfo.h" #include "RivIntersectionSourceInfo.h" #include "RivObjectSourceInfo.h" #include "RivSimWellConnectionSourceInfo.h" #include "RivSimWellPipeSourceInfo.h" #include "RivSourceInfo.h" #include "RivTernarySaturationOverlayItem.h" #include "RivWellConnectionSourceInfo.h" #include "RivWellFracturePartMgr.h" #include "RivWellPathSourceInfo.h" #include "cafCmdExecCommandManager.h" #include "cafCmdFeatureManager.h" #include "cafCmdFeatureMenuBuilder.h" #include "cafDisplayCoordTransform.h" #include "cafPdmUiTreeView.h" #include "cafSelectionManager.h" #include "cafOverlayScalarMapperLegend.h" #include "cvfDrawableGeo.h" #include "cvfHitItemCollection.h" #include "cvfOverlayAxisCross.h" #include "cvfPart.h" #include "cvfTransform.h" #include #include #include #include //================================================================================================== // // RiaViewerCommands // //================================================================================================== RicPickEventHandler* RiuViewerCommands::sm_overridingPickHandler = nullptr; std::vector RiuViewerCommands::sm_defaultPickEventHandlers; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuViewerCommands::RiuViewerCommands(RiuViewer* ownerViewer) : QObject(ownerViewer) , m_currentGridIdx(-1) , m_currentCellIndex(-1) , m_currentFaceIndex(cvf::StructGridInterface::NO_FACE) , m_currentPickPositionInDomainCoords(cvf::Vec3d::UNDEFINED) , m_viewer(ownerViewer) { if ( sm_defaultPickEventHandlers.empty() ) { addDefaultPickEventHandler(RicIntersectionPickEventHandler::instance()); addDefaultPickEventHandler(Ric3dWellLogCurvePickEventHandler::instance()); addDefaultPickEventHandler(RicWellPathPickEventHandler::instance()); addDefaultPickEventHandler(RicContourMapPickEventHandler::instance()); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuViewerCommands::~RiuViewerCommands() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::setOwnerView(Rim3dView * owner) { m_reservoirView = owner; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::displayContextMenu(QMouseEvent* event) { // Do the ray pick, and extract the infos std::vector pickItemInfos; { cvf::HitItemCollection hitItems; if (m_viewer->rayPick( event->x(), event->y(), &hitItems)) { pickItemInfos = RiuPickItemInfo::convertToPickItemInfos(hitItems); } } // Find the following data const cvf::Part* firstHitPart = nullptr; uint firstPartTriangleIndex = cvf::UNDEFINED_UINT; m_currentPickPositionInDomainCoords = cvf::Vec3d::UNDEFINED; if (pickItemInfos.size()) { cvf::Vec3d globalIntersectionPoint(cvf::Vec3d::ZERO); if ( pickItemInfos.size() ) { globalIntersectionPoint = pickItemInfos[0].globalPickedPoint(); } for (const auto& pickItem : pickItemInfos) { const RivObjectSourceInfo* objectSourceInfo = dynamic_cast(pickItem.sourceInfo()); if ( objectSourceInfo && dynamic_cast(objectSourceInfo->object()) ) { // Skip picking on perforation interval, display well path context menu continue; } const RivSourceInfo* rivSourceInfo = dynamic_cast(pickItem.sourceInfo()); if ( rivSourceInfo && rivSourceInfo->hasNNCIndices()) { // Skip picking on nnc-s continue; } firstHitPart = pickItem.pickedPart(); firstPartTriangleIndex = pickItem.faceIdx(); globalIntersectionPoint = pickItem.globalPickedPoint(); break; } cvf::Vec3d displayModelOffset = cvf::Vec3d::ZERO; if (m_reservoirView.p()) { cvf::ref transForm = m_reservoirView.p()->displayCoordTransform(); m_currentPickPositionInDomainCoords = transForm->transformToDomainCoord(globalIntersectionPoint); } } // Build menue QMenu menu; caf::CmdFeatureMenuBuilder menuBuilder; m_currentGridIdx = cvf::UNDEFINED_SIZE_T; m_currentCellIndex = cvf::UNDEFINED_SIZE_T; // Check type of view RimGridView* gridView = dynamic_cast(m_reservoirView.p()); Rim2dIntersectionView* int2dView = dynamic_cast(m_reservoirView.p()); if (firstHitPart && firstPartTriangleIndex != cvf::UNDEFINED_UINT) { const RivSourceInfo* rivSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivFemPickSourceInfo* femSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivIntersectionSourceInfo* crossSectionSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivIntersectionBoxSourceInfo* intersectionBoxSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); if (rivSourceInfo || femSourceInfo || crossSectionSourceInfo || intersectionBoxSourceInfo) { if (rivSourceInfo) { if (!rivSourceInfo->hasCellFaceMapping()) return; // Set the data regarding what was hit m_currentGridIdx = rivSourceInfo->gridIndex(); m_currentCellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(firstPartTriangleIndex); m_currentFaceIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellFace(firstPartTriangleIndex); } else if (femSourceInfo) { m_currentGridIdx = femSourceInfo->femPartIndex(); m_currentCellIndex = femSourceInfo->triangleToElmMapper()->elementIndex(firstPartTriangleIndex); } else if (crossSectionSourceInfo) { findCellAndGridIndex(crossSectionSourceInfo, firstPartTriangleIndex, &m_currentCellIndex, &m_currentGridIdx); m_currentFaceIndex = cvf::StructGridInterface::NO_FACE; RiuSelectionItem* selItem = new RiuGeneralSelectionItem(crossSectionSourceInfo->crossSection()); RiuSelectionManager::instance()->setSelectedItem(selItem, RiuSelectionManager::RUI_TEMPORARY); if (gridView) { menuBuilder << "RicHideIntersectionFeature"; menuBuilder.addSeparator(); menuBuilder << "RicNewIntersectionViewFeature"; menuBuilder.addSeparator(); } else if (int2dView) { menuBuilder << "RicSelectColorResult"; } } else if (intersectionBoxSourceInfo) { findCellAndGridIndex(intersectionBoxSourceInfo, firstPartTriangleIndex, &m_currentCellIndex, &m_currentGridIdx); m_currentFaceIndex = cvf::StructGridInterface::NO_FACE; RiuSelectionItem* selItem = new RiuGeneralSelectionItem(intersectionBoxSourceInfo->intersectionBox()); RiuSelectionManager::instance()->setSelectedItem(selItem, RiuSelectionManager::RUI_TEMPORARY); menuBuilder << "RicHideIntersectionBoxFeature"; menuBuilder.addSeparator(); } if (gridView) { // IJK -slice commands RimViewController* viewController = nullptr; if (m_reservoirView) viewController = m_reservoirView->viewController(); if (!viewController || !viewController->isRangeFiltersControlled()) { size_t i, j, k; ijkFromCellIndex(m_currentGridIdx, m_currentCellIndex, &i, &j, &k); QVariantList iSliceList; iSliceList.push_back(0); iSliceList.push_back(CVF_MAX(static_cast(i + 1), 1)); iSliceList.push_back(static_cast(m_currentGridIdx)); QVariantList jSliceList; jSliceList.push_back(1); jSliceList.push_back(CVF_MAX(static_cast(j + 1), 1)); jSliceList.push_back(static_cast(m_currentGridIdx)); QVariantList kSliceList; kSliceList.push_back(2); kSliceList.push_back(CVF_MAX(static_cast(k + 1), 1)); kSliceList.push_back(static_cast(m_currentGridIdx)); menuBuilder.subMenuStart("Range Filter Slice", QIcon(":/CellFilter_Range.png")); menuBuilder.addCmdFeatureWithUserData("RicNewSliceRangeFilterFeature", "I-slice Range Filter", iSliceList); menuBuilder.addCmdFeatureWithUserData("RicNewSliceRangeFilterFeature", "J-slice Range Filter", jSliceList); menuBuilder.addCmdFeatureWithUserData("RicNewSliceRangeFilterFeature", "K-slice Range Filter", kSliceList); menuBuilder.subMenuEnd(); } menuBuilder << "RicEclipsePropertyFilterNewInViewFeature"; menuBuilder << "RicGeoMechPropertyFilterNewInViewFeature"; menuBuilder.addSeparator(); menuBuilder.subMenuStart("Intersections", QIcon(":/IntersectionXPlane16x16.png")); menuBuilder << "RicNewPolylineIntersectionFeature"; menuBuilder << "RicNewAzimuthDipIntersectionFeature"; menuBuilder << "RicIntersectionBoxAtPosFeature"; menuBuilder << "RicIntersectionBoxXSliceFeature"; menuBuilder << "RicIntersectionBoxYSliceFeature"; menuBuilder << "RicIntersectionBoxZSliceFeature"; } menuBuilder.subMenuEnd(); menuBuilder.addSeparator(); RimEclipseView* eclipseView = dynamic_cast(m_reservoirView.p()); if (eclipseView) { // Hide faults command const RigFault* fault = eclipseView->mainGrid()->findFaultFromCellIndexAndCellFace(m_currentCellIndex, m_currentFaceIndex); if (fault) { menuBuilder.addSeparator(); QString faultName = fault->name(); QVariantList hideFaultList; qulonglong currentCellIndex = m_currentCellIndex; hideFaultList.push_back(currentCellIndex); hideFaultList.push_back(m_currentFaceIndex); menuBuilder.addCmdFeatureWithUserData("RicEclipseHideFaultFeature", QString("Hide ") + faultName, hideFaultList); } } } } // Well log curve creation commands if (firstHitPart && firstHitPart->sourceInfo()) { const RivWellPathSourceInfo* wellPathSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); if (wellPathSourceInfo) { RimWellPath* wellPath = wellPathSourceInfo->wellPath(); if (wellPath) { if (firstPartTriangleIndex != cvf::UNDEFINED_UINT) { cvf::Vec3d pickedPositionInUTM = m_currentPickPositionInDomainCoords; if (int2dView) pickedPositionInUTM = int2dView->transformToUtm(pickedPositionInUTM); double measuredDepth = wellPathSourceInfo->measuredDepth(firstPartTriangleIndex, pickedPositionInUTM); cvf::Vec3d closestPointOnCenterLine = wellPathSourceInfo->closestPointOnCenterLine(firstPartTriangleIndex, pickedPositionInUTM); RiuSelectionItem* selItem = new RiuWellPathSelectionItem(wellPathSourceInfo, closestPointOnCenterLine, measuredDepth); RiuSelectionManager::instance()->setSelectedItem(selItem, RiuSelectionManager::RUI_TEMPORARY); } //TODO: Update so these also use RiuWellPathSelectionItem caf::SelectionManager::instance()->setSelectedItem(wellPath); menuBuilder << "RicNewWellLogCurveExtractionFeature"; menuBuilder << "RicNewWellLogFileCurveFeature"; menuBuilder.addSeparator(); menuBuilder.subMenuStart("Well Plots", QIcon(":/WellLogTrack16x16.png")); menuBuilder << "RicNewRftPlotFeature"; menuBuilder << "RicNewPltPlotFeature"; menuBuilder.addSeparator(); menuBuilder << "RicShowWellAllocationPlotFeature"; menuBuilder << "RicNewWellBoreStabilityPlotFeature"; menuBuilder.subMenuEnd(); menuBuilder.addSeparator(); menuBuilder.subMenuStart("3D Well Log Curves", QIcon(":/WellLogCurve16x16.png")); menuBuilder << "RicAdd3dWellLogCurveFeature"; menuBuilder << "RicAdd3dWellLogFileCurveFeature"; menuBuilder.subMenuEnd(); menuBuilder.addSeparator(); menuBuilder << "RicNewWellPathAttributeFeature"; menuBuilder.subMenuStart("Completions", QIcon(":/FishBoneGroup16x16.png")); menuBuilder << "RicNewWellPathFractureAtPosFeature"; menuBuilder << "RicNewFishbonesSubsAtMeasuredDepthFeature"; menuBuilder << "RicNewPerforationIntervalAtMeasuredDepthFeature"; menuBuilder.subMenuEnd(); menuBuilder.addSeparator(); menuBuilder << "RicNewWellPathIntersectionFeature"; } } const RivSimWellPipeSourceInfo* eclipseWellSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); if (eclipseWellSourceInfo) { RimSimWellInView* well = eclipseWellSourceInfo->well(); if (well) { caf::SelectionManager::instance()->setSelectedItem(well); RiuSelectionItem* selItem = new RiuSimWellSelectionItem(eclipseWellSourceInfo->well(), m_currentPickPositionInDomainCoords, eclipseWellSourceInfo->branchIndex()); RiuSelectionManager::instance()->setSelectedItem(selItem, RiuSelectionManager::RUI_TEMPORARY); menuBuilder << "RicNewWellLogCurveExtractionFeature"; menuBuilder << "RicNewWellLogRftCurveFeature"; menuBuilder.addSeparator(); menuBuilder.subMenuStart("Well Plots", QIcon(":/WellLogTrack16x16.png")); menuBuilder << "RicNewRftPlotFeature"; menuBuilder << "RicNewPltPlotFeature"; menuBuilder.addSeparator(); menuBuilder << "RicPlotProductionRateFeature"; menuBuilder << "RicShowWellAllocationPlotFeature"; menuBuilder.subMenuEnd(); menuBuilder.addSeparator(); menuBuilder << "RicShowContributingWellsFeature"; menuBuilder.addSeparator(); menuBuilder << "RicNewSimWellFractureAtPosFeature"; menuBuilder.addSeparator(); menuBuilder << "RicNewSimWellIntersectionFeature"; } } } // View Link commands if (!firstHitPart) { if (gridView) { menuBuilder << "RicLinkViewFeature"; menuBuilder << "RicShowLinkOptionsFeature"; menuBuilder << "RicSetMasterViewFeature"; menuBuilder << "RicUnLinkViewFeature"; } else if (int2dView) { menuBuilder << "RicSelectColorResult"; } } if (gridView) { menuBuilder.addSeparator(); menuBuilder << "RicNewGridTimeHistoryCurveFeature"; menuBuilder << "RicShowFlowCharacteristicsPlotFeature"; menuBuilder << "RicSaveEclipseInputActiveVisibleCellsFeature"; menuBuilder << "RicShowGridStatisticsFeature"; menuBuilder << "RicSelectColorResult"; } else if (int2dView) { } menuBuilder.appendToMenu(&menu); if (!menu.isEmpty()) { menu.exec(event->globalPos()); } // Delete items in temporary selection RiuSelectionManager::instance()->deleteAllItems(RiuSelectionManager::RUI_TEMPORARY); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::handlePickAction(int winPosX, int winPosY, Qt::KeyboardModifiers keyboardModifiers) { // Overlay item picking if (handleOverlayItemPicking(winPosX, winPosY)) { return; } // Do the ray intersection with the scene std::vector pickItemInfos; { cvf::HitItemCollection hitItems; if ( m_viewer->rayPick(winPosX, winPosY, &hitItems) ) { if ( hitItems.count() ) { pickItemInfos = RiuPickItemInfo::convertToPickItemInfos(hitItems); } } } // Make pickEventHandlers do their stuff if ( pickItemInfos.size() ) { Ric3DPickEvent viewerEventObject(pickItemInfos, m_reservoirView); if (sm_overridingPickHandler && sm_overridingPickHandler->handlePickEvent(viewerEventObject)) { return; } for ( size_t i = 0; i < sm_defaultPickEventHandlers.size(); i++ ) { if ( sm_defaultPickEventHandlers[i]->handlePickEvent(viewerEventObject) ) { return; } } } // Old pick handling. Todo: Encapsulate in pickEventHandlers size_t gridIndex = cvf::UNDEFINED_SIZE_T; size_t cellIndex = cvf::UNDEFINED_SIZE_T; size_t nncIndex = cvf::UNDEFINED_SIZE_T; cvf::StructGridInterface::FaceType face = cvf::StructGridInterface::NO_FACE; int gmFace = -1; bool intersectionHit = false; std::array intersectionTriangleHit; cvf::Vec3d localIntersectionPoint(cvf::Vec3d::ZERO); cvf::Vec3d globalIntersectionPoint(cvf::Vec3d::ZERO); // Extract all the above information from the pick { const cvf::Part* firstHitPart = nullptr; uint firstPartTriangleIndex = cvf::UNDEFINED_UINT; const cvf::Part* firstNncHitPart = nullptr; uint nncPartTriangleIndex = cvf::UNDEFINED_UINT; if ( pickItemInfos.size() ) { size_t indexToFirstNoneNncItem = cvf::UNDEFINED_SIZE_T;; size_t indexToNncItemNearFirstItem = cvf::UNDEFINED_SIZE_T;; findFirstItems(pickItemInfos, &indexToFirstNoneNncItem, &indexToNncItemNearFirstItem); if ( indexToFirstNoneNncItem != cvf::UNDEFINED_SIZE_T ) { localIntersectionPoint = pickItemInfos[indexToFirstNoneNncItem].localPickedPoint(); globalIntersectionPoint = pickItemInfos[indexToFirstNoneNncItem].globalPickedPoint(); firstHitPart = pickItemInfos[indexToFirstNoneNncItem].pickedPart(); firstPartTriangleIndex = pickItemInfos[indexToFirstNoneNncItem].faceIdx(); } if ( indexToNncItemNearFirstItem != cvf::UNDEFINED_SIZE_T ) { firstNncHitPart = pickItemInfos[indexToNncItemNearFirstItem].pickedPart(); nncPartTriangleIndex = pickItemInfos[indexToNncItemNearFirstItem].faceIdx(); } } if (firstNncHitPart && firstNncHitPart->sourceInfo()) { const RivSourceInfo* rivSourceInfo = dynamic_cast(firstNncHitPart->sourceInfo()); if (rivSourceInfo) { if (nncPartTriangleIndex < rivSourceInfo->m_NNCIndices->size()) { nncIndex = rivSourceInfo->m_NNCIndices->get(nncPartTriangleIndex); } } } if (firstHitPart && firstHitPart->sourceInfo()) { const RivObjectSourceInfo* rivObjectSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivSourceInfo* rivSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivFemPickSourceInfo* femSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivIntersectionSourceInfo* crossSectionSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivIntersectionBoxSourceInfo* intersectionBoxSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivSimWellPipeSourceInfo* eclipseWellSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivWellConnectionSourceInfo* wellConnectionSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); if (rivObjectSourceInfo) { RimFracture* fracture = dynamic_cast(rivObjectSourceInfo->object()); { bool blockSelectionOfFracture = false; if (fracture) { std::vector uiItems; RiuMainWindow::instance()->projectTreeView()->selectedUiItems(uiItems); if (uiItems.size() == 1) { auto selectedFractureTemplate = dynamic_cast(uiItems[0]); if (selectedFractureTemplate != nullptr && selectedFractureTemplate == fracture->fractureTemplate()) { blockSelectionOfFracture = true; } } } if (!blockSelectionOfFracture) { RiuMainWindow::instance()->selectAsCurrentItem(fracture); } } RimStimPlanFractureTemplate* stimPlanTempl = fracture ? dynamic_cast(fracture->fractureTemplate()) : nullptr; RimEllipseFractureTemplate* ellipseTempl = fracture ? dynamic_cast(fracture->fractureTemplate()) : nullptr; if (stimPlanTempl || ellipseTempl) { // Set fracture resultInfo text QString resultInfoText; cvf::ref transForm = m_reservoirView->displayCoordTransform(); cvf::Vec3d domainCoord = transForm->transformToDomainCoord(globalIntersectionPoint); RimEclipseView* eclView = dynamic_cast(m_reservoirView.p()); RivWellFracturePartMgr* partMgr = fracture->fracturePartManager(); if (eclView) resultInfoText = partMgr->resultInfoText(*eclView, domainCoord); // Set intersection point result text QString intersectionPointText; intersectionPointText.sprintf("Intersection point : Global [E: %.2f, N: %.2f, Depth: %.2f]", domainCoord.x(), domainCoord.y(), -domainCoord.z()); resultInfoText.append(intersectionPointText); // Display result info text RiuMainWindow::instance()->setResultInfo(resultInfoText); } } if (rivSourceInfo) { gridIndex = rivSourceInfo->gridIndex(); if (rivSourceInfo->hasCellFaceMapping()) { CVF_ASSERT(rivSourceInfo->m_cellFaceFromTriangleMapper.notNull()); cellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(firstPartTriangleIndex); face = rivSourceInfo->m_cellFaceFromTriangleMapper->cellFace(firstPartTriangleIndex); } } else if (femSourceInfo) { gridIndex = femSourceInfo->femPartIndex(); cellIndex = femSourceInfo->triangleToElmMapper()->elementIndex(firstPartTriangleIndex); gmFace = femSourceInfo->triangleToElmMapper()->elementFace(firstPartTriangleIndex); } else if (crossSectionSourceInfo) { findCellAndGridIndex(crossSectionSourceInfo, firstPartTriangleIndex, &cellIndex, &gridIndex); intersectionHit = true; intersectionTriangleHit = crossSectionSourceInfo->triangle(firstPartTriangleIndex); bool allowActiveViewChange = dynamic_cast(m_viewer->ownerViewWindow()) == nullptr; RiuMainWindow::instance()->selectAsCurrentItem(crossSectionSourceInfo->crossSection(), allowActiveViewChange); } else if (intersectionBoxSourceInfo) { findCellAndGridIndex(intersectionBoxSourceInfo, firstPartTriangleIndex, &cellIndex, &gridIndex); intersectionHit = true; intersectionTriangleHit = intersectionBoxSourceInfo->triangle(firstPartTriangleIndex); RiuMainWindow::instance()->selectAsCurrentItem(intersectionBoxSourceInfo->intersectionBox()); } else if (eclipseWellSourceInfo) { bool allowActiveViewChange = dynamic_cast(m_viewer->ownerViewWindow()) == nullptr; RiuMainWindow::instance()->selectAsCurrentItem(eclipseWellSourceInfo->well(), allowActiveViewChange); } else if (wellConnectionSourceInfo) { bool allowActiveViewChange = dynamic_cast(m_viewer->ownerViewWindow()) == nullptr; size_t globalCellIndex = wellConnectionSourceInfo->globalCellIndexFromTriangleIndex(firstPartTriangleIndex); RimEclipseView* eclipseView = dynamic_cast(m_reservoirView.p()); if (eclipseView) { RimEclipseCase* eclipseCase = nullptr; eclipseView->firstAncestorOrThisOfTypeAsserted(eclipseCase); if (eclipseCase->eclipseCaseData() && eclipseCase->eclipseCaseData()->virtualPerforationTransmissibilities()) { std::vector completionsForOneCell; { auto connectionFactors = eclipseCase->eclipseCaseData()->virtualPerforationTransmissibilities(); size_t timeStep = eclipseView->currentTimeStep(); const auto& multipleCompletions = connectionFactors->multipleCompletionsPerEclipseCell(wellConnectionSourceInfo->wellPath(), timeStep); auto completionDataIt = multipleCompletions.find(globalCellIndex); if (completionDataIt != multipleCompletions.end()) { completionsForOneCell = completionDataIt->second; } } if (!completionsForOneCell.empty()) { double aggregatedConnectionFactor = 0.0; for (const auto& completionData : completionsForOneCell) { aggregatedConnectionFactor += completionData.transmissibility(); } QString resultInfoText; resultInfoText += QString("Well Connection Factor : %1

").arg(aggregatedConnectionFactor); { RiuResultTextBuilder textBuilder(eclipseView, globalCellIndex, eclipseView->currentTimeStep()); resultInfoText += textBuilder.geometrySelectionText("
"); } resultInfoText += "

Details :
"; for (const auto& completionData : completionsForOneCell) { for (const auto& metaData : completionData.metadata()) { resultInfoText += QString("Name %1 Description %2
").arg(metaData.name).arg(metaData.comment); } } RiuMainWindow::instance()->setResultInfo(resultInfoText); } } } RiuMainWindow::instance()->selectAsCurrentItem(wellConnectionSourceInfo->wellPath(), allowActiveViewChange); } else if (dynamic_cast(firstHitPart->sourceInfo())) { const RivSimWellConnectionSourceInfo* simWellConnectionSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); bool allowActiveViewChange = dynamic_cast(m_viewer->ownerViewWindow()) == nullptr; size_t globalCellIndex = simWellConnectionSourceInfo->globalCellIndexFromTriangleIndex(firstPartTriangleIndex); double connectionFactor = simWellConnectionSourceInfo->connectionFactorFromTriangleIndex(firstPartTriangleIndex); RimEclipseView* eclipseView = dynamic_cast(m_reservoirView.p()); if (eclipseView) { RimEclipseCase* eclipseCase = nullptr; eclipseView->firstAncestorOrThisOfTypeAsserted(eclipseCase); if (eclipseCase->eclipseCaseData() && eclipseCase->eclipseCaseData()->virtualPerforationTransmissibilities()) { auto connectionFactors = eclipseCase->eclipseCaseData()->virtualPerforationTransmissibilities(); size_t timeStep = eclipseView->currentTimeStep(); const auto& completionData = connectionFactors->completionsForSimWell(simWellConnectionSourceInfo->simWellInView()->simWellData(), timeStep); for (const auto& compData : completionData) { if (compData.completionDataGridCell().globalCellIndex() == globalCellIndex) { { QString resultInfoText = QString("Simulation Well Connection Factor : %1

").arg(connectionFactor); { RiuResultTextBuilder textBuilder(eclipseView, globalCellIndex, eclipseView->currentTimeStep()); resultInfoText += textBuilder.geometrySelectionText("
"); } RiuMainWindow::instance()->setResultInfo(resultInfoText); } break; } } } } RiuMainWindow::instance()->selectAsCurrentItem(simWellConnectionSourceInfo->simWellInView(), allowActiveViewChange); } } } if (cellIndex == cvf::UNDEFINED_SIZE_T) { RiuSelectionManager::instance()->deleteAllItems(); } else { bool appendToSelection = false; if (keyboardModifiers & Qt::ControlModifier) { appendToSelection = true; } std::vector items; RiuSelectionManager::instance()->selectedItems(items); const caf::ColorTable& colorTable = RiaColorTables::selectionPaletteColors(); cvf::Color3f curveColor = colorTable.cycledColor3f(items.size()); if (!appendToSelection) { curveColor = colorTable.cycledColor3f(0); } RiuSelectionItem* selItem = nullptr; { Rim2dIntersectionView* intersectionView = dynamic_cast(m_reservoirView.p()); RimEclipseView* eclipseView = dynamic_cast(m_reservoirView.p()); RimGeoMechView* geomView = dynamic_cast(m_reservoirView.p()); if (intersectionView) { intersectionView->intersection()->firstAncestorOrThisOfType(eclipseView); intersectionView->intersection()->firstAncestorOrThisOfType(geomView); } if (eclipseView) { selItem = new RiuEclipseSelectionItem(eclipseView, gridIndex, cellIndex, nncIndex, curveColor, face, localIntersectionPoint); } if (geomView) { if(intersectionHit) selItem = new RiuGeoMechSelectionItem(geomView, gridIndex, cellIndex, curveColor, gmFace, localIntersectionPoint, intersectionTriangleHit); else selItem = new RiuGeoMechSelectionItem(geomView, gridIndex, cellIndex, curveColor, gmFace, localIntersectionPoint); } if (intersectionView) selItem = new Riu2dIntersectionSelectionItem(intersectionView, selItem); } if (appendToSelection) { RiuSelectionManager::instance()->appendItemToSelection(selItem); } else if(selItem) { RiuSelectionManager::instance()->setSelectedItem(selItem); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::setPickEventHandler(RicPickEventHandler* pickEventHandler) { if (sm_overridingPickHandler) sm_overridingPickHandler->notifyUnregistered(); sm_overridingPickHandler = pickEventHandler; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::removePickEventHandlerIfActive(RicPickEventHandler* pickEventHandler) { if (sm_overridingPickHandler == pickEventHandler) { sm_overridingPickHandler = nullptr; if (pickEventHandler) pickEventHandler->notifyUnregistered(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::Vec3d RiuViewerCommands::lastPickPositionInDomainCoords() const { return m_currentPickPositionInDomainCoords; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::addDefaultPickEventHandler(RicDefaultPickEventHandler* pickEventHandler) { removeDefaultPickEventHandler(pickEventHandler); if (pickEventHandler) { sm_defaultPickEventHandlers.push_back(pickEventHandler); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::removeDefaultPickEventHandler(RicDefaultPickEventHandler* pickEventHandler) { for ( auto it = sm_defaultPickEventHandlers.begin(); it != sm_defaultPickEventHandlers.end(); ++it ) { if ( *it == pickEventHandler ) { sm_defaultPickEventHandlers.erase(it); break; } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::findCellAndGridIndex(const RivIntersectionSourceInfo* crossSectionSourceInfo, cvf::uint firstPartTriangleIndex, size_t* cellIndex, size_t* gridIndex) { CVF_ASSERT(cellIndex && gridIndex); RimCase* ownerCase = m_reservoirView->ownerCase(); RimEclipseCase* eclipseCase = dynamic_cast(ownerCase); RimGeoMechCase* geomCase = dynamic_cast(ownerCase); if (eclipseCase) { //RimEclipseView* eclipseView = dynamic_cast(m_reservoirView.p()); RimEclipseView* eclipseView; crossSectionSourceInfo->crossSection()->firstAncestorOrThisOfType(eclipseView); size_t globalCellIndex = crossSectionSourceInfo->triangleToCellIndex()[firstPartTriangleIndex]; const RigGridBase* hostGrid = eclipseView->mainGrid()->gridAndGridLocalIdxFromGlobalCellIdx(globalCellIndex, cellIndex); *gridIndex = hostGrid->gridIndex(); } else if (geomCase) { *cellIndex = crossSectionSourceInfo->triangleToCellIndex()[firstPartTriangleIndex]; *gridIndex = 0; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::findCellAndGridIndex(const RivIntersectionBoxSourceInfo* intersectionBoxSourceInfo, cvf::uint firstPartTriangleIndex, size_t* cellIndex, size_t* gridIndex) { CVF_ASSERT(cellIndex && gridIndex); RimEclipseView* eclipseView = dynamic_cast(m_reservoirView.p()); RimGeoMechView* geomView = dynamic_cast(m_reservoirView.p()); if (eclipseView) { size_t globalCellIndex = intersectionBoxSourceInfo->triangleToCellIndex()[firstPartTriangleIndex]; const RigCell& cell = eclipseView->mainGrid()->globalCellArray()[globalCellIndex]; *cellIndex = cell.gridLocalCellIndex(); *gridIndex = cell.hostGrid()->gridIndex(); } else if (geomView) { *cellIndex = intersectionBoxSourceInfo->triangleToCellIndex()[firstPartTriangleIndex]; *gridIndex = 0; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::findFirstItems(const std::vector & pickItemInfos, size_t* indexToFirstNoneNncItem, size_t* indexToNncItemNearFirsItem) { CVF_ASSERT(pickItemInfos.size() > 0); CVF_ASSERT(indexToFirstNoneNncItem); CVF_ASSERT(indexToNncItemNearFirsItem); double pickDepthThresholdSquared = 0.05 *0.05; { RimEclipseView* eclipseView = dynamic_cast(m_reservoirView.p()); if (eclipseView && eclipseView->mainGrid()) { double characteristicCellSize = eclipseView->mainGrid()->characteristicIJCellSize(); pickDepthThresholdSquared = characteristicCellSize / 100.0; pickDepthThresholdSquared = pickDepthThresholdSquared * pickDepthThresholdSquared; } } size_t firstNonNncHitIndex = cvf::UNDEFINED_SIZE_T; size_t nncNearFirstItemIndex = cvf::UNDEFINED_SIZE_T; cvf::Vec3d firstOrFirstNonNncIntersectionPoint = pickItemInfos[0].globalPickedPoint(); // Find first nnc part, and store as a separate thing if the nnc is first or close behind the first hit item. // Find index to first ordinary (non-nnc) part for (size_t i = 0; i < pickItemInfos.size(); i++) { // If hit item is nnc and is close to first (none-nnc) hit, store nncpart and face id bool canFindRelvantNNC = true; const RivSourceInfo* rivSourceInfo = dynamic_cast(pickItemInfos[i].sourceInfo()); if ( rivSourceInfo && rivSourceInfo->hasNNCIndices() ) { if ( nncNearFirstItemIndex == cvf::UNDEFINED_SIZE_T && canFindRelvantNNC) { cvf::Vec3d distFirstNonNNCToCandidate = firstOrFirstNonNncIntersectionPoint - pickItemInfos[i].globalPickedPoint(); // This candidate is an NNC hit if ( distFirstNonNNCToCandidate.lengthSquared() < pickDepthThresholdSquared ) { nncNearFirstItemIndex = i; } else { canFindRelvantNNC = false; } } } else { if ( firstNonNncHitIndex == cvf::UNDEFINED_SIZE_T ) { firstNonNncHitIndex = i; } } if (firstNonNncHitIndex != cvf::UNDEFINED_SIZE_T && (nncNearFirstItemIndex != cvf::UNDEFINED_SIZE_T || !canFindRelvantNNC) ) { break; // Found what can be found } } (*indexToFirstNoneNncItem) = firstNonNncHitIndex; (*indexToNncItemNearFirsItem) = nncNearFirstItemIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::ijkFromCellIndex(size_t gridIdx, size_t cellIndex, size_t* i, size_t* j, size_t* k) { RimEclipseView* eclipseView = dynamic_cast(m_reservoirView.p()); RimGeoMechView* geomView = dynamic_cast(m_reservoirView.p()); if (eclipseView && eclipseView->eclipseCase()) { eclipseView->eclipseCase()->eclipseCaseData()->grid(gridIdx)->ijkFromCellIndex(cellIndex, i, j, k); } if (geomView && geomView->geoMechCase()) { geomView->femParts()->part(gridIdx)->getOrCreateStructGrid()->ijkFromCellIndex(cellIndex, i, j, k); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RiuViewerCommands::handleOverlayItemPicking(int winPosX, int winPosY) { cvf::OverlayItem* pickedOverlayItem = m_viewer->overlayItem(winPosX, winPosY); if (!pickedOverlayItem) { pickedOverlayItem = m_viewer->pickFixedPositionedLegend(winPosX, winPosY); } if (pickedOverlayItem) { auto intersectionView = dynamic_cast(m_reservoirView.p()); if (intersectionView && intersectionView->handleOverlayItemPicked(pickedOverlayItem)) { return true; } else { std::vector legendConfigs = m_reservoirView->legendConfigs(); for (const auto& legendConfig : legendConfigs) { if (legendConfig && legendConfig->titledOverlayFrame() == pickedOverlayItem) { RiuMainWindow::instance()->selectAsCurrentItem(legendConfig); return true; } } } } return false; }