mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-09 23:16:00 -06:00
Fishbones : Add model and visualization
This commit is contained in:
parent
2dcf3c75f5
commit
414733899e
@ -49,6 +49,7 @@ include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Summary
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Flow
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Fishbones
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ResultStatisticsCache
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ReservoirDataModel
|
||||
@ -107,6 +108,7 @@ list( APPEND REFERENCED_CMAKE_FILES
|
||||
ProjectDataModel/CMakeLists_files.cmake
|
||||
ProjectDataModel/Summary/CMakeLists_files.cmake
|
||||
ProjectDataModel/Flow/CMakeLists_files.cmake
|
||||
ProjectDataModel/Fishbones/CMakeLists_files.cmake
|
||||
|
||||
GeoMech/GeoMechVisualization/CMakeLists_files.cmake
|
||||
|
||||
@ -121,6 +123,7 @@ list( APPEND REFERENCED_CMAKE_FILES
|
||||
Commands/CrossSectionCommands/CMakeLists_files.cmake
|
||||
Commands/EclipseCommands/CMakeLists_files.cmake
|
||||
Commands/EclipseCommands/EclipseWell/CMakeLists_files.cmake
|
||||
Commands/FishbonesCommands/CMakeLists_files.cmake
|
||||
Commands/FlowCommands/CMakeLists_files.cmake
|
||||
Commands/IntersectionBoxCommands/CMakeLists_files.cmake
|
||||
Commands/OctaveScriptCommands/CMakeLists_files.cmake
|
||||
|
@ -0,0 +1,23 @@
|
||||
|
||||
# Use this workaround until we're on 2.8.3 on all platforms and can use CMAKE_CURRENT_LIST_DIR directly
|
||||
if (${CMAKE_VERSION} VERSION_GREATER "2.8.2")
|
||||
set(CEE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}/)
|
||||
endif()
|
||||
|
||||
set (SOURCE_GROUP_HEADER_FILES
|
||||
${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.h
|
||||
)
|
||||
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
${SOURCE_GROUP_HEADER_FILES}
|
||||
)
|
||||
|
||||
list(APPEND CODE_SOURCE_FILES
|
||||
${SOURCE_GROUP_SOURCE_FILES}
|
||||
)
|
||||
|
||||
source_group( "CommandFeature\\Fishbones" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake )
|
@ -0,0 +1,87 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017- 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 "RicNewFishbonesSubsFeature.h"
|
||||
|
||||
#include "RimFishbonesMultipleSubs.h"
|
||||
#include "RimWellPath.h"
|
||||
|
||||
#include "RiuMainWindow.h"
|
||||
|
||||
#include "cafSelectionManager.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
|
||||
CAF_CMD_SOURCE_INIT(RicNewFishbonesSubsFeature, "RicNewFishbonesSubsFeature");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewFishbonesSubsFeature::onActionTriggered(bool isChecked)
|
||||
{
|
||||
RimWellPath* wellPath = selectedWellPath();
|
||||
CVF_ASSERT(wellPath);
|
||||
|
||||
RimFishbonesMultipleSubs* obj = new RimFishbonesMultipleSubs;
|
||||
obj->setName(QString("Fishbones Subs (%1)").arg(wellPath->fishbonesSubs.size()));
|
||||
wellPath->fishbonesSubs.push_back(obj);
|
||||
|
||||
wellPath->updateConnectedEditors();
|
||||
RiuMainWindow::instance()->selectAsCurrentItem(obj);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellPath* RicNewFishbonesSubsFeature::selectedWellPath()
|
||||
{
|
||||
RimWellPath* wellPath = nullptr;
|
||||
|
||||
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
|
||||
|
||||
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>(pdmUiItem);
|
||||
if (objHandle)
|
||||
{
|
||||
objHandle->firstAncestorOrThisOfType(wellPath);
|
||||
}
|
||||
|
||||
return wellPath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewFishbonesSubsFeature::setupActionLook(QAction* actionToSetup)
|
||||
{
|
||||
//actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png"));
|
||||
actionToSetup->setText("New Fishbones Subs Definition");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicNewFishbonesSubsFeature::isCommandEnabled()
|
||||
{
|
||||
if (selectedWellPath())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017- 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 "cafCmdFeature.h"
|
||||
|
||||
class RimWellPath;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicNewFishbonesSubsFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
protected:
|
||||
|
||||
virtual void onActionTriggered(bool isChecked) override;
|
||||
virtual void setupActionLook(QAction* actionToSetup) override;
|
||||
virtual bool isCommandEnabled() override;
|
||||
|
||||
private:
|
||||
static RimWellPath* selectedWellPath();
|
||||
};
|
@ -25,6 +25,7 @@
|
||||
#include "RimEclipseInputProperty.h"
|
||||
#include "RimEclipsePropertyFilter.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimFishbonesMultipleSubs.h"
|
||||
#include "RimFormationNames.h"
|
||||
#include "RimFormationNamesCollection.h"
|
||||
#include "RimGeoMechPropertyFilter.h"
|
||||
@ -92,6 +93,7 @@ bool isDeletable(PdmUiItem * uiItem)
|
||||
if (dynamic_cast<RimIntersectionBox*>(uiItem)) return true;
|
||||
if (dynamic_cast<RimFormationNames*>(uiItem)) return true;
|
||||
if (dynamic_cast<RimFormationNamesCollection*>(uiItem)) return true;
|
||||
if (dynamic_cast<RimFishbonesMultipleSubs*>(uiItem)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -35,9 +35,11 @@ ${CEE_CURRENT_LIST_DIR}RivSingleCellPartGenerator.h
|
||||
${CEE_CURRENT_LIST_DIR}RivSimWellPipeSourceInfo.h
|
||||
${CEE_CURRENT_LIST_DIR}RivWellSpheresPartMgr.h
|
||||
${CEE_CURRENT_LIST_DIR}RivPartPriority.h
|
||||
${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.h
|
||||
${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.h
|
||||
${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.h
|
||||
|
||||
${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.h
|
||||
${CEE_CURRENT_LIST_DIR}RivFishbonesSubsPartMgr.h
|
||||
)
|
||||
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
@ -68,8 +70,11 @@ ${CEE_CURRENT_LIST_DIR}RivPipeQuadToSegmentMapper.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RivSingleCellPartGenerator.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RivSimWellPipeSourceInfo.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RivWellSpheresPartMgr.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.cpp
|
||||
${CEE_CURRENT_LIST_DIR}RivFishbonesSubsPartMgr.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
|
233
ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp
Normal file
233
ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017 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 "RivFishbonesSubsPartMgr.h"
|
||||
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "RimFishbonesMultipleSubs.h"
|
||||
#include "RimWellPath.h"
|
||||
|
||||
#include "RivObjectSourceInfo.h"
|
||||
#include "RivPipeGeometryGenerator.h"
|
||||
|
||||
#include "cafDisplayCoordTransform.h"
|
||||
#include "cafEffectGenerator.h"
|
||||
|
||||
#include "cvfDrawableGeo.h"
|
||||
#include "cvfModelBasicList.h"
|
||||
#include "cvfPart.h"
|
||||
#include "cvfTransform.h"
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RivFishbonesSubsPartMgr::RivFishbonesSubsPartMgr(RimFishbonesMultipleSubs* subs)
|
||||
: m_rimFishbonesSubs(subs)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RivFishbonesSubsPartMgr::~RivFishbonesSubsPartMgr()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivFishbonesSubsPartMgr::appendGeometryPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize)
|
||||
{
|
||||
clearGeometryCache();
|
||||
|
||||
if (!m_rimFishbonesSubs->isChecked()) return;
|
||||
|
||||
if (m_parts.size() == 0)
|
||||
{
|
||||
buildParts(displayCoordTransform, characteristicCellSize);
|
||||
}
|
||||
|
||||
for (auto part : m_parts)
|
||||
{
|
||||
model->addPart(part.p());
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivFishbonesSubsPartMgr::clearGeometryCache()
|
||||
{
|
||||
m_parts.clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivFishbonesSubsPartMgr::buildParts(caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize)
|
||||
{
|
||||
std::vector<double> locationOfSubs = m_rimFishbonesSubs->locationOfSubs();
|
||||
|
||||
RimWellPath* wellPath = nullptr;
|
||||
m_rimFishbonesSubs->firstAncestorOrThisOfTypeAsserted(wellPath);
|
||||
|
||||
RigWellPath* rigWellPath = wellPath->wellPathGeometry();
|
||||
|
||||
RivPipeGeometryGenerator geoGenerator;
|
||||
geoGenerator.setRadius(m_rimFishbonesSubs->tubingRadius());
|
||||
|
||||
for (size_t instanceIndex = 0; instanceIndex < locationOfSubs.size(); instanceIndex++)
|
||||
{
|
||||
double measuredDepth = locationOfSubs[instanceIndex];
|
||||
|
||||
cvf::Vec3d position = rigWellPath->interpolatedPointAlongWellPath(measuredDepth);
|
||||
|
||||
cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED;
|
||||
cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED;
|
||||
rigWellPath->twoClosestPoints(position, &p1, &p2);
|
||||
|
||||
if (!p1.isUndefined() && !p2.isUndefined())
|
||||
{
|
||||
std::vector<double> lateralLengths = m_rimFishbonesSubs->lateralLengths();
|
||||
cvf::Mat4d buildAngleRotationMatrix;
|
||||
|
||||
for (size_t i = 0; i < lateralLengths.size(); i++)
|
||||
{
|
||||
cvf::Vec3d lateralDirection;
|
||||
{
|
||||
cvf::Vec3d alongWellPath = (p2 - p1).getNormalized();
|
||||
cvf::Vec3d lateralInitialDirection = cvf::Vec3d::Z_AXIS;
|
||||
{
|
||||
double intialRotationAngle = m_rimFishbonesSubs->rotationAngle(instanceIndex);
|
||||
double lateralOffsetDegrees = 360.0 / lateralLengths.size();
|
||||
|
||||
double lateralOffsetRadians = cvf::Math::toRadians(intialRotationAngle + lateralOffsetDegrees * i);
|
||||
|
||||
cvf::Mat4d lateralOffsetMatrix = cvf::Mat4d::fromRotation(alongWellPath, lateralOffsetRadians);
|
||||
|
||||
lateralInitialDirection = lateralInitialDirection.getTransformedVector(lateralOffsetMatrix);
|
||||
}
|
||||
|
||||
cvf::Vec3d rotationAxis;
|
||||
rotationAxis.cross(alongWellPath, lateralInitialDirection);
|
||||
|
||||
double exitAngleRadians = cvf::Math::toRadians(m_rimFishbonesSubs->exitAngle());
|
||||
cvf::Mat4d lateralRotationMatrix = cvf::Mat4d::fromRotation(rotationAxis, exitAngleRadians);
|
||||
|
||||
lateralDirection = alongWellPath.getTransformedVector(lateralRotationMatrix);
|
||||
|
||||
double buildAngleRadians = cvf::Math::toRadians(m_rimFishbonesSubs->buildAngle());
|
||||
buildAngleRotationMatrix = cvf::Mat4d::fromRotation(rotationAxis, buildAngleRadians);
|
||||
}
|
||||
|
||||
std::vector<cvf::Vec3d> domainCoords;
|
||||
|
||||
// Compute coordinates along the lateral by modifying the lateral direction by the build angle for
|
||||
// every unit vector along the lateral
|
||||
{
|
||||
cvf::Vec3d accumulatedPosition = position;
|
||||
double accumulatedLength = 0.0;
|
||||
while (accumulatedLength < lateralLengths[i])
|
||||
{
|
||||
domainCoords.push_back(accumulatedPosition);
|
||||
|
||||
double delta = 1.0;
|
||||
|
||||
if (lateralLengths[i] - accumulatedLength < 1.0)
|
||||
{
|
||||
delta = lateralLengths[i] - accumulatedLength;
|
||||
}
|
||||
|
||||
accumulatedPosition += delta * lateralDirection;
|
||||
|
||||
// Modify the lateral direction by the build angle for each unit vector
|
||||
lateralDirection = lateralDirection.getTransformedVector(buildAngleRotationMatrix);
|
||||
|
||||
accumulatedLength += delta;
|
||||
}
|
||||
|
||||
// Add the last accumulated position if it is not present
|
||||
if (domainCoords.back() != accumulatedPosition)
|
||||
{
|
||||
domainCoords.push_back(accumulatedPosition);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<cvf::Vec3d> displayCoords;
|
||||
for (auto domainCoord : domainCoords)
|
||||
{
|
||||
displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(domainCoord));
|
||||
}
|
||||
|
||||
cylinderWithCenterLineParts(&m_parts, displayCoords, wellPath->wellPathColor(), wellPath->combinedScaleFactor() * characteristicCellSize * 0.5);
|
||||
|
||||
cvf::ref<RivObjectSourceInfo> objectSourceInfo = new RivObjectSourceInfo(m_rimFishbonesSubs);
|
||||
|
||||
for (auto p : m_parts)
|
||||
{
|
||||
p->setSourceInfo(objectSourceInfo.p());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivFishbonesSubsPartMgr::cylinderWithCenterLineParts(cvf::Collection<cvf::Part>* destinationParts, const std::vector<cvf::Vec3d>& centerCoords, const cvf::Color3f& color, double radius)
|
||||
{
|
||||
cvf::ref<RivPipeGeometryGenerator> geoGenerator = new RivPipeGeometryGenerator;
|
||||
geoGenerator->setRadius(radius);
|
||||
geoGenerator->setCrossSectionVertexCount(12);
|
||||
|
||||
cvf::ref<cvf::Vec3dArray> cvfCoords = new cvf::Vec3dArray(centerCoords);
|
||||
geoGenerator->setPipeCenterCoords(cvfCoords.p());
|
||||
|
||||
cvf::ref<cvf::DrawableGeo> surfaceGeo = geoGenerator->createPipeSurface();
|
||||
if (surfaceGeo.notNull())
|
||||
{
|
||||
cvf::Part* part = new cvf::Part;
|
||||
part->setDrawable(surfaceGeo.p());
|
||||
|
||||
caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(color), caf::PO_1);
|
||||
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
|
||||
|
||||
part->setEffect(eff.p());
|
||||
|
||||
destinationParts->push_back(part);
|
||||
}
|
||||
|
||||
cvf::ref<cvf::DrawableGeo> centerLineGeo = geoGenerator->createCenterLine();
|
||||
if (centerLineGeo.notNull())
|
||||
{
|
||||
cvf::Part* part = new cvf::Part;
|
||||
part->setDrawable(centerLineGeo.p());
|
||||
|
||||
caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(color), caf::PO_1);
|
||||
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
|
||||
|
||||
part->setEffect(eff.p());
|
||||
|
||||
destinationParts->push_back(part);
|
||||
}
|
||||
}
|
||||
|
67
ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h
Normal file
67
ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h
Normal file
@ -0,0 +1,67 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017 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 "cafPdmPointer.h"
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfMatrix4.h"
|
||||
#include "cvfObject.h"
|
||||
#include "cvfVector3.h"
|
||||
|
||||
#include "cvfCollection.h"
|
||||
#include "cvfColor3.h"
|
||||
|
||||
|
||||
namespace cvf
|
||||
{
|
||||
class ModelBasicList;
|
||||
class DrawableGeo;
|
||||
class Part;
|
||||
class Transform;
|
||||
}
|
||||
|
||||
namespace caf
|
||||
{
|
||||
class DisplayCoordTransform;
|
||||
}
|
||||
|
||||
class RimFishbonesMultipleSubs;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
class RivFishbonesSubsPartMgr : public cvf::Object
|
||||
{
|
||||
public:
|
||||
RivFishbonesSubsPartMgr(RimFishbonesMultipleSubs* subs);
|
||||
~RivFishbonesSubsPartMgr();
|
||||
|
||||
void appendGeometryPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize);
|
||||
void clearGeometryCache();
|
||||
|
||||
private:
|
||||
void buildParts(caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize);
|
||||
|
||||
static void cylinderWithCenterLineParts(cvf::Collection<cvf::Part>* destinationParts, const std::vector<cvf::Vec3d>& centerCoords, const cvf::Color3f& color, double radius);
|
||||
|
||||
private:
|
||||
caf::PdmPointer<RimFishbonesMultipleSubs> m_rimFishbonesSubs;
|
||||
cvf::Collection<cvf::Part> m_parts;
|
||||
};
|
@ -351,4 +351,4 @@ cvf::ref< cvf::DrawableGeo> RivWellConnectionsPartMgr::createArrowGeometry(const
|
||||
geo->computeNormals();
|
||||
|
||||
return geo;
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,11 @@
|
||||
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "RimFishbonesMultipleSubs.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPathCollection.h"
|
||||
|
||||
#include "RivPipeGeometryGenerator.h"
|
||||
#include "RivFishbonesSubsPartMgr.h"
|
||||
#include "RivPartPriority.h"
|
||||
#include "RivPipeGeometryGenerator.h"
|
||||
#include "RivWellPathSourceInfo.h"
|
||||
@ -83,6 +84,31 @@ RivWellPathPartMgr::~RivWellPathPartMgr()
|
||||
clearAllBranchData();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivWellPathPartMgr::appendFishbonesPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize)
|
||||
{
|
||||
if (!m_rimWellPath) return;
|
||||
|
||||
// This concept is taken from RivReservoirSimWellsPartMgr, and is required to be able to have
|
||||
// separate part managers for each view
|
||||
if (m_fishbonesPartMgrs.size() != m_rimWellPath->fishbonesSubs().size())
|
||||
{
|
||||
m_fishbonesPartMgrs.clear();
|
||||
|
||||
for (auto rimFishboneSubs : m_rimWellPath->fishbonesSubs())
|
||||
{
|
||||
m_fishbonesPartMgrs.push_back(new RivFishbonesSubsPartMgr(rimFishboneSubs));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto rivFishbonesPartManager : m_fishbonesPartMgrs)
|
||||
{
|
||||
rivFishbonesPartManager->appendGeometryPartsToModel(model, displayCoordTransform, characteristicCellSize);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// The pipe geometry needs to be rebuilt on scale change to keep the pipes round
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -268,6 +294,8 @@ void RivWellPathPartMgr::appendStaticGeometryPartsToModel(cvf::ModelBasicList* m
|
||||
{
|
||||
model->addPart(m_wellLabelPart.p());
|
||||
}
|
||||
|
||||
appendFishbonesPartsToModel(model, displayCoordTransform, characteristicCellSize);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -282,6 +310,16 @@ void RivWellPathPartMgr::setScaleTransform( cvf::Transform * scaleTransform )
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivWellPathPartMgr::scheduleGeometryRegen()
|
||||
{
|
||||
m_needsTransformUpdate = true;
|
||||
|
||||
m_fishbonesPartMgrs.clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "cafPdmPointer.h"
|
||||
#include "cvfBoundingBox.h"
|
||||
#include "cvfCollection.h"
|
||||
|
||||
namespace cvf
|
||||
{
|
||||
@ -40,6 +41,7 @@ namespace caf {
|
||||
class RivPipeGeometryGenerator;
|
||||
class RimProject;
|
||||
class RimWellPath;
|
||||
class RivFishbonesSubsPartMgr;
|
||||
|
||||
class RivWellPathPartMgr : public cvf::Object
|
||||
{
|
||||
@ -49,7 +51,7 @@ public:
|
||||
|
||||
void setScaleTransform(cvf::Transform * scaleTransform);
|
||||
|
||||
void scheduleGeometryRegen() { m_needsTransformUpdate = true; }//printf("R"); }
|
||||
void scheduleGeometryRegen();
|
||||
|
||||
void appendStaticGeometryPartsToModel(cvf::ModelBasicList* model, cvf::Vec3d displayModelOffset,
|
||||
double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox,
|
||||
@ -57,14 +59,17 @@ public:
|
||||
|
||||
size_t segmentIndexFromTriangleIndex(size_t triangleIndex);
|
||||
|
||||
private:
|
||||
void appendFishbonesPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize);
|
||||
void buildWellPathParts(cvf::Vec3d displayModelOffset, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox);
|
||||
void clearAllBranchData();
|
||||
|
||||
private:
|
||||
caf::PdmPointer<RimWellPath> m_rimWellPath;
|
||||
|
||||
cvf::ref<cvf::Transform> m_scaleTransform;
|
||||
bool m_needsTransformUpdate;
|
||||
|
||||
void buildWellPathParts(cvf::Vec3d displayModelOffset, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox);
|
||||
void clearAllBranchData();
|
||||
struct RivPipeBranchData
|
||||
{
|
||||
cvf::ref<RivPipeGeometryGenerator> m_pipeGeomGenerator;
|
||||
@ -80,4 +85,6 @@ private:
|
||||
cvf::ref<cvf::ScalarMapper> m_scalarMapper;
|
||||
cvf::ref<cvf::Effect> m_scalarMapperSurfaceEffect;
|
||||
cvf::ref<cvf::Effect> m_scalarMapperMeshEffect;
|
||||
|
||||
cvf::Collection<RivFishbonesSubsPartMgr> m_fishbonesPartMgrs;
|
||||
};
|
||||
|
@ -0,0 +1,23 @@
|
||||
|
||||
# Use this workaround until we're on 2.8.3 on all platforms and can use CMAKE_CURRENT_LIST_DIR directly
|
||||
if (${CMAKE_VERSION} VERSION_GREATER "2.8.2")
|
||||
set(CEE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}/)
|
||||
endif()
|
||||
|
||||
set (SOURCE_GROUP_HEADER_FILES
|
||||
${CEE_CURRENT_LIST_DIR}RimFishbonesMultipleSubs.h
|
||||
)
|
||||
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
${CEE_CURRENT_LIST_DIR}RimFishbonesMultipleSubs.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
${SOURCE_GROUP_HEADER_FILES}
|
||||
)
|
||||
|
||||
list(APPEND CODE_SOURCE_FILES
|
||||
${SOURCE_GROUP_SOURCE_FILES}
|
||||
)
|
||||
|
||||
source_group( "ProjectDataModel\\Fishbones" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake )
|
@ -0,0 +1,396 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017 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 "RimFishbonesMultipleSubs.h"
|
||||
|
||||
#include "RimProject.h"
|
||||
|
||||
#include "cafPdmUiListEditor.h"
|
||||
|
||||
#include "cvfAssert.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
CAF_PDM_SOURCE_INIT(RimFishbonesMultipleSubs, "FishbonesMultipleSubs");
|
||||
|
||||
namespace caf {
|
||||
template<>
|
||||
void AppEnum<RimFishbonesMultipleSubs::LocationType>::setUp()
|
||||
{
|
||||
addItem(RimFishbonesMultipleSubs::FB_SUB_COUNT_END, "FB_SUB_COUNT", "Start/End/Count");
|
||||
addItem(RimFishbonesMultipleSubs::FB_SUB_SPACING_END, "FB_SUB_SPACING", "Start/End/Spacing");
|
||||
addItem(RimFishbonesMultipleSubs::FB_SUB_USER_DEFINED, "FB_SUB_CUSTOM", "User Specification");
|
||||
setDefault(RimFishbonesMultipleSubs::FB_SUB_USER_DEFINED);
|
||||
}
|
||||
|
||||
template<>
|
||||
void AppEnum<RimFishbonesMultipleSubs::LateralsOrientationType>::setUp()
|
||||
{
|
||||
addItem(RimFishbonesMultipleSubs::FB_LATERAL_ORIENTATION_FIXED, "FB_LATERAL_ORIENTATION_FIXED", "Fixed Angle");
|
||||
addItem(RimFishbonesMultipleSubs::FB_LATERAL_ORIENTATION_RANDOM, "FB_LATERAL_ORIENTATION_RANDOM", "Random Angle");
|
||||
setDefault(RimFishbonesMultipleSubs::FB_LATERAL_ORIENTATION_RANDOM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimFishbonesMultipleSubs::RimFishbonesMultipleSubs()
|
||||
{
|
||||
CAF_PDM_InitObject("FishbonesMultipleSubs", ":/Default.png", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_lateralCountPerSub, "LateralCountPerSub", size_t(3), "Count Per Sub", "", "", "");
|
||||
CAF_PDM_InitField(&m_lateralLength, "LateralLength", QString("12.0"), "Length(s) [m]", "", "Specify multiple length values if the sub lengths differ", "");
|
||||
|
||||
CAF_PDM_InitField(&m_lateralExitAngle, "LateralExitAngle", 35.0, "Exit Angle [deg]", "", "", "");
|
||||
CAF_PDM_InitField(&m_lateralBuildAngle, "LateralBuildAngle", 5.0, "Build Angle [deg/m]", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_lateralHoleRadius, "LateralHoleRadius", 12.0, "Hole Radius [mm]", "", "", "");
|
||||
CAF_PDM_InitField(&m_lateralTubingRadius, "LateralTubingRadius", 8.0, "Tubing Radius [mm]", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_lateralOpenHoleRoghnessFactor, "LateralOpenHoleRoghnessFactor", 0.001, "Open Hole Roghness Factor [m]", "", "", "");
|
||||
CAF_PDM_InitField(&m_lateralTubingRoghnessFactor, "LateralTubingRoghnessFactor", 1e-5, "Tubing Roghness Factor [m]", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_lateralLengthFraction, "LateralLengthFraction", 100.0, "Length Fraction [0..1]", "", "", "");
|
||||
CAF_PDM_InitField(&m_lateralInstallFraction, "LateralInstallFraction", 100.0, "Install Fraction [0..1]", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_icdCount, "IcdCount", size_t(2), "ICD Count", "", "", "");
|
||||
CAF_PDM_InitField(&m_icdOrificeRadius, "IcdOrificeRadius", 8.0, "ICD Orifice Radius [mm]", "", "", "");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_locationOfSubs, "LocationOfSubs", "Measured Depths [m]", "", "", "");
|
||||
m_locationOfSubs.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
|
||||
|
||||
CAF_PDM_InitField(&m_subsLocationMode, "SubsLocationMode", caf::AppEnum<LocationType>(FB_SUB_USER_DEFINED), "Location Defined By", "", "", "");
|
||||
CAF_PDM_InitField(&m_rangeStart, "RangeStart", 100.0, "Start [m]", "", "", "");
|
||||
CAF_PDM_InitField(&m_rangeEnd, "RangeEnd", 250.0, "End [m]", "", "", "");
|
||||
CAF_PDM_InitField(&m_rangeSubSpacing, "RangeSubSpacing", 40.0, "Spacing [m]", "", "", "");
|
||||
CAF_PDM_InitField(&m_rangeSubCount, "RangeSubCount", size_t(25), "Count", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_subsOrientationMode, "SubsOrientationMode", caf::AppEnum<LateralsOrientationType>(FB_LATERAL_ORIENTATION_RANDOM), "Orientation", "", "", "");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_installationRotationAngles, "InstallationRotationAngles", "Installation Rotation Angles [deg]", "", "", "");
|
||||
m_installationRotationAngles.uiCapability()->setUiHidden(true);
|
||||
CAF_PDM_InitField(&m_fixedInstallationRotationAngle, "FixedInstallationRotationAngle", 0.0, " Fixed Angle [deg]", "", "", "");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimFishbonesMultipleSubs::~RimFishbonesMultipleSubs()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFishbonesMultipleSubs::locationOfSubs() const
|
||||
{
|
||||
return m_locationOfSubs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFishbonesMultipleSubs::rotationAngle(size_t index) const
|
||||
{
|
||||
if (m_subsOrientationMode == FB_LATERAL_ORIENTATION_FIXED)
|
||||
{
|
||||
return m_fixedInstallationRotationAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
CVF_ASSERT(index < m_installationRotationAngles().size());
|
||||
|
||||
return m_installationRotationAngles()[index];
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFishbonesMultipleSubs::exitAngle() const
|
||||
{
|
||||
return m_lateralExitAngle;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFishbonesMultipleSubs::buildAngle() const
|
||||
{
|
||||
return m_lateralBuildAngle;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFishbonesMultipleSubs::tubingRadius() const
|
||||
{
|
||||
return m_lateralTubingRadius;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFishbonesMultipleSubs::lateralCountPerSub() const
|
||||
{
|
||||
return m_lateralCountPerSub;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFishbonesMultipleSubs::lateralLengths() const
|
||||
{
|
||||
QStringList items = m_lateralLength().split(' ');
|
||||
double currentLength = 0.0;
|
||||
|
||||
std::vector<double> lengths;
|
||||
for (int i = 0; i < static_cast<int>(m_lateralCountPerSub); i++)
|
||||
{
|
||||
if (i < items.size())
|
||||
{
|
||||
bool conversionOk = false;
|
||||
double candidateValue = items[i].toDouble(&conversionOk);
|
||||
if (conversionOk)
|
||||
{
|
||||
currentLength = candidateValue;
|
||||
}
|
||||
}
|
||||
|
||||
lengths.push_back(currentLength);
|
||||
}
|
||||
|
||||
return lengths;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFishbonesMultipleSubs::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
|
||||
{
|
||||
bool recomputeLocations = false;
|
||||
|
||||
if (changedField == &m_subsLocationMode)
|
||||
{
|
||||
if (m_subsLocationMode == FB_SUB_COUNT_END || m_subsLocationMode == FB_SUB_SPACING_END)
|
||||
{
|
||||
recomputeLocations = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changedField == &m_rangeStart ||
|
||||
changedField == &m_rangeEnd ||
|
||||
changedField == &m_rangeSubCount ||
|
||||
changedField == &m_rangeSubSpacing)
|
||||
{
|
||||
recomputeLocations = true;
|
||||
}
|
||||
|
||||
if (recomputeLocations)
|
||||
{
|
||||
if (m_subsLocationMode == FB_SUB_COUNT_END)
|
||||
{
|
||||
size_t divisor = 1;
|
||||
if (m_rangeSubCount > 2) divisor = m_rangeSubCount - 1;
|
||||
|
||||
m_rangeSubSpacing = fabs(m_rangeStart - m_rangeEnd) / divisor;
|
||||
}
|
||||
else if (m_subsLocationMode == FB_SUB_SPACING_END)
|
||||
{
|
||||
m_rangeSubCount = (fabs(m_rangeStart - m_rangeEnd) / m_rangeSubSpacing) + 1;
|
||||
|
||||
if (m_rangeSubCount < 1)
|
||||
{
|
||||
m_rangeSubCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_subsLocationMode == FB_SUB_COUNT_END || m_subsLocationMode == FB_SUB_SPACING_END)
|
||||
{
|
||||
std::vector<double> measuredDepths = locationsFromStartSpacingAndCount(m_rangeStart, m_rangeSubSpacing, m_rangeSubCount);
|
||||
m_locationOfSubs = measuredDepths;
|
||||
}
|
||||
}
|
||||
|
||||
if (recomputeLocations ||
|
||||
changedField == &m_locationOfSubs ||
|
||||
changedField == &m_subsOrientationMode)
|
||||
{
|
||||
m_installationRotationAngles.v().clear();
|
||||
|
||||
recomputeIntallationRotationAngles();
|
||||
}
|
||||
|
||||
RimProject* proj;
|
||||
this->firstAncestorOrThisOfTypeAsserted(proj);
|
||||
proj->createDisplayModelAndRedrawAllViews();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFishbonesMultipleSubs::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
|
||||
{
|
||||
uiOrdering.add(&m_name); // From RimNamedObject
|
||||
|
||||
{
|
||||
caf::PdmUiGroup* group = uiOrdering.addNewGroup("Location");
|
||||
|
||||
group->add(&m_subsLocationMode);
|
||||
if (m_subsLocationMode() != FB_SUB_USER_DEFINED)
|
||||
{
|
||||
group->add(&m_rangeStart);
|
||||
group->add(&m_rangeEnd);
|
||||
|
||||
if (m_subsLocationMode() == FB_SUB_COUNT_END)
|
||||
{
|
||||
group->add(&m_rangeSubCount);
|
||||
group->add(&m_rangeSubSpacing);
|
||||
}
|
||||
else if (m_subsLocationMode() == FB_SUB_SPACING_END)
|
||||
{
|
||||
group->add(&m_rangeSubSpacing);
|
||||
group->add(&m_rangeSubCount);
|
||||
}
|
||||
}
|
||||
|
||||
group->add(&m_locationOfSubs);
|
||||
}
|
||||
|
||||
{
|
||||
caf::PdmUiGroup* group = uiOrdering.addNewGroup("Lateral Configuration");
|
||||
|
||||
group->add(&m_lateralCountPerSub);
|
||||
group->add(&m_lateralLength);
|
||||
|
||||
group->add(&m_lateralExitAngle);
|
||||
group->add(&m_lateralBuildAngle);
|
||||
|
||||
group->add(&m_subsOrientationMode);
|
||||
if (m_subsOrientationMode == FB_LATERAL_ORIENTATION_FIXED)
|
||||
{
|
||||
group->add(&m_fixedInstallationRotationAngle);
|
||||
}
|
||||
|
||||
caf::PdmUiGroup* successGroup = group->addNewGroup("Installation Success Factors");
|
||||
successGroup->add(&m_lateralLengthFraction);
|
||||
successGroup->add(&m_lateralInstallFraction);
|
||||
|
||||
caf::PdmUiGroup* mswGroup = group->addNewGroup("Multi Segment Wells");
|
||||
mswGroup->setCollapsedByDefault(true);
|
||||
mswGroup->add(&m_lateralHoleRadius);
|
||||
mswGroup->add(&m_lateralTubingRadius);
|
||||
mswGroup->add(&m_lateralOpenHoleRoghnessFactor);
|
||||
mswGroup->add(&m_lateralTubingRoghnessFactor);
|
||||
mswGroup->add(&m_icdCount);
|
||||
mswGroup->add(&m_icdOrificeRadius);
|
||||
}
|
||||
|
||||
// Visibility
|
||||
|
||||
if (m_subsLocationMode == FB_SUB_USER_DEFINED)
|
||||
{
|
||||
m_locationOfSubs.uiCapability()->setUiReadOnly(false);
|
||||
|
||||
m_rangeSubSpacing.uiCapability()->setUiReadOnly(true);
|
||||
m_rangeSubCount.uiCapability()->setUiReadOnly(true);
|
||||
m_rangeStart.uiCapability()->setUiReadOnly(true);
|
||||
m_rangeEnd.uiCapability()->setUiReadOnly(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_locationOfSubs.uiCapability()->setUiReadOnly(true);
|
||||
|
||||
m_rangeSubSpacing.uiCapability()->setUiReadOnly(false);
|
||||
m_rangeSubCount.uiCapability()->setUiReadOnly(false);
|
||||
m_rangeStart.uiCapability()->setUiReadOnly(false);
|
||||
m_rangeEnd.uiCapability()->setUiReadOnly(false);
|
||||
|
||||
if (m_subsLocationMode == FB_SUB_COUNT_END)
|
||||
{
|
||||
m_rangeSubSpacing.uiCapability()->setUiReadOnly(true);
|
||||
m_rangeSubCount.uiCapability()->setUiReadOnly(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rangeSubSpacing.uiCapability()->setUiReadOnly(false);
|
||||
m_rangeSubCount.uiCapability()->setUiReadOnly(true);
|
||||
}
|
||||
}
|
||||
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFishbonesMultipleSubs::initAfterRead()
|
||||
{
|
||||
if (m_locationOfSubs().size() != m_installationRotationAngles().size())
|
||||
{
|
||||
recomputeIntallationRotationAngles();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFishbonesMultipleSubs::recomputeIntallationRotationAngles()
|
||||
{
|
||||
std::vector<double> vals;
|
||||
|
||||
for (size_t i = 0; i < m_locationOfSubs().size(); i++)
|
||||
{
|
||||
vals.push_back(RimFishbonesMultipleSubs::randomValue(0, 360));
|
||||
}
|
||||
|
||||
m_installationRotationAngles = vals;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFishbonesMultipleSubs::locationsFromStartSpacingAndCount(double start, double spacing, size_t count)
|
||||
{
|
||||
std::vector<double> measuredDepths;
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
measuredDepths.push_back(start + spacing * i);
|
||||
}
|
||||
|
||||
return measuredDepths;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RimFishbonesMultipleSubs::randomValue(int min, int max)
|
||||
{
|
||||
int range = abs(max - min);
|
||||
int random_integer = min + int(range*rand() / (RAND_MAX + 1.0));
|
||||
|
||||
return random_integer;
|
||||
}
|
||||
|
@ -0,0 +1,106 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017 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 "RimCheckableNamedObject.h"
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimFishbonesMultipleSubs : public RimCheckableNamedObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum LocationType
|
||||
{
|
||||
FB_SUB_COUNT_END,
|
||||
FB_SUB_SPACING_END,
|
||||
FB_SUB_USER_DEFINED
|
||||
};
|
||||
|
||||
enum LateralsOrientationType
|
||||
{
|
||||
FB_LATERAL_ORIENTATION_FIXED,
|
||||
FB_LATERAL_ORIENTATION_RANDOM
|
||||
};
|
||||
|
||||
public:
|
||||
RimFishbonesMultipleSubs();
|
||||
virtual ~RimFishbonesMultipleSubs();
|
||||
|
||||
std::vector<double> locationOfSubs() const;
|
||||
|
||||
double rotationAngle(size_t index) const;
|
||||
double exitAngle() const;
|
||||
double buildAngle() const;
|
||||
|
||||
double tubingRadius() const;
|
||||
double lateralCountPerSub() const;
|
||||
std::vector<double> lateralLengths() const;
|
||||
|
||||
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
|
||||
|
||||
protected:
|
||||
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
|
||||
virtual void initAfterRead() override;
|
||||
|
||||
private:
|
||||
void recomputeIntallationRotationAngles();
|
||||
|
||||
static std::vector<double> locationsFromStartSpacingAndCount(double start, double spacing, size_t count);
|
||||
static int randomValue(int min, int max);
|
||||
|
||||
private:
|
||||
caf::PdmField<size_t> m_lateralCountPerSub;
|
||||
caf::PdmField<QString> m_lateralLength;
|
||||
|
||||
caf::PdmField<double> m_lateralExitAngle;
|
||||
caf::PdmField<double> m_lateralBuildAngle;
|
||||
|
||||
caf::PdmField<double> m_lateralHoleRadius;
|
||||
caf::PdmField<double> m_lateralTubingRadius;
|
||||
|
||||
caf::PdmField<double> m_lateralOpenHoleRoghnessFactor;
|
||||
caf::PdmField<double> m_lateralTubingRoghnessFactor;
|
||||
|
||||
caf::PdmField<double> m_lateralLengthFraction;
|
||||
caf::PdmField<double> m_lateralInstallFraction;
|
||||
|
||||
caf::PdmField<size_t> m_icdCount;
|
||||
caf::PdmField<double> m_icdOrificeRadius;
|
||||
|
||||
caf::PdmField<caf::AppEnum<LocationType> > m_subsLocationMode;
|
||||
caf::PdmField<double> m_rangeStart;
|
||||
caf::PdmField<double> m_rangeEnd;
|
||||
caf::PdmField<double> m_rangeSubSpacing;
|
||||
caf::PdmField<size_t> m_rangeSubCount;
|
||||
|
||||
caf::PdmField<caf::AppEnum<LateralsOrientationType> > m_subsOrientationMode;
|
||||
|
||||
|
||||
caf::PdmField<std::vector<double>> m_locationOfSubs; // Given in measured depth
|
||||
|
||||
caf::PdmField<std::vector<double>> m_installationRotationAngles;
|
||||
caf::PdmField<double> m_fixedInstallationRotationAngle;
|
||||
|
||||
};
|
@ -394,6 +394,8 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
|
||||
commandIds << "RicShowTotalAllocationDataFeature";
|
||||
|
||||
commandIds << "RicSummaryCurveSwitchAxisFeature";
|
||||
|
||||
commandIds << "RicNewFishbonesSubsFeature";
|
||||
|
||||
// Work in progress -- End
|
||||
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include "RimWellLogPlotCollection.h"
|
||||
#include "RimWellPathCollection.h"
|
||||
|
||||
#include "RimFishbonesMultipleSubs.h"
|
||||
|
||||
#include "RiuMainWindow.h"
|
||||
|
||||
#include "RivWellPathPartMgr.h"
|
||||
@ -101,6 +103,9 @@ RimWellPath::RimWellPath()
|
||||
CAF_PDM_InitFieldNoDefault(&m_wellLogFile, "WellLogFile", "Well Log File", "", "", "");
|
||||
m_wellLogFile.uiCapability()->setUiHidden(true);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&fishbonesSubs, "FishbonesSubs", "fishbonesSubs", "", "", "");
|
||||
fishbonesSubs.uiCapability()->setUiHidden(true);
|
||||
|
||||
m_wellPath = NULL;
|
||||
}
|
||||
|
||||
@ -421,6 +426,17 @@ void RimWellPath::updateFilePathsFromProjectPath(const QString& newProjectPath,
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellPath::combinedScaleFactor() const
|
||||
{
|
||||
RimWellPathCollection* wellPathColl = nullptr;
|
||||
this->firstAncestorOrThisOfTypeAsserted(wellPathColl);
|
||||
|
||||
return this->wellPathRadiusScaleFactor() * wellPathColl->wellPathRadiusScaleFactor();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -29,6 +29,7 @@
|
||||
// Include to make Pdm work for cvf::Color
|
||||
#include "cafPdmFieldCvfColor.h"
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cvfObject.h"
|
||||
|
||||
class RifWellPathAsciiFileReader;
|
||||
@ -37,6 +38,8 @@ class RimProject;
|
||||
class RimWellLogFile;
|
||||
class RivWellPathPartMgr;
|
||||
|
||||
class RimFishbonesMultipleSubs;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
@ -70,12 +73,14 @@ public:
|
||||
caf::PdmChildField<RimWellLogFile*> m_wellLogFile;
|
||||
|
||||
RigWellPath* wellPathGeometry();
|
||||
caf::PdmChildArrayField<RimFishbonesMultipleSubs*> fishbonesSubs;
|
||||
|
||||
RivWellPathPartMgr* partMgr();
|
||||
|
||||
bool readWellPathFile(QString * errorMessage, RifWellPathAsciiFileReader* asciiReader);
|
||||
void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath);
|
||||
|
||||
|
||||
double combinedScaleFactor() const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "cvfGeometryTools.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -52,3 +54,106 @@ double RigWellPath::datumElevation() const
|
||||
return m_datumElevation;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::Vec3d RigWellPath::interpolatedPointAlongWellPath(double measuredDepth)
|
||||
{
|
||||
cvf::Vec3d wellPathPoint = cvf::Vec3d::ZERO;
|
||||
|
||||
size_t i = 0;
|
||||
while (i < m_measuredDepths.size() && m_measuredDepths.at(i) < measuredDepth )
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
if (m_measuredDepths.size() > i)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
//For measuredDepth same or lower than first point, use this first point
|
||||
wellPathPoint = m_wellPathPoints.at(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Do interpolation
|
||||
double stepsize = (measuredDepth - m_measuredDepths.at(i-1)) /
|
||||
(m_measuredDepths.at(i) - m_measuredDepths.at(i - 1));
|
||||
wellPathPoint = m_wellPathPoints.at(i - 1) + stepsize * (m_wellPathPoints.at(i) - m_wellPathPoints.at(i-1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Use endpoint if measuredDepth same or higher than last point
|
||||
wellPathPoint = m_wellPathPoints.at(i-1);
|
||||
}
|
||||
|
||||
|
||||
return wellPathPoint;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigWellPath::wellPathAzimuthAngle(const cvf::Vec3d& position) const
|
||||
{
|
||||
double azimuthAngle = 0.0;
|
||||
|
||||
cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED;
|
||||
cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED;
|
||||
|
||||
twoClosestPoints(position, &p1, &p2);
|
||||
if (!p1.isUndefined() && !p2.isUndefined())
|
||||
{
|
||||
cvf::Vec3d direction = p1 - p2;
|
||||
|
||||
if (abs(direction.x()) > 1e-5)
|
||||
{
|
||||
double atanValue = direction.y() / direction.x();
|
||||
azimuthAngle = atan(atanValue);
|
||||
azimuthAngle = cvf::Math::toDegrees(azimuthAngle);
|
||||
azimuthAngle = -azimuthAngle;
|
||||
}
|
||||
}
|
||||
|
||||
return azimuthAngle;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigWellPath::twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2) const
|
||||
{
|
||||
CVF_ASSERT(p1 && p2);
|
||||
|
||||
size_t closestIndex = cvf::UNDEFINED_SIZE_T;
|
||||
double closestDistance = cvf::UNDEFINED_DOUBLE;
|
||||
|
||||
for (size_t i = 1; i < m_wellPathPoints.size(); i++)
|
||||
{
|
||||
cvf::Vec3d p1 = m_wellPathPoints[i - 1];
|
||||
cvf::Vec3d p2 = m_wellPathPoints[i - 0];
|
||||
|
||||
double candidateDistance = cvf::GeometryTools::linePointSquareDist(p1, p2, position);
|
||||
if (candidateDistance < closestDistance)
|
||||
{
|
||||
closestDistance = candidateDistance;
|
||||
closestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (closestIndex != cvf::UNDEFINED_DOUBLE)
|
||||
{
|
||||
if (closestIndex > 0)
|
||||
{
|
||||
*p1 = m_wellPathPoints[closestIndex - 1];
|
||||
*p2 = m_wellPathPoints[closestIndex - 0];
|
||||
}
|
||||
else
|
||||
{
|
||||
*p1 = m_wellPathPoints[closestIndex + 1];
|
||||
*p2 = m_wellPathPoints[closestIndex + 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,9 @@ public:
|
||||
void setDatumElevation(double value);
|
||||
bool hasDatumElevation() const;
|
||||
double datumElevation() const;
|
||||
cvf::Vec3d interpolatedPointAlongWellPath(double measuredDepth);
|
||||
double wellPathAzimuthAngle(const cvf::Vec3d& position) const;
|
||||
void twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2) const;
|
||||
|
||||
private:
|
||||
bool m_hasDatumElevation;
|
||||
|
Loading…
Reference in New Issue
Block a user