|
|
|
|
|
#include "nmWellEditorSession.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "nmDataHorizontalFracturedWell.h"
|
|
|
|
|
|
#include "nmDataPerforation.h"
|
|
|
|
|
|
#include "nmDataVerticalFracturedWell.h"
|
|
|
|
|
|
#include "nmDataVerticalWell.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
|
#include <QtGlobal>
|
|
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
/* Qt 4.8的lupdate需要显式标记间接翻译字符串。 */
|
|
|
|
|
|
static const char* const s_pSessionTranslationMarkers[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
QT_TRANSLATE_NOOP("nmWellEditorSession", "The original well data is unavailable."),
|
|
|
|
|
|
QT_TRANSLATE_NOOP("nmWellEditorSession", "The well type is not supported."),
|
|
|
|
|
|
QT_TRANSLATE_NOOP("nmWellEditorSession", "Failed to create the well working copy."),
|
|
|
|
|
|
QT_TRANSLATE_NOOP("nmWellEditorSession", "The well editing session is unavailable."),
|
|
|
|
|
|
QT_TRANSLATE_NOOP("nmWellEditorSession", "Failed to create the selected well type.")
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
QString sessionText(const char* pText)
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_UNUSED(s_pSessionTranslationMarkers);
|
|
|
|
|
|
return QCoreApplication::translate("nmWellEditorSession", pText);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool isSupportedWellType(NM_WELL_MODEL eWellType)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 首期编辑器只开放已完成字段目录和轨迹交互的三种井型。
|
|
|
|
|
|
return eWellType == Vertical_Well ||
|
|
|
|
|
|
eWellType == Vertical_Fractured_Well ||
|
|
|
|
|
|
eWellType == Horizontal_Fractured_Well;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool isVerticalWellType(NM_WELL_MODEL eWellType)
|
|
|
|
|
|
{
|
|
|
|
|
|
return eWellType == Vertical_Well ||
|
|
|
|
|
|
eWellType == Vertical_Fractured_Well;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool arePerforationTypesCompatible(NM_WELL_MODEL eSourceType,
|
|
|
|
|
|
NM_WELL_MODEL eTargetType)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 直井和压裂直井的射孔MD语义一致,多段压裂水平井使用独立水平段。
|
|
|
|
|
|
return isVerticalWellType(eSourceType) &&
|
|
|
|
|
|
isVerticalWellType(eTargetType);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ensureRequiredPerforations(nmDataWellBase* pWell)
|
|
|
|
|
|
{
|
|
|
|
|
|
nmDataHorizontalFracturedWell* pHorizontal =
|
|
|
|
|
|
dynamic_cast<nmDataHorizontalFracturedWell*>(pWell);
|
|
|
|
|
|
if (pHorizontal != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
pHorizontal->ensureBasePerforation();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double wellboreTopMd(nmDataWellBase* pWell)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pWell == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 水平井的有效井筒从第一段射孔起点开始,其余井型使用井底MD。
|
|
|
|
|
|
if (dynamic_cast<nmDataHorizontalFracturedWell*>(pWell) != nullptr &&
|
|
|
|
|
|
pWell->getPerforationCount() > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
nmDataPerforation* pFirstPerforation = pWell->getPerforation(0);
|
|
|
|
|
|
if (pFirstPerforation != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return pFirstPerforation->getMdStart().getValue().toDouble();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return pWell->getBottomholeMD().getValue().toDouble();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double mapPerforationMd(double dSourceMd,
|
|
|
|
|
|
double dSourceTop,
|
|
|
|
|
|
double dSourceLength,
|
|
|
|
|
|
double dTargetTop,
|
|
|
|
|
|
double dTargetLength)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 异常旧数据无法按比例换算时只平移井筒起点,避免除零或产生非数值。
|
|
|
|
|
|
if (dSourceLength <= 0.0 || dTargetLength <= 0.0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return dSourceMd + dTargetTop - dSourceTop;
|
|
|
|
|
|
}
|
|
|
|
|
|
double dRelativePosition =
|
|
|
|
|
|
(dSourceMd - dSourceTop) / dSourceLength;
|
|
|
|
|
|
return dTargetTop + dRelativePosition * dTargetLength;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmWellEditorSession::nmWellEditorSession(
|
|
|
|
|
|
const nmWellEditContext& oContext)
|
|
|
|
|
|
: m_oContext(oContext),
|
|
|
|
|
|
m_mapWorkingWells(),
|
|
|
|
|
|
m_nCurrentWellType(static_cast<int>(Unknow_Well)),
|
|
|
|
|
|
m_bInitialized(false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmWellEditorSession::~nmWellEditorSession()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 会话独占所有缓存;已由takeModifiedWell()转移的对象不再位于映射中。
|
|
|
|
|
|
qDeleteAll(m_mapWorkingWells);
|
|
|
|
|
|
m_mapWorkingWells.clear();
|
|
|
|
|
|
m_oContext.m_pFrameworkWell = nullptr;
|
|
|
|
|
|
m_oContext.m_pOriginalWell = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmWellEditorSession::initialize(QString& sError)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_oContext.m_pOriginalWell == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
sError = sessionText("The original well data is unavailable.");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NM_WELL_MODEL eWellType =
|
|
|
|
|
|
m_oContext.m_pOriginalWell->getWellType();
|
|
|
|
|
|
if (!isSupportedWellType(eWellType))
|
|
|
|
|
|
{
|
|
|
|
|
|
sError = sessionText("The well type is not supported.");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 原始井只作为克隆源,后续界面和子窗口均操作独立工作副本。
|
|
|
|
|
|
nmDataWellBase* pWorkingWell =
|
|
|
|
|
|
m_oContext.m_pOriginalWell->clone();
|
|
|
|
|
|
if (pWorkingWell == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
sError = sessionText("Failed to create the well working copy.");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 异常旧工程可能包含零射孔水平井,进入编辑会话前恢复业务不变量。
|
|
|
|
|
|
ensureRequiredPerforations(pWorkingWell);
|
|
|
|
|
|
|
|
|
|
|
|
m_nCurrentWellType = static_cast<int>(eWellType);
|
|
|
|
|
|
m_mapWorkingWells.insert(m_nCurrentWellType, pWorkingWell);
|
|
|
|
|
|
m_bInitialized = true;
|
|
|
|
|
|
sError.clear();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataWellBase* nmWellEditorSession::currentWell() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_mapWorkingWells.value(m_nCurrentWellType, nullptr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NM_WELL_MODEL nmWellEditorSession::currentWellType() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return static_cast<NM_WELL_MODEL>(m_nCurrentWellType);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmWellEditorSession::switchWellType(NM_WELL_MODEL eWellType,
|
|
|
|
|
|
QString& sError)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_bInitialized)
|
|
|
|
|
|
{
|
|
|
|
|
|
sError = sessionText("The well editing session is unavailable.");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!isSupportedWellType(eWellType))
|
|
|
|
|
|
{
|
|
|
|
|
|
sError = sessionText("The well type is not supported.");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int nTargetType = static_cast<int>(eWellType);
|
|
|
|
|
|
if (nTargetType == m_nCurrentWellType)
|
|
|
|
|
|
{
|
|
|
|
|
|
sError.clear();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第一步:已有井型直接恢复缓存,避免往返切换丢失输入。
|
|
|
|
|
|
if (m_mapWorkingWells.contains(nTargetType))
|
|
|
|
|
|
{
|
|
|
|
|
|
m_nCurrentWellType = nTargetType;
|
|
|
|
|
|
sError.clear();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:首次进入井型时只迁移共享数据,保留目标井型默认几何。
|
|
|
|
|
|
nmDataWellBase* pNewWell = createWell(eWellType);
|
|
|
|
|
|
if (pNewWell == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
sError = sessionText("Failed to create the selected well type.");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
nmDataWellBase* pSharedSource = currentWell();
|
|
|
|
|
|
nmDataWellBase* pPerforationSource =
|
|
|
|
|
|
findCompatiblePerforationSource(eWellType);
|
|
|
|
|
|
initializeWorkingWell(pSharedSource,
|
|
|
|
|
|
pPerforationSource,
|
|
|
|
|
|
pNewWell);
|
|
|
|
|
|
m_mapWorkingWells.insert(nTargetType, pNewWell);
|
|
|
|
|
|
m_nCurrentWellType = nTargetType;
|
|
|
|
|
|
sError.clear();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWellEditorSession::setWellName(const QString& sWellName)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 井名属于所有井型共有信息,必须同步缓存以保证往返切换后一致。
|
|
|
|
|
|
QMap<int, nmDataWellBase*>::iterator oIt =
|
|
|
|
|
|
m_mapWorkingWells.begin();
|
|
|
|
|
|
for (; oIt != m_mapWorkingWells.end(); ++oIt)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (oIt.value() != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
oIt.value()->setWellName(sWellName);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWellEditorSession::setTimeDependentSkin(bool bEnabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 详情数据属于射孔,只能与当前井型工作副本保持一致。
|
|
|
|
|
|
nmDataWellBase* pWell = currentWell();
|
|
|
|
|
|
if (pWell != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
pWell->setTimeDependentSkin(bEnabled);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QStringList nmWellEditorSession::otherWellNames() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_oContext.m_listOtherWellNames;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataWellBase* nmWellEditorSession::takeModifiedWell()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_bInitialized)
|
|
|
|
|
|
{
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第一步:从映射摘除最终副本,使会话不再拥有其所有权。
|
|
|
|
|
|
nmDataWellBase* pModifiedWell =
|
|
|
|
|
|
m_mapWorkingWells.take(m_nCurrentWellType);
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:销毁未选中的井型缓存,避免临时对象泄漏到提交层。
|
|
|
|
|
|
qDeleteAll(m_mapWorkingWells);
|
|
|
|
|
|
m_mapWorkingWells.clear();
|
|
|
|
|
|
m_bInitialized = false;
|
|
|
|
|
|
return pModifiedWell;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataWellBase* nmWellEditorSession::createWell(
|
|
|
|
|
|
NM_WELL_MODEL eWellType) const
|
|
|
|
|
|
{
|
|
|
|
|
|
// 必须调用各派生类默认构造,目标井型的井长和裂缝默认值由此保留。
|
|
|
|
|
|
switch (eWellType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Vertical_Well:
|
|
|
|
|
|
return new nmDataVerticalWell();
|
|
|
|
|
|
case Vertical_Fractured_Well:
|
|
|
|
|
|
return new nmDataVerticalFracturedWell();
|
|
|
|
|
|
case Horizontal_Fractured_Well:
|
|
|
|
|
|
return new nmDataHorizontalFracturedWell();
|
|
|
|
|
|
default:
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataWellBase* nmWellEditorSession::findCompatiblePerforationSource(
|
|
|
|
|
|
NM_WELL_MODEL eTargetType) const
|
|
|
|
|
|
{
|
|
|
|
|
|
// 第一步:优先使用当前工作副本,保持连续切换时的最新输入。
|
|
|
|
|
|
nmDataWellBase* pCurrentWell = currentWell();
|
|
|
|
|
|
if (pCurrentWell != nullptr &&
|
|
|
|
|
|
arePerforationTypesCompatible(
|
|
|
|
|
|
pCurrentWell->getWellType(), eTargetType))
|
|
|
|
|
|
{
|
|
|
|
|
|
return pCurrentWell;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:切换经过水平井时,从已有垂直井缓存恢复兼容射孔来源。
|
|
|
|
|
|
QMap<int, nmDataWellBase*>::const_iterator oIt =
|
|
|
|
|
|
m_mapWorkingWells.constBegin();
|
|
|
|
|
|
for (; oIt != m_mapWorkingWells.constEnd(); ++oIt)
|
|
|
|
|
|
{
|
|
|
|
|
|
nmDataWellBase* pCandidate = oIt.value();
|
|
|
|
|
|
if (pCandidate != nullptr &&
|
|
|
|
|
|
arePerforationTypesCompatible(
|
|
|
|
|
|
pCandidate->getWellType(), eTargetType))
|
|
|
|
|
|
{
|
|
|
|
|
|
return pCandidate;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWellEditorSession::initializeWorkingWell(
|
|
|
|
|
|
nmDataWellBase* pSharedSource,
|
|
|
|
|
|
nmDataWellBase* pPerforationSource,
|
|
|
|
|
|
nmDataWellBase* pTarget) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pSharedSource == nullptr || pTarget == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第一步:白名单复制跨井型仍具有相同含义的数据。
|
|
|
|
|
|
copySharedWellData(pSharedSource, pTarget);
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:只在垂直井族内迁移射孔;跨井族保留目标构造默认值。
|
|
|
|
|
|
if (pPerforationSource != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
pTarget->setTimeDependentSkin(
|
|
|
|
|
|
pPerforationSource->isTimeDependentSkin());
|
|
|
|
|
|
migratePerforationData(pPerforationSource, pTarget);
|
|
|
|
|
|
}
|
|
|
|
|
|
ensureRequiredPerforations(pTarget);
|
|
|
|
|
|
|
|
|
|
|
|
// 第三步:目标对象完全初始化后统一重建派生几何。
|
|
|
|
|
|
rebuildDerivedGeometry(pTarget);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWellEditorSession::copySharedWellData(
|
|
|
|
|
|
nmDataWellBase* pSource,
|
|
|
|
|
|
nmDataWellBase* pTarget) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pSource == nullptr || pTarget == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 只复制跨井型语义完全一致的字段,严禁使用基类整体赋值覆盖目标默认值。
|
|
|
|
|
|
|
|
|
|
|
|
// 第一步:复制井身份、位置和通用井筒配置。
|
|
|
|
|
|
pTarget->setWellName(pSource->getWellName());
|
|
|
|
|
|
pTarget->setWellCode(pSource->getWellCode());
|
|
|
|
|
|
pTarget->setX(pSource->getX());
|
|
|
|
|
|
pTarget->setY(pSource->getY());
|
|
|
|
|
|
pTarget->setRadius(pSource->getRadius());
|
|
|
|
|
|
|
|
|
|
|
|
pTarget->setDrillFloorElevation(pSource->getDrillFloorElevation());
|
|
|
|
|
|
pTarget->setZw(pSource->getZw());
|
|
|
|
|
|
pTarget->setRateDependentSkin(pSource->getRateDependentSkin());
|
|
|
|
|
|
pTarget->setdSdQ(pSource->getdSdQ());
|
|
|
|
|
|
pTarget->setWellboreModel(pSource->getWellboreModel());
|
|
|
|
|
|
pTarget->setWellboreStorage(pSource->getWellboreStorage());
|
|
|
|
|
|
pTarget->setFinalWellboreStorage(pSource->getFinalWellboreStorage());
|
|
|
|
|
|
pTarget->setInputWellHead(pSource->getInputWellHead());
|
|
|
|
|
|
pTarget->setWellHeadX(pSource->getWellHeadX());
|
|
|
|
|
|
pTarget->setWellHeadY(pSource->getWellHeadY());
|
|
|
|
|
|
pTarget->setCInitialCFinal(pSource->getCInitialCFinal());
|
|
|
|
|
|
pTarget->setDtChangingStorage(pSource->getDtChangingStorage());
|
|
|
|
|
|
pTarget->setLeakSkin(pSource->getLeakSkin());
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:保留输入历史和已有计算结果,切换井型不应丢失曲线数据。
|
|
|
|
|
|
pTarget->setPressurePoints(pSource->getPressurePoints());
|
|
|
|
|
|
pTarget->setFlowPoints(pSource->getFlowPoints());
|
|
|
|
|
|
pTarget->setIndexF(pSource->getIndexF());
|
|
|
|
|
|
pTarget->setHistoryPressure(pSource->getHistoryPressure());
|
|
|
|
|
|
pTarget->setHistoryLogLog(pSource->getHistoryLogLog());
|
|
|
|
|
|
pTarget->setHistorySemiLog(pSource->getHistorySemiLog());
|
|
|
|
|
|
pTarget->setResultPressure(pSource->getResultPressure());
|
|
|
|
|
|
pTarget->setResultLogLog(pSource->getResultLogLog());
|
|
|
|
|
|
pTarget->setResultSemiLog(pSource->getResultSemiLog());
|
|
|
|
|
|
|
|
|
|
|
|
// 第三步:保留图元显示属性和跨井型开关。
|
|
|
|
|
|
pTarget->setPlotVisible(pSource->getPlotVisible());
|
|
|
|
|
|
pTarget->setDotStyle(pSource->getDotStyle());
|
|
|
|
|
|
pTarget->setDotColor(pSource->getDotColorR(),
|
|
|
|
|
|
pSource->getDotColorG(),
|
|
|
|
|
|
pSource->getDotColorB());
|
|
|
|
|
|
pTarget->setDotRadius(pSource->getDotRadius());
|
|
|
|
|
|
pTarget->setDotFilling(pSource->getDotFilling());
|
|
|
|
|
|
pTarget->setShowSubObjs(pSource->getShowSubObjs());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWellEditorSession::migratePerforationData(
|
|
|
|
|
|
nmDataWellBase* pSource,
|
|
|
|
|
|
nmDataWellBase* pTarget) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pSource == nullptr || pTarget == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第一步:清空目标默认射孔前保存两种井型各自的井筒坐标范围。
|
|
|
|
|
|
double dSourceTop = wellboreTopMd(pSource);
|
|
|
|
|
|
double dSourceLength = pSource->getWellLength().getValue().toDouble();
|
|
|
|
|
|
double dTargetTop = wellboreTopMd(pTarget);
|
|
|
|
|
|
double dTargetLength = pTarget->getWellLength().getValue().toDouble();
|
|
|
|
|
|
int nSourceCount = pSource->getPerforationCount();
|
|
|
|
|
|
|
|
|
|
|
|
pTarget->clearPerforations();
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:拷贝构造保留表皮、流动段、时间状态和图表位置等完整数据。
|
|
|
|
|
|
for (int nIndex = 0; nIndex < nSourceCount; ++nIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
nmDataPerforation* pSourcePerforation =
|
|
|
|
|
|
pSource->getPerforation(nIndex);
|
|
|
|
|
|
if (pSourcePerforation == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataPerforation* pTargetPerforation =
|
|
|
|
|
|
new nmDataPerforation(*pSourcePerforation);
|
|
|
|
|
|
double dTargetStart = mapPerforationMd(
|
|
|
|
|
|
pSourcePerforation->getMdStart().getValue().toDouble(),
|
|
|
|
|
|
dSourceTop,
|
|
|
|
|
|
dSourceLength,
|
|
|
|
|
|
dTargetTop,
|
|
|
|
|
|
dTargetLength);
|
|
|
|
|
|
double dTargetEnd = mapPerforationMd(
|
|
|
|
|
|
pSourcePerforation->getMdEnd().getValue().toDouble(),
|
|
|
|
|
|
dSourceTop,
|
|
|
|
|
|
dSourceLength,
|
|
|
|
|
|
dTargetTop,
|
|
|
|
|
|
dTargetLength);
|
|
|
|
|
|
pTargetPerforation->getMdStart().setValue(dTargetStart);
|
|
|
|
|
|
pTargetPerforation->getMdEnd().setValue(dTargetEnd);
|
|
|
|
|
|
pTarget->addPerforation(pTargetPerforation);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWellEditorSession::rebuildDerivedGeometry(
|
|
|
|
|
|
nmDataWellBase* pWell) const
|
|
|
|
|
|
{
|
|
|
|
|
|
// 裂缝集合是参数派生数据,必须在共享字段迁移完成后统一重建。
|
|
|
|
|
|
if (nmDataVerticalFracturedWell* pVertical =
|
|
|
|
|
|
dynamic_cast<nmDataVerticalFracturedWell*>(pWell))
|
|
|
|
|
|
{
|
|
|
|
|
|
pVertical->setFracs();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (nmDataHorizontalFracturedWell* pHorizontal =
|
|
|
|
|
|
dynamic_cast<nmDataHorizontalFracturedWell*>(pWell))
|
|
|
|
|
|
{
|
|
|
|
|
|
pHorizontal->setFracs();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|