From 107a4b9b6007a7ccadd6cc957df4f1db09d4ba53 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Thu, 31 Jan 2019 15:49:12 +0100 Subject: [PATCH] #4012 Always place well target points in real cell geometry --- .../RicCreateWellTargetsPickEventHandler.cpp | 97 +++++++++++++++++++ .../RicCreateWellTargetsPickEventHandler.h | 1 + .../UserInterface/RiuPickItemInfo.cpp | 4 +- .../UserInterface/RiuPickItemInfo.h | 11 ++- .../UserInterface/RiuViewerCommands.cpp | 10 +- Fwk/AppFwk/cafViewer/cafViewer.cpp | 8 +- Fwk/AppFwk/cafViewer/cafViewer.h | 2 +- 7 files changed, 121 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.cpp b/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.cpp index 597bab04dc..b0f29ad855 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.cpp @@ -20,9 +20,16 @@ #include "RiaOffshoreSphericalCoords.h" +#include "RigFemPart.h" +#include "RigFemPartCollection.h" +#include "RigFemPartGrid.h" +#include "RigHexIntersectionTools.h" +#include "RigMainGrid.h" #include "RigWellPath.h" #include "Rim3dView.h" +#include "RimGeoMechView.h" +#include "RimEclipseView.h" #include "RimModeledWellPath.h" #include "RimWellPath.h" #include "RimWellPathGeometryDef.h" @@ -30,11 +37,18 @@ #include "RiuViewerCommands.h" +#include "RivFemPartGeometryGenerator.h" +#include "RivFemPickSourceInfo.h" +#include "RivSourceInfo.h" #include "RivWellPathSourceInfo.h" #include "cafDisplayCoordTransform.h" #include "cafSelectionManager.h" +#include "cvfStructGridGeometryGenerator.h" + +#include + #include //-------------------------------------------------------------------------------------------------- @@ -98,6 +112,17 @@ bool RicCreateWellTargetsPickEventHandler::handlePickEvent(const Ric3DPickEvent& { targetPointInDomain = intersectionPointInDomain; doSetAzimuthAndInclination = false; + + cvf::Vec3d domainRayOrigin = + rimView->displayCoordTransform()->transformToDomainCoord(firstPickItem.globalRayOrigin()); + cvf::Vec3d domainRayEnd = targetPointInDomain + (targetPointInDomain - domainRayOrigin); + + cvf::Vec3d hexElementIntersection = findHexElementIntersection(rimView, firstPickItem, domainRayOrigin, domainRayEnd); + CVF_ASSERT(!hexElementIntersection.isUndefined()); + if (!hexElementIntersection.isUndefined()) + { + targetPointInDomain = hexElementIntersection; + } } if (!m_geometryToAddTargetsTo->firstActiveTarget()) @@ -196,3 +221,75 @@ bool RicCreateWellTargetsPickEventHandler::calculateAzimuthAndInclinationAtMd(do *inclination = 0.0; return false; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RicCreateWellTargetsPickEventHandler::findHexElementIntersection(Rim3dView* view, const RiuPickItemInfo& pickItem, const cvf::Vec3d& domainRayOrigin, const cvf::Vec3d& domainRayEnd) +{ + auto sourceInfo = dynamic_cast(pickItem.sourceInfo()); + auto femSourceInfo = dynamic_cast(pickItem.sourceInfo()); + + size_t cellIndex = cvf::UNDEFINED_SIZE_T; + std::array cornerVertices; + double characteristicLength = 0.0; + if (sourceInfo) + { + size_t gridIndex = sourceInfo->gridIndex(); + if (sourceInfo->hasCellFaceMapping()) + { + cellIndex = sourceInfo->m_cellFaceFromTriangleMapper->cellIndex(pickItem.faceIdx()); + + RimEclipseView* eclipseView = dynamic_cast(view); + if (eclipseView && eclipseView->mainGrid()) + { + RigGridBase* hitGrid = eclipseView->mainGrid()->gridByIndex(gridIndex); + hitGrid->cellCornerVertices(cellIndex, cornerVertices.data()); + double dx, dy, dz; + hitGrid->characteristicCellSizes(&dx, &dy, &dz); + characteristicLength = dz; + } + } + } + else if (femSourceInfo) + { + size_t femPartIndex = femSourceInfo->femPartIndex(); + if (femSourceInfo->triangleToElmMapper()) + { + size_t elementIndex = femSourceInfo->triangleToElmMapper()->elementIndex(pickItem.faceIdx()); + + RimGeoMechView* geoMechView = dynamic_cast(view); + if (geoMechView && geoMechView->femParts()) + { + RigFemPart* femPart = geoMechView->femParts()->part(femPartIndex); + if (femPart->elementType(cellIndex) == HEX8 || femPart->elementType(cellIndex) == HEX8P) + { + cellIndex = elementIndex; + femPart->getOrCreateStructGrid()->cellCornerVertices(cellIndex, cornerVertices.data()); + characteristicLength = femPart->characteristicElementSize(); + } + } + } + } + + std::vector intersectionInfo; + RigHexIntersectionTools::lineHexCellIntersection(domainRayOrigin, domainRayEnd, cornerVertices.data(), cellIndex, &intersectionInfo); + if (!intersectionInfo.empty()) + { + // Sort intersection on distance to ray origin + CVF_ASSERT(intersectionInfo.size() > 1); + std::sort(intersectionInfo.begin(), intersectionInfo.end(), + [&domainRayOrigin](const HexIntersectionInfo& lhs, const HexIntersectionInfo& rhs) + { + return (lhs.m_intersectionPoint - domainRayOrigin).lengthSquared() < (rhs.m_intersectionPoint - domainRayOrigin).lengthSquared(); + } + ); + const double eps = 1.0e-3; + cvf::Vec3d intersectionRay = intersectionInfo.back().m_intersectionPoint - intersectionInfo.front().m_intersectionPoint; + cvf::Vec3d newPoint = intersectionInfo.front().m_intersectionPoint + intersectionRay * eps; + CVF_ASSERT(RigHexIntersectionTools::isPointInCell(newPoint, cornerVertices.data())); + return newPoint; + } + + return cvf::Vec3d::UNDEFINED; +} diff --git a/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.h b/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.h index 3e3ebf60de..789c454528 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.h +++ b/ApplicationCode/Commands/WellPathCommands/RicCreateWellTargetsPickEventHandler.h @@ -44,6 +44,7 @@ private: double* azimuth, double* inclination) const; + static cvf::Vec3d findHexElementIntersection(Rim3dView* view, const RiuPickItemInfo& pickItem, const cvf::Vec3d& domainRayOrigin, const cvf::Vec3d& domainRayEnd); private: caf::PdmPointer m_geometryToAddTargetsTo; }; diff --git a/ApplicationCode/UserInterface/RiuPickItemInfo.cpp b/ApplicationCode/UserInterface/RiuPickItemInfo.cpp index 26339096af..2488bad98f 100644 --- a/ApplicationCode/UserInterface/RiuPickItemInfo.cpp +++ b/ApplicationCode/UserInterface/RiuPickItemInfo.cpp @@ -52,13 +52,13 @@ RiuPickItemInfo RiuPickItemInfo::extractPickItemInfo(const cvf::HitItem* hitItem //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RiuPickItemInfo::convertToPickItemInfos( const cvf::HitItemCollection &hitItems) +std::vector RiuPickItemInfo::convertToPickItemInfos( const cvf::HitItemCollection &hitItems, const cvf::Vec3d& globalRayOrigin) { std::vector pickItemInfos; pickItemInfos.reserve(hitItems.count()); for ( size_t i = 0; i < hitItems.count(); i++ ) { - pickItemInfos.emplace_back(RiuPickItemInfo(hitItems.item(i))); + pickItemInfos.emplace_back(RiuPickItemInfo(hitItems.item(i), globalRayOrigin)); } return pickItemInfos; } diff --git a/ApplicationCode/UserInterface/RiuPickItemInfo.h b/ApplicationCode/UserInterface/RiuPickItemInfo.h index f01073b49d..f554d04469 100644 --- a/ApplicationCode/UserInterface/RiuPickItemInfo.h +++ b/ApplicationCode/UserInterface/RiuPickItemInfo.h @@ -28,6 +28,7 @@ namespace cvf class Object; class HitItem; class HitItemCollection; + class Ray; } @@ -39,18 +40,21 @@ public: , m_pickedPart(nullptr) , m_globalPickedPoint (cvf::Vec3d::UNDEFINED) , m_localPickedPoint (cvf::Vec3d::UNDEFINED) + , m_globalRayOrigin(cvf::Vec3d::UNDEFINED) , m_sourceInfo (nullptr) , m_faceIdx (-1) {} - explicit RiuPickItemInfo(const cvf::HitItem* hitItem) + explicit RiuPickItemInfo(const cvf::HitItem* hitItem, const cvf::Vec3d& globalRayOrigin) : m_pickedPart(nullptr) , m_globalPickedPoint (cvf::Vec3d::UNDEFINED) , m_localPickedPoint (cvf::Vec3d::UNDEFINED) + , m_globalRayOrigin(cvf::Vec3d::UNDEFINED) , m_sourceInfo (nullptr) , m_faceIdx (-1) { *this = extractPickItemInfo(hitItem); + m_globalRayOrigin = globalRayOrigin; } const cvf::Part* pickedPart() const { return m_pickedPart;} @@ -59,18 +63,19 @@ public: const cvf::Object* sourceInfo() const { return m_sourceInfo;} cvf::uint faceIdx() const { return m_faceIdx;} double distanceAlongRay() const { return m_distanceAlongRay;} + cvf::Vec3d globalRayOrigin() const { return m_globalRayOrigin;} static RiuPickItemInfo extractPickItemInfo(const cvf::HitItem* hitItem); - static std::vector convertToPickItemInfos(const cvf::HitItemCollection &hitItems); + static std::vector convertToPickItemInfos(const cvf::HitItemCollection &hitItems, const cvf::Vec3d& globalRayOrigin); private: double m_distanceAlongRay; const cvf::Part* m_pickedPart; cvf::Vec3d m_globalPickedPoint; cvf::Vec3d m_localPickedPoint; + cvf::Vec3d m_globalRayOrigin; const cvf::Object* m_sourceInfo; cvf::uint m_faceIdx; - }; diff --git a/ApplicationCode/UserInterface/RiuViewerCommands.cpp b/ApplicationCode/UserInterface/RiuViewerCommands.cpp index 7a88a3c598..b9c236e321 100644 --- a/ApplicationCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationCode/UserInterface/RiuViewerCommands.cpp @@ -158,9 +158,10 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) std::vector pickItemInfos; { cvf::HitItemCollection hitItems; - if (m_viewer->rayPick(event->x(), event->y(), &hitItems)) + cvf::Vec3d globalRayOrigin; + if (m_viewer->rayPick(event->x(), event->y(), &hitItems, &globalRayOrigin)) { - pickItemInfos = RiuPickItemInfo::convertToPickItemInfos(hitItems); + pickItemInfos = RiuPickItemInfo::convertToPickItemInfos(hitItems, globalRayOrigin); } } @@ -524,15 +525,16 @@ void RiuViewerCommands::handlePickAction(int winPosX, int winPosY, Qt::KeyboardM std::vector pickItemInfos; { + cvf::Vec3d globalRayOrigin; cvf::HitItemCollection hitItems; - m_viewer->rayPick(winPosX, winPosY, &hitItems); + m_viewer->rayPick(winPosX, winPosY, &hitItems, &globalRayOrigin); // Do specialized text pick, since vizfwk does not hit text handleTextPicking(winPosX, winPosY, &hitItems); if (hitItems.count()) { - pickItemInfos = RiuPickItemInfo::convertToPickItemInfos(hitItems); + pickItemInfos = RiuPickItemInfo::convertToPickItemInfos(hitItems, globalRayOrigin); } } diff --git a/Fwk/AppFwk/cafViewer/cafViewer.cpp b/Fwk/AppFwk/cafViewer/cafViewer.cpp index 8e1cf454b6..4a4522470d 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.cpp +++ b/Fwk/AppFwk/cafViewer/cafViewer.cpp @@ -474,7 +474,7 @@ const caf::NavigationPolicy* caf::Viewer::getNavigationPolicy() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool caf::Viewer::rayPick(int winPosX, int winPosY, cvf::HitItemCollection* pickedPoints) +bool caf::Viewer::rayPick(int winPosX, int winPosY, cvf::HitItemCollection* pickedPoints, cvf::Vec3d* globalRayOrigin/*=nullptr*/) { CVF_ASSERT(m_mainRendering.notNull()); @@ -485,7 +485,11 @@ bool caf::Viewer::rayPick(int winPosX, int winPosY, cvf::HitItemCollection* pick if (ris.notNull()) { bool retVal = m_mainRendering->rayIntersect(*ris, pickedPoints); - + if (retVal && globalRayOrigin) + { + CVF_ASSERT(ris->ray() != nullptr); + *globalRayOrigin = ris->ray()->origin(); + } return retVal; } else diff --git a/Fwk/AppFwk/cafViewer/cafViewer.h b/Fwk/AppFwk/cafViewer/cafViewer.h index b3e3af497b..52d1625119 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.h +++ b/Fwk/AppFwk/cafViewer/cafViewer.h @@ -135,7 +135,7 @@ public: // Test whether it is any point in doing navigation etc. bool canRender() const; - bool rayPick(int winPosX, int winPosY, cvf::HitItemCollection* pickedPoints) ; + bool rayPick(int winPosX, int winPosY, cvf::HitItemCollection* pickedPoints, cvf::Vec3d* rayGlobalOrigin = nullptr) ; cvf::OverlayItem* overlayItem(int winPosX, int winPosY); // QPainter based drawing on top of the OpenGL graphics