#3387 Add "Show Well Plan" command

This commit is contained in:
Jacob Støren 2018-09-26 12:38:53 +02:00
parent 4170a57bf2
commit 478160fdfe
11 changed files with 383 additions and 2 deletions

View File

@ -29,6 +29,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaCurveDataTools.h
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveResampler.h
${CMAKE_CURRENT_LIST_DIR}/RiaStatisticsTools.h
${CMAKE_CURRENT_LIST_DIR}/RiaPolyArcLineSampler.h
${CMAKE_CURRENT_LIST_DIR}/RiaWellPlanCalculator.h
${CMAKE_CURRENT_LIST_DIR}/RiaSCurveCalculator.h
${CMAKE_CURRENT_LIST_DIR}/RiaArcCurveCalculator.h
${CMAKE_CURRENT_LIST_DIR}/RiaJCurveCalculator.h
@ -70,6 +71,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaCurveDataTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveResampler.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaStatisticsTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaPolyArcLineSampler.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaWellPlanCalculator.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaSCurveCalculator.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaArcCurveCalculator.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaJCurveCalculator.cpp

View File

@ -0,0 +1,134 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaWellPlanCalculator.h"
#include "cvfGeometryTools.h"
#include "cvfMatrix4.h"
#include "RiaArcCurveCalculator.h"
#include "RiaOffshoreSphericalCoords.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaWellPlanCalculator::RiaWellPlanCalculator(const cvf::Vec3d& startTangent,
const std::vector<cvf::Vec3d>& lineArcEndPoints)
: m_startTangent(startTangent)
, m_lineArcEndPoints(lineArcEndPoints)
{
if (m_lineArcEndPoints.size() < 2) return ;
WellPlanSegment segment = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
RiaOffshoreSphericalCoords startAziIncRad(m_startTangent);
segment.inc = cvf::Math::toDegrees(startAziIncRad.inc());
segment.azi = cvf::Math::toDegrees(startAziIncRad.azi());
segment.TVD = -lineArcEndPoints[0].z();
segment.NS = lineArcEndPoints[0].y();
segment.EW = lineArcEndPoints[0].x();
m_wpResult.push_back(segment);
cvf::Vec3d p1 = m_lineArcEndPoints[0];
cvf::Vec3d p2 = m_lineArcEndPoints[1];
cvf::Vec3d t2 = m_startTangent;
for (size_t pIdx = 0; pIdx < m_lineArcEndPoints.size() - 1 ; ++pIdx)
{
addSegment(t2, m_lineArcEndPoints[pIdx], m_lineArcEndPoints[pIdx + 1] , &t2);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaWellPlanCalculator::addSegment(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent)
{
cvf::Vec3d p1p2 = p2 - p1;
CVF_ASSERT (p1p2.lengthSquared() > 1e-20);
if (cvf::GeometryTools::getAngle(t1, p1p2) < 1e-5)
{
addLineSegment(p1, p2, endTangent);
}
else // resample arc
{
addArcSegment(t1, p1, p2, endTangent);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaWellPlanCalculator::addLineSegment(cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent)
{
WellPlanSegment segment = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
cvf::Vec3d p1p2 = p2 - p1;
double length = p1p2.length();
segment.CL = length;
segment.MD = m_wpResult.back().MD + length;
cvf::Vec3d tangent = p1p2 / length;
RiaOffshoreSphericalCoords aziIncRad(p1p2);
segment.inc = cvf::Math::toDegrees(aziIncRad.inc());
segment.azi = cvf::Math::toDegrees(aziIncRad.azi());
segment.TVD = -p2.z();
segment.NS = p2.y();
segment.EW = p2.x();
segment.dogleg = 0.0;
segment.build = 0.0;
segment.turn = 0.0;
m_wpResult.push_back(segment);
*endTangent = tangent;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaWellPlanCalculator::addArcSegment(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent)
{
WellPlanSegment segment = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
RiaArcCurveCalculator arcCalc(p1, t1, p2);
segment.CL = arcCalc.arcLength();
segment.MD = m_wpResult.back().MD + segment.CL;
segment.inc = cvf::Math::toDegrees(arcCalc.endInclination());
segment.azi = cvf::Math::toDegrees(arcCalc.endAzimuth());
segment.TVD = -p2.z();
segment.NS = p2.y();
segment.EW = p2.x();
segment.dogleg = cvf::Math::toDegrees(30.0/arcCalc.radius());
RiaOffshoreSphericalCoords startAziIncRad(t1);
double buildInRadsPrLength = (arcCalc.endInclination() - startAziIncRad.inc())/arcCalc.arcLength();
double turnInRadsPrLength = (arcCalc.endAzimuth() - startAziIncRad.azi())/arcCalc.arcLength();
segment.build = 30*cvf::Math::toDegrees(buildInRadsPrLength) ;
segment.turn = 30*cvf::Math::toDegrees(turnInRadsPrLength) ;
m_wpResult.push_back(segment);
(*endTangent) = arcCalc.endTangent();
}

View File

@ -0,0 +1,58 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cvfBase.h"
#include "cvfVector3.h"
#include <vector>
class RiaWellPlanCalculator
{
public:
RiaWellPlanCalculator(const cvf::Vec3d& startTangent,
const std::vector<cvf::Vec3d>& lineArcEndPoints);
struct WellPlanSegment
{
double MD;
double CL;
double inc;
double azi;
double TVD;
double NS;
double EW;
double dogleg;
double build;
double turn;
};
const std::vector<WellPlanSegment>& wellPlan() const { return m_wpResult; }
private:
void addSegment(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent);
void addLineSegment(cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent);
void addArcSegment(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent);
cvf::Vec3d m_startTangent;
std::vector<cvf::Vec3d> m_lineArcEndPoints;
std::vector<WellPlanSegment> m_wpResult;
};

View File

@ -4,6 +4,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicWellPathDeleteFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportFileFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportSsihubFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewEditableWellPathFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicShowWellPlanFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewWellPathListTargetFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewWellPathAttributeFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicDeleteWellPathTargetFeature.h
@ -22,6 +23,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicWellPathDeleteFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportFileFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicWellPathsImportSsihubFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewEditableWellPathFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicShowWellPlanFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewWellPathListTargetFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewWellPathAttributeFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicDeleteWellPathTargetFeature.cpp

View File

@ -0,0 +1,84 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicShowWellPlanFeature.h"
#include "RimModeledWellPath.h"
#include "../ApplicationCommands/RicShowPlotDataFeature.h"
#include "cafSelectionManagerTools.h"
#include <QAction>
#include "RiuTextDialog.h"
CAF_CMD_SOURCE_INIT(RicShowWellPlanFeature, "RicShowWellPlanFeature");
//--------------------------------------------------------------------------------------------------
///
///
/// RicShowPlotDataFeature
///
///
//--------------------------------------------------------------------------------------------------
bool RicShowWellPlanFeature::isCommandEnabled()
{
auto selectedWellPaths = caf::selectedObjectsByType<RimModeledWellPath*>();
if (selectedWellPaths.size() > 0)
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicShowWellPlanFeature::onActionTriggered(bool isChecked)
{
this->disableModelChangeContribution();
std::vector<RimModeledWellPath*> selectedWellPaths = caf::selectedObjectsByType<RimModeledWellPath*>();
if (selectedWellPaths.size() == 0 )
{
return;
}
for (auto wellPath : selectedWellPaths)
{
QString title = "Well Plan for " + wellPath->name();
RiuTextDialog* textDialog = new RiuTextDialog();
textDialog->setMinimumSize(800, 600);
textDialog->setWindowTitle(title);
textDialog->setText(wellPath->wellPlanText());
textDialog->show();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicShowWellPlanFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("Show Well Plan");
actionToSetup->setIcon(QIcon(":/PlotWindow24x24.png"));
}

View File

@ -0,0 +1,37 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
//==================================================================================================
///
//==================================================================================================
class RicShowWellPlanFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
// Overrides
virtual bool isCommandEnabled();
virtual void onActionTriggered( bool isChecked );
virtual void setupActionLook( QAction* actionToSetup );
};

View File

@ -93,6 +93,7 @@
#include "RimSimWellFracture.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#include "RimModeledWellPath.h"
#include "RiuMainWindow.h"
@ -279,12 +280,11 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder.addSeparator();
menuBuilder.subMenuStart("3D Well Log Curves", QIcon(":/WellLogCurve16x16.png"));
menuBuilder << "RicAdd3dWellLogCurveFeature";
menuBuilder << "RicAdd3dWellLogFileCurveFeature";
menuBuilder << "RicAdd3dWellLogRftCurveFeature";
menuBuilder.subMenuEnd();
menuBuilder << "RicNewEditableWellPathFeature";
menuBuilder << "RicNewWellPathIntersectionFeature";
@ -307,6 +307,10 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicExportVisibleWellPathsFeature";
menuBuilder.subMenuEnd();
if ( dynamic_cast<RimModeledWellPath*>(uiItem) )
{
menuBuilder << "RicShowWellPlanFeature";
}
menuBuilder << "RicCreateMultipleFracturesFeature";
menuBuilder << "Separator";

View File

@ -30,6 +30,7 @@
#include "RimWellPath.h"
#include "RimWellPathFractureCollection.h"
#include "RimWellPathFracture.h"
#include "RifEclipseDataTableFormatter.h"
CAF_PDM_SOURCE_INIT(RimModeledWellPath, "ModeledWellPath");
@ -116,6 +117,54 @@ RimWellPathGeometryDef* RimModeledWellPath::geometryDefinition()
return m_geometryDefinition;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimModeledWellPath::wellPlanText()
{
QString planText;
QTextStream qtxtStream(&planText);
RifEclipseDataTableFormatter formatter(qtxtStream);
formatter.setTableRowPrependText("");
formatter.setTableRowLineAppendText("");
std::vector<RifEclipseOutputTableColumn> tableHeader;
tableHeader.push_back({"MD"});
tableHeader.push_back({"CL"});
tableHeader.push_back({"Inc"});
tableHeader.push_back({"Azi"});
tableHeader.push_back({"TVD"});
tableHeader.push_back({"NS"});
tableHeader.push_back({"EW"});
tableHeader.push_back({"Dogleg"});
tableHeader.push_back({"Build"});
tableHeader.push_back({"Turn"});
formatter.header(tableHeader);
if (m_geometryDefinition)
{
std::vector<RiaWellPlanCalculator::WellPlanSegment> wellPlan = m_geometryDefinition->wellPlan();
for (const auto& segment : wellPlan)
{
formatter.add(segment.MD);
formatter.add(segment.CL);
formatter.add(segment.inc);
formatter.add(segment.azi);
formatter.add(segment.TVD);
formatter.add(segment.NS);
formatter.add(segment.EW);
formatter.add(segment.dogleg);
formatter.add(segment.build);
formatter.add(segment.turn);
formatter.rowCompleted();
}
}
formatter.tableCompleted();
return planText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -37,6 +37,7 @@ public:
void updateWellPathVisualization();
void scheduleUpdateOfDependentVisualization();
RimWellPathGeometryDef* geometryDefinition();
QString wellPlanText();
private:
virtual void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName) override;

View File

@ -139,6 +139,14 @@ cvf::ref<RigWellPath> RimWellPathGeometryDef::createWellPathGeometry()
return wellPathGeometry;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RiaWellPlanCalculator::WellPlanSegment> RimWellPathGeometryDef::wellPlan() const
{
RiaWellPlanCalculator wpCalc(startTangent(), lineArcEndpoints());
return wpCalc.wellPlan();
}
//--------------------------------------------------------------------------------------------------
///

View File

@ -25,6 +25,7 @@
#include "cafPdmFieldCvfVec3d.h"
#include "cafPdmPtrField.h"
#include "cafPdmChildArrayField.h"
#include "RiaWellPlanCalculator.h"
class RimWellPath;
@ -62,6 +63,7 @@ public:
void enableTargetPointPicking(bool isEnabling);
std::vector<RiaWellPlanCalculator::WellPlanSegment> wellPlan() const;
std::vector<RimWellPathTarget*> activeWellTargets() const;
protected:
void defineCustomContextMenu(const caf::PdmFieldHandle* fieldNeedingMenu,