diff --git a/ApplicationCode/ProjectDataModel/RimEllipseFractureTemplate.cpp b/ApplicationCode/ProjectDataModel/RimEllipseFractureTemplate.cpp index 4f2209f40b..44379568ae 100644 --- a/ApplicationCode/ProjectDataModel/RimEllipseFractureTemplate.cpp +++ b/ApplicationCode/ProjectDataModel/RimEllipseFractureTemplate.cpp @@ -86,7 +86,7 @@ caf::PdmFieldHandle* RimEllipseFractureTemplate::userDescriptionField() void RimEllipseFractureTemplate::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (changedField == &halfLength || changedField == &height || changedField == &azimuthAngle || changedField == &perforationLength) + if (changedField == &halfLength || changedField == &height || changedField == &azimuthAngle || changedField == &perforationLength || changedField == &orientation) { //Changes to one of these parameters should change all fractures with this fracture template attached. RimProject* proj; @@ -112,6 +112,12 @@ void RimEllipseFractureTemplate::fieldChangedByUi(const caf::PdmFieldHandle* cha fracture->setRecomputeGeometryFlag(); } + if (changedField == &orientation) + { + fracture->setAzimuth(orientation()); + fracture->setRecomputeGeometryFlag(); + } + if (changedField == &perforationLength && (abs(oldValue.toDouble() - fracture->perforationLength()) < 1e-5)) { fracture->perforationLength = perforationLength; diff --git a/ApplicationCode/ProjectDataModel/RimFracture.cpp b/ApplicationCode/ProjectDataModel/RimFracture.cpp index 23bec7f118..f26dac02f8 100644 --- a/ApplicationCode/ProjectDataModel/RimFracture.cpp +++ b/ApplicationCode/ProjectDataModel/RimFracture.cpp @@ -201,6 +201,14 @@ caf::PdmFieldHandle* RimFracture::userDescriptionField() return &name; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RimFracture::fracturePosition() const +{ + return m_anchorPosition; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimFracture.h b/ApplicationCode/ProjectDataModel/RimFracture.h index 982df7fc1e..47a09bf03a 100644 --- a/ApplicationCode/ProjectDataModel/RimFracture.h +++ b/ApplicationCode/ProjectDataModel/RimFracture.h @@ -31,6 +31,7 @@ #include "cafPdmPtrField.h" #include "cafPdmFieldCvfVec3d.h" #include "cvfPlane.h" +#include "RimEllipseFractureTemplate.h" class RigFracture; @@ -56,6 +57,7 @@ public: cvf::Vec3d anchorPosition(); void setAnchorPosition(const cvf::Vec3d& pos); + virtual void setAzimuth(RimEllipseFractureTemplate::FracOrientationEnum orientation) =0; cvf::Mat4f transformMatrix(); @@ -79,6 +81,8 @@ public: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; virtual caf::PdmFieldHandle* userDescriptionField() override; + cvf::Vec3d fracturePosition() const; + protected: virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override; diff --git a/ApplicationCode/ProjectDataModel/RimSimWellFracture.cpp b/ApplicationCode/ProjectDataModel/RimSimWellFracture.cpp index 85a89eeac4..e87bd6d2fb 100644 --- a/ApplicationCode/ProjectDataModel/RimSimWellFracture.cpp +++ b/ApplicationCode/ProjectDataModel/RimSimWellFracture.cpp @@ -26,6 +26,8 @@ #include "RimProject.h" #include "cafPdmUiDoubleSliderEditor.h" +#include "RimEllipseFractureTemplate.h" +#include "RimFracture.h" @@ -66,6 +68,34 @@ void RimSimWellFracture::setClosestWellCoord(cvf::Vec3d& position, size_t branch updateFracturePositionFromLocation(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSimWellFracture::setAzimuth(RimEllipseFractureTemplate::FracOrientationEnum orientation) +{ + if (orientation == RimEllipseFractureTemplate::ALONG_WELL_PATH || orientation== RimEllipseFractureTemplate::TRANSVERSE_WELL_PATH) + { + updateBranchGeometry(); + double simWellAzimuth = m_branchCenterLines[m_branchIndex].wellPathAzimuthAngle(fracturePosition()); + if (orientation == RimEllipseFractureTemplate::TRANSVERSE_WELL_PATH ) + { + azimuth = simWellAzimuth; + } + if (orientation == RimEllipseFractureTemplate::ALONG_WELL_PATH) + { + if (simWellAzimuth + 90 < 360) azimuth = simWellAzimuth + 90; + else azimuth = simWellAzimuth - 90; + } + + } + else //Azimuth value, read from template + { + azimuth = attachedFractureDefinition()->azimuthAngle; + } + + +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -120,7 +150,23 @@ void RimSimWellFracture::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi uiOrdering.add(&m_location); caf::PdmUiGroup* geometryGroup = uiOrdering.addNewGroup("Properties"); + geometryGroup->add(&azimuth); + if (attachedFractureDefinition()) + { + if (attachedFractureDefinition()->orientation == RimEllipseFractureTemplate::ALONG_WELL_PATH + || attachedFractureDefinition()->orientation == RimEllipseFractureTemplate::TRANSVERSE_WELL_PATH) + { + azimuth.uiCapability()->setUiReadOnly(true); + } + else if (attachedFractureDefinition()->orientation == RimEllipseFractureTemplate::AZIMUTH) + { + azimuth.uiCapability()->setUiReadOnly(false); + } + } + + + geometryGroup->add(&m_fractureTemplate); caf::PdmUiGroup* fractureCenterGroup = uiOrdering.addNewGroup("Fracture Center Info"); diff --git a/ApplicationCode/ProjectDataModel/RimSimWellFracture.h b/ApplicationCode/ProjectDataModel/RimSimWellFracture.h index bcf9d8b656..866cdc6942 100644 --- a/ApplicationCode/ProjectDataModel/RimSimWellFracture.h +++ b/ApplicationCode/ProjectDataModel/RimSimWellFracture.h @@ -21,6 +21,7 @@ #include "RimFracture.h" #include "RigSimulationWellCoordsAndMD.h" +#include "RimEllipseFractureTemplate.h" //================================================================================================== @@ -41,6 +42,7 @@ public: void recomputeWellCenterlineCoordinates(); void updateFracturePositionFromLocation(); + void setAzimuth(RimEllipseFractureTemplate::FracOrientationEnum orientation) override; protected: diff --git a/ApplicationCode/ProjectDataModel/RimWellPathFracture.cpp b/ApplicationCode/ProjectDataModel/RimWellPathFracture.cpp index 95dd90a0f5..2c3ba3457a 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathFracture.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathFracture.cpp @@ -23,6 +23,7 @@ #include "RimWellPath.h" #include "cafPdmUiDoubleSliderEditor.h" +#include "RimEllipseFractureTemplate.h" @@ -81,6 +82,32 @@ void RimWellPathFracture::fieldChangedByUi(const caf::PdmFieldHandle* changedFie } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathFracture::setAzimuth(RimEllipseFractureTemplate::FracOrientationEnum orientation) +{ + + if (orientation == RimEllipseFractureTemplate::ALONG_WELL_PATH || orientation == RimEllipseFractureTemplate::TRANSVERSE_WELL_PATH) + { +// updateBranchGeometry(); +// double simWellAzimuth = m_branchCenterLines[m_branchIndex].wellPathAzimuthAngle(fracturePosition()); + //TODO: Calculate well path azimuth angle + double WellPathAzimuth = 0.0; + if (orientation == RimEllipseFractureTemplate::ALONG_WELL_PATH) + { + azimuth = WellPathAzimuth; + } + if (orientation == RimEllipseFractureTemplate::TRANSVERSE_WELL_PATH) + { + if (WellPathAzimuth + 90 < 360) azimuth = WellPathAzimuth + 90; + else azimuth = WellPathAzimuth - 90; + } + + } + +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -112,6 +139,20 @@ void RimWellPathFracture::defineUiOrdering(QString uiConfigName, caf::PdmUiOrder caf::PdmUiGroup* geometryGroup = uiOrdering.addNewGroup("Properties"); geometryGroup->add(&azimuth); + if (attachedFractureDefinition()) + { + if (attachedFractureDefinition()->orientation == RimEllipseFractureTemplate::ALONG_WELL_PATH + || attachedFractureDefinition()->orientation == RimEllipseFractureTemplate::TRANSVERSE_WELL_PATH) + { + azimuth.uiCapability()->setUiReadOnly(true); + } + else if (attachedFractureDefinition()->orientation == RimEllipseFractureTemplate::AZIMUTH) + { + azimuth.uiCapability()->setUiReadOnly(false); + } + } + + geometryGroup->add(&m_fractureTemplate); caf::PdmUiGroup* fractureCenterGroup = uiOrdering.addNewGroup("Fracture Center Info"); diff --git a/ApplicationCode/ProjectDataModel/RimWellPathFracture.h b/ApplicationCode/ProjectDataModel/RimWellPathFracture.h index c70e2a0426..fb872dbe5e 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathFracture.h +++ b/ApplicationCode/ProjectDataModel/RimWellPathFracture.h @@ -41,6 +41,7 @@ public: void setMeasuredDepth(double mdValue); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; + virtual void setAzimuth(RimEllipseFractureTemplate::FracOrientationEnum orientation) override; protected: virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; diff --git a/ApplicationCode/ReservoirDataModel/RigSimulationWellCoordsAndMD.cpp b/ApplicationCode/ReservoirDataModel/RigSimulationWellCoordsAndMD.cpp index 98bbe6952c..b7f257d76c 100644 --- a/ApplicationCode/ReservoirDataModel/RigSimulationWellCoordsAndMD.cpp +++ b/ApplicationCode/ReservoirDataModel/RigSimulationWellCoordsAndMD.cpp @@ -19,6 +19,7 @@ #include "RigSimulationWellCoordsAndMD.h" #include "cvfGeometryTools.h" +#include "cvfMath.h" //-------------------------------------------------------------------------------------------------- /// @@ -89,7 +90,29 @@ cvf::Vec3d RigSimulationWellCoordsAndMD::interpolatedPointAlongWellPath(double m double RigSimulationWellCoordsAndMD::locationAlongWellCoords(const cvf::Vec3d& position) const { double location = 0.0; + + size_t closestIndex = findClosestIndex(position); + if (closestIndex != cvf::UNDEFINED_DOUBLE) + { + cvf::Vec3d p1 = m_wellPathPoints[closestIndex - 1]; + cvf::Vec3d p2 = m_wellPathPoints[closestIndex - 0]; + + double intersection = 0.0; + cvf::GeometryTools::projectPointOnLine(p1, p2, position, &intersection); + + location = m_measuredDepths[closestIndex - 1]; + location += intersection * (p1-p2).length(); + } + + return location; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RigSimulationWellCoordsAndMD::findClosestIndex(const cvf::Vec3d& position) const +{ size_t closestIndex = cvf::UNDEFINED_SIZE_T; double closestDistance = cvf::UNDEFINED_DOUBLE; @@ -105,20 +128,48 @@ double RigSimulationWellCoordsAndMD::locationAlongWellCoords(const cvf::Vec3d& p closestIndex = i; } } + return closestIndex; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigSimulationWellCoordsAndMD::wellPathAzimuthAngle(const cvf::Vec3d& position) const +{ + size_t closestIndex = findClosestIndex(position); + + //For vertical well (x-component of direction = 0) returned angle will be 0. + double AzimuthAngle = 0.0; if (closestIndex != cvf::UNDEFINED_DOUBLE) { - cvf::Vec3d p1 = m_wellPathPoints[closestIndex - 1]; - cvf::Vec3d p2 = m_wellPathPoints[closestIndex - 0]; + cvf::Vec3d p1; + cvf::Vec3d p2; - double intersection = 0.0; - cvf::GeometryTools::projectPointOnLine(p1, p2, position, &intersection); + if (closestIndex > 0) + { + p1 = m_wellPathPoints[closestIndex - 1]; + p2 = m_wellPathPoints[closestIndex - 0]; + } + else + { + p1 = m_wellPathPoints[closestIndex + 1]; + p2 = m_wellPathPoints[closestIndex + 0]; + } - location = m_measuredDepths[closestIndex - 1]; - location += intersection * (p1-p2).length(); - } + cvf::Vec3d direction = p1 - p2; - return location; + + if (abs(direction.x()) > 1e-5) + { + double atanValue = direction.y() / direction.x(); + AzimuthAngle = atan(atanValue); + AzimuthAngle = cvf::Math::toDegrees(AzimuthAngle); + AzimuthAngle = -AzimuthAngle; + } + } + + return AzimuthAngle; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigSimulationWellCoordsAndMD.h b/ApplicationCode/ReservoirDataModel/RigSimulationWellCoordsAndMD.h index 49b93aaee9..d16d87218b 100644 --- a/ApplicationCode/ReservoirDataModel/RigSimulationWellCoordsAndMD.h +++ b/ApplicationCode/ReservoirDataModel/RigSimulationWellCoordsAndMD.h @@ -41,6 +41,11 @@ public: cvf::Vec3d interpolatedPointAlongWellPath(double measuredDepth) const; double locationAlongWellCoords(const cvf::Vec3d& position) const; + size_t findClosestIndex(const cvf::Vec3d& position) const; + + double wellPathAzimuthAngle(const cvf::Vec3d& position) const; + + private: void computeMeasuredDepths();