Fishbones : Add model and visualization

This commit is contained in:
Magne Sjaastad
2017-05-05 11:21:40 +02:00
parent 2dcf3c75f5
commit 414733899e
19 changed files with 1167 additions and 7 deletions

View File

@@ -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

View 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);
}
}

View 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;
};

View File

@@ -351,4 +351,4 @@ cvf::ref< cvf::DrawableGeo> RivWellConnectionsPartMgr::createArrowGeometry(const
geo->computeNormals();
return geo;
}
}

View File

@@ -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();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -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;
};