(#399) WIP: First commit of experimental geomech WellLog extractor

Not yet enabled in any way
This commit is contained in:
Jacob Støren 2015-09-04 15:30:04 +02:00
parent ef4b0fa0d3
commit 8d57bbe77b
11 changed files with 492 additions and 143 deletions

View File

@ -109,6 +109,7 @@ list( APPEND CPP_SOURCES
list( APPEND REFERENCED_CMAKE_FILES
ReservoirDataModel/CMakeLists_files.cmake
ReservoirDataModel/CMakeLists_filesNotToUnitTest.cmake
FileInterface/CMakeLists_files.cmake
ProjectDataModel/CMakeLists_files.cmake
ModelVisualization/CMakeLists_files.cmake

View File

@ -35,8 +35,6 @@ class RigFemPartNodes
public:
std::vector<int> nodeIds;
std::vector<cvf::Vec3f> coordinates;
};
class RigFemPart : public cvf::Object

View File

@ -39,6 +39,7 @@
#include "qwt_plot_curve.h"
#include "RimWellLogPlotCollection.h"
#include "cafPdmUiTreeOrdering.h"
#include "RigGeoMechWellLogExtractor.h"
//==================================================================================================
///
@ -128,7 +129,7 @@ void RimWellLogExtractionCurve::updatePlotData()
CVF_ASSERT(wellLogCollection);
cvf::ref<RigEclipseWellLogExtractor> eclExtractor = wellLogCollection->findOrCreateExtractor(m_wellPath, eclipseCase);
//cvf::ref<RigGeoMechWellLogExtractor> geomExtractor = wellLogCollection->findOrCreateExtractor(m_wellPath, geomCase);
cvf::ref<RigGeoMechWellLogExtractor> geomExtractor = wellLogCollection->findOrCreateExtractor(m_wellPath, geomCase);
std::vector<double> filteredValues;
std::vector<double> filteredDepths;

View File

@ -27,6 +27,8 @@
#include "RimEclipseCase.h"
#include "RigEclipseWellLogExtractor.h"
#include "RimWellPathCollection.h"
#include "RimGeoMechCase.h"
#include "RigGeoMechWellLogExtractor.h"
CAF_PDM_SOURCE_INIT(RimWellLogPlotCollection, "WellLogPlotCollection");
@ -74,3 +76,29 @@ RigEclipseWellLogExtractor* RimWellLogPlotCollection::findOrCreateExtractor(RimW
return extractor.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigGeoMechWellLogExtractor* RimWellLogPlotCollection::findOrCreateExtractor(RimWellPath* wellPath, RimGeoMechCase* eclCase)
{
if (!(wellPath && eclCase && wellPath->wellPathGeometry() && eclCase->geoMechData()))
{
return NULL;
}
RigGeoMechCaseData* eclCaseData = eclCase->geoMechData();
RigWellPath* wellPathGeom = wellPath->wellPathGeometry();
for (size_t exIdx = 0; exIdx < m_geomExtractors.size(); ++exIdx)
{
if (m_geomExtractors[exIdx]->caseData() == eclCaseData && m_geomExtractors[exIdx]->wellPathData() == wellPathGeom)
{
return m_geomExtractors[exIdx].p();
}
}
cvf::ref<RigGeoMechWellLogExtractor> extractor = new RigGeoMechWellLogExtractor(eclCaseData, wellPathGeom);
m_geomExtractors.push_back(extractor.p());
return extractor.p();
}

View File

@ -26,6 +26,8 @@
class RimWellLogPlot;
class RigEclipseWellLogExtractor;
class RigGeoMechWellLogExtractor;
class RimGeoMechCase;
class RimWellPath;
class RimEclipseCase;
//==================================================================================================
@ -40,8 +42,10 @@ public:
virtual ~RimWellLogPlotCollection();
RigEclipseWellLogExtractor* findOrCreateExtractor(RimWellPath* wellPath, RimEclipseCase* eclCase);
RigGeoMechWellLogExtractor* findOrCreateExtractor(RimWellPath* wellPath, RimGeoMechCase* eclCase);
caf::PdmChildArrayField<RimWellLogPlot*> wellLogPlots;
private:
cvf::Collection<RigEclipseWellLogExtractor> m_extractors;
cvf::Collection<RigGeoMechWellLogExtractor> m_geomExtractors;
};

View File

@ -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}RigGeoMechWellLogExtractor.h
)
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RigGeoMechWellLogExtractor.cpp
)
list(APPEND CODE_HEADER_FILES
${SOURCE_GROUP_HEADER_FILES}
)
list(APPEND CODE_SOURCE_FILES
${SOURCE_GROUP_SOURCE_FILES}
)
source_group( "ReservoirDataModel2" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_filesNotToUnitTest.cmake )

View File

@ -25,150 +25,18 @@
#include "cvfBoundingBox.h"
#include "cvfGeometryTools.h"
//==================================================================================================
/// Internal class for intersection point info
//==================================================================================================
struct HexIntersectionInfo
{
public:
HexIntersectionInfo( cvf::Vec3d intersectionPoint,
bool isIntersectionEntering,
cvf::StructGridInterface::FaceType face,
size_t hexIndex)
: m_intersectionPoint(intersectionPoint),
m_isIntersectionEntering(isIntersectionEntering),
m_face(face),
m_hexIndex(hexIndex) {}
cvf::Vec3d m_intersectionPoint;
bool m_isIntersectionEntering;
cvf::StructGridInterface::FaceType m_face;
size_t m_hexIndex;
};
//--------------------------------------------------------------------------------------------------
/// Specialized Line - Hex intersection
//--------------------------------------------------------------------------------------------------
int lineHexCellIntersection(const cvf::Vec3d p1, const cvf::Vec3d p2, const cvf::Vec3d hexCorners[8], const size_t hexIndex,
std::vector<HexIntersectionInfo>* intersections )
{
CVF_ASSERT(intersections != NULL);
int intersectionCount = 0;
for (int face = 0; face < 6 ; ++face)
{
cvf::ubyte faceVertexIndices[4];
cvf::StructGridInterface::cellFaceVertexIndices(static_cast<cvf::StructGridInterface::FaceType>(face), faceVertexIndices);
cvf::Vec3d intersection;
bool isEntering = false;
cvf::Vec3d faceCenter = cvf::GeometryTools::computeFaceCenter( hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]]);
for (int i = 0; i < 4; ++i)
{
int next = i < 3 ? i+1 : 0;
int intsStatus = cvf::GeometryTools::intersectLineSegmentTriangle(p1, p2,
hexCorners[faceVertexIndices[i]], hexCorners[faceVertexIndices[next]], faceCenter,
&intersection,
&isEntering);
if (intsStatus == 1)
{
intersectionCount++;
intersections->push_back(HexIntersectionInfo(intersection, isEntering, static_cast<cvf::StructGridInterface::FaceType>(face), hexIndex));
}
}
}
return intersectionCount;
}
//==================================================================================================
/// Class used to sort the intersections along the wellpath
//==================================================================================================
struct WellPathDepthPoint
{
WellPathDepthPoint(double md, bool entering): measuredDepth(md), isEnteringCell(entering){}
double measuredDepth;
bool isEnteringCell; // As opposed to leaving.
bool operator < (const WellPathDepthPoint& other) const
{
double depthDiff = other.measuredDepth - measuredDepth;
const double tolerance = 1e-6;
if (fabs(depthDiff) < tolerance) // Equal depth
{
if (isEnteringCell == other.isEnteringCell)
{
CVF_ASSERT(false); // For now
return false; // Completely equal
}
if(!isEnteringCell) // Leaving this cell
{
return true;
}
else
{
return false;
}
}
// The depths are not equal
if (measuredDepth < other.measuredDepth)
{
return true;
}
else if (measuredDepth > other.measuredDepth)
{
return false;
}
CVF_ASSERT(false);
return false;
}
};
#include "RigWellLogExtractionTools.h"
//==================================================================================================
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigEclipseWellLogExtractor::RigEclipseWellLogExtractor(const RigCaseData* aCase, const RigWellPath* wellpath)
: m_caseData(aCase), m_wellPath(wellpath)
{
calculateIntersection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<double>& RigEclipseWellLogExtractor::measuredDepth()
{
return m_measuredDepth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<double>& RigEclipseWellLogExtractor::trueVerticalDepth()
{
return m_trueVerticalDepth;
}
//--------------------------------------------------------------------------------------------------
///
@ -206,7 +74,7 @@ void RigEclipseWellLogExtractor::calculateIntersection()
hexCorners[6] = nodeCoords[cornerIndices[6]];
hexCorners[7] = nodeCoords[cornerIndices[7]];
int intersectionCount = lineHexCellIntersection(p1, p2, hexCorners, closeCells[cIdx], &intersections);
int intersectionCount = RigHexIntersector::lineHexCellIntersection(p1, p2, hexCorners, closeCells[cIdx], &intersections);
}
// Now, with all the intersections of this piece of line, we need to
@ -292,3 +160,5 @@ std::vector<size_t> RigEclipseWellLogExtractor::findCloseCells(const cvf::Boundi
return closeCells;
}

View File

@ -43,18 +43,20 @@ class RigEclipseWellLogExtractor : public cvf::Object
public:
RigEclipseWellLogExtractor(const RigCaseData* aCase, const RigWellPath* wellpath);
const std::vector<double>& measuredDepth();
const std::vector<double>& trueVerticalDepth();
const std::vector<double>& measuredDepth(){ return m_measuredDepth; }
const std::vector<double>& trueVerticalDepth(){return m_trueVerticalDepth;}
const RigWellPath* wellPathData() { return m_wellPath.p();}
void curveData(const RigResultAccessor* resultAccessor, std::vector<double>* values );
const RigCaseData* caseData() { return m_caseData.p();}
const RigWellPath* wellPathData() { return m_wellPath.p();}
private:
protected:
void calculateIntersection();
std::vector<size_t> findCloseCells(const cvf::BoundingBox& bb);
cvf::cref<RigCaseData> m_caseData;
std::vector<double> m_measuredDepth;
std::vector<double> m_trueVerticalDepth;
@ -63,7 +65,5 @@ private:
std::vector<cvf::StructGridInterface::FaceType>
m_intersectedCellFaces;
cvf::cref<RigCaseData> m_caseData;
cvf::cref<RigWellPath> m_wellPath;
};

View File

@ -0,0 +1,210 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA
// Copyright (C) Ceetron Solutions AS
//
// 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 "RigGeoMechWellLogExtractor.h"
#include "RigFemPart.h"
#include "RigFemPartCollection.h"
#include "RigGeoMechCaseData.h"
#include "RigFemPartResultsCollection.h"
#include "RigWellLogExtractionTools.h"
#include "RigWellPath.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigGeoMechWellLogExtractor::RigGeoMechWellLogExtractor(RigGeoMechCaseData* aCase, const RigWellPath* wellpath)
:m_caseData(aCase), m_wellPath(wellpath)
{
calculateIntersection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigGeoMechWellLogExtractor::curveData(const RigFemResultAddress& resAddr, int frameIndex, std::vector<double>* values)
{
CVF_TIGHT_ASSERT(values);
values->resize(m_intersections.size());// + 1); // Plus one for the end of the wellpath stopping inside a cell
const RigFemPart* femPart = m_caseData->femParts()->part(0);
const std::vector<cvf::Vec3f>& nodeCoords = femPart->nodes().coordinates;
const std::vector<float>& resultValues = m_caseData->femPartResults()->resultValues(resAddr, 0, frameIndex);
for (size_t cpIdx = 0; cpIdx < m_intersections.size(); ++cpIdx)
{
size_t elmIdx = m_intersectedCells[cpIdx];
RigElementType elmType = femPart->elementType(elmIdx);
if (elmType != HEX8) continue;
cvf::StructGridInterface::FaceType cellFace = m_intersectedCellFaces[cpIdx];
int faceNodeCount = 0;
const int* faceLocalIndices = RigFemTypes::localElmNodeIndicesForFace(elmType, cellFace, &faceNodeCount);
const int* elmNodeIndices = femPart->connectivities(elmIdx);
cvf::Vec3d v0(nodeCoords[elmNodeIndices[faceLocalIndices[0]]]);
cvf::Vec3d v1(nodeCoords[elmNodeIndices[faceLocalIndices[1]]]);
cvf::Vec3d v2(nodeCoords[elmNodeIndices[faceLocalIndices[2]]]);
cvf::Vec3d v3(nodeCoords[elmNodeIndices[faceLocalIndices[3]]]);
size_t resIdx0 = cvf::UNDEFINED_SIZE_T;
size_t resIdx1 = cvf::UNDEFINED_SIZE_T;
size_t resIdx2 = cvf::UNDEFINED_SIZE_T;
size_t resIdx3 = cvf::UNDEFINED_SIZE_T;
if (resAddr.resultPosType == RIG_NODAL)
{
resIdx0 = elmNodeIndices[faceLocalIndices[0]];
resIdx1 = elmNodeIndices[faceLocalIndices[1]];
resIdx2 = elmNodeIndices[faceLocalIndices[2]];
resIdx3 = elmNodeIndices[faceLocalIndices[3]];
}
else
{
resIdx0 = (size_t)femPart->elementNodeResultIdx((int)elmIdx, faceLocalIndices[0]);
resIdx1 = (size_t)femPart->elementNodeResultIdx((int)elmIdx, faceLocalIndices[1]);
resIdx2 = (size_t)femPart->elementNodeResultIdx((int)elmIdx, faceLocalIndices[2]);
resIdx3 = (size_t)femPart->elementNodeResultIdx((int)elmIdx, faceLocalIndices[3]);
}
double interpolatedValue = cvf::GeometryTools::interpolateQuad(
v0, resultValues[resIdx0],
v1, resultValues[resIdx1],
v2, resultValues[resIdx2],
v3, resultValues[resIdx3],
m_intersections[cpIdx]
);
(*values)[cpIdx] = interpolatedValue;
}
// What do we do with the endpoint of the wellpath ?
// Ignore it for now ...
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigGeoMechWellLogExtractor::calculateIntersection()
{
CVF_ASSERT(m_caseData->femParts()->partCount() == 1);
const RigFemPart* femPart = m_caseData->femParts()->part(0);
const std::vector<cvf::Vec3f>& nodeCoords = femPart->nodes().coordinates;
double globalMeasuredDepth = 0; // Where do we start ? z - of first well path point ?
for (size_t wpp = 0; wpp < m_wellPath->m_wellPathPoints.size() - 1; ++wpp)
{
cvf::BoundingBox bb;
cvf::Vec3d p1 = m_wellPath->m_wellPathPoints[wpp];
cvf::Vec3d p2 = m_wellPath->m_wellPathPoints[wpp+1];
bb.add(p1);
bb.add(p2);
std::vector<size_t> closeCells = findCloseCells(bb);
std::vector<HexIntersectionInfo> intersections;
cvf::Vec3d hexCorners[8];
for (size_t cIdx = 0; cIdx < closeCells.size(); ++cIdx)
{
if (femPart->elementType(cIdx) != HEX8) continue;
const int* cornerIndices = femPart->connectivities(cIdx);
hexCorners[0] = cvf::Vec3d(nodeCoords[cornerIndices[0]]);
hexCorners[1] = cvf::Vec3d(nodeCoords[cornerIndices[1]]);
hexCorners[2] = cvf::Vec3d(nodeCoords[cornerIndices[2]]);
hexCorners[3] = cvf::Vec3d(nodeCoords[cornerIndices[3]]);
hexCorners[4] = cvf::Vec3d(nodeCoords[cornerIndices[4]]);
hexCorners[5] = cvf::Vec3d(nodeCoords[cornerIndices[5]]);
hexCorners[6] = cvf::Vec3d(nodeCoords[cornerIndices[6]]);
hexCorners[7] = cvf::Vec3d(nodeCoords[cornerIndices[7]]);
int intersectionCount = RigHexIntersector::lineHexCellIntersection(p1, p2, hexCorners, closeCells[cIdx], &intersections);
}
// Now, with all the intersections of this piece of line, we need to
// sort them in order, and set the measured depth and corresponding cell index
// map <WellPathDepthPoint, (CellIdx, intersectionPoint)>
std::map<WellPathDepthPoint, HexIntersectionInfo > sortedIntersections;
for (size_t intIdx = 0; intIdx < intersections.size(); ++intIdx)
{
double lenghtAlongLineSegment = (intersections[intIdx].m_intersectionPoint - p1).length();
double measuredDepthOfPoint = globalMeasuredDepth + lenghtAlongLineSegment;
sortedIntersections.insert(std::make_pair(WellPathDepthPoint(measuredDepthOfPoint, intersections[intIdx].m_isIntersectionEntering), intersections[intIdx]));
}
// Now populate the return arrays
std::map<WellPathDepthPoint, HexIntersectionInfo >::iterator it;
it = sortedIntersections.begin();
while (it != sortedIntersections.end())
{
m_measuredDepth.push_back(it->first.measuredDepth);
m_trueVerticalDepth.push_back(it->second.m_intersectionPoint[2]);
m_intersections.push_back(it->second.m_intersectionPoint);
m_intersectedCells.push_back(it->second.m_hexIndex);
m_intersectedCellFaces.push_back(it->second.m_face);
++it;
}
// Increment the measured depth
globalMeasuredDepth += (p2-p1).length();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<size_t> RigGeoMechWellLogExtractor::findCloseCells(const cvf::BoundingBox& bb)
{
std::vector<size_t> closeCells;
if (m_caseData->femParts()->partCount())
{
const RigFemPart* femPart = m_caseData->femParts()->part(0);
const std::vector<cvf::Vec3f>& nodeCoords = femPart->nodes().coordinates;
size_t elmCount = femPart->elementCount();
for (size_t elmIdx = 0; elmIdx < elmCount; ++elmIdx)
{
const int* elmNodeIndices = femPart->connectivities(elmIdx);
int elmNodeCount = RigFemTypes::elmentNodeCount( femPart->elementType(elmIdx));
for (int enIdx = 0; enIdx < elmNodeCount; ++enIdx)
{
if (bb.contains(cvf::Vec3d(nodeCoords[elmNodeIndices[enIdx]])))
{
closeCells.push_back(elmIdx);
break;
}
}
}
}
return closeCells;
}

View File

@ -0,0 +1,72 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA
// Copyright (C) Ceetron Solutions AS
//
// 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 "cvfObject.h"
#include "cvfMath.h"
#include "cvfVector3.h"
#include <vector>
#include "cvfStructGrid.h"
class RigWellPath;
class RigGeoMechCaseData;
class RigFemResultAddress;
namespace cvf {
class BoundingBox;
}
//==================================================================================================
///
//==================================================================================================
class RigGeoMechWellLogExtractor : public cvf::Object
{
public:
RigGeoMechWellLogExtractor(RigGeoMechCaseData* aCase, const RigWellPath* wellpath);
const std::vector<double>& measuredDepth(){ return m_measuredDepth; }
const std::vector<double>& trueVerticalDepth(){return m_trueVerticalDepth;}
const RigWellPath* wellPathData() { return m_wellPath.p();}
void curveData(const RigFemResultAddress& resAddr, int frameIndex, std::vector<double>* values );
const RigGeoMechCaseData* caseData() { return m_caseData.p();}
private:
void calculateIntersection();
std::vector<size_t> findCloseCells(const cvf::BoundingBox& bb);
cvf::ref<RigGeoMechCaseData> m_caseData;
std::vector<double> m_measuredDepth;
std::vector<double> m_trueVerticalDepth;
std::vector<cvf::Vec3d> m_intersections;
std::vector<size_t> m_intersectedCells;
std::vector<cvf::StructGridInterface::FaceType>
m_intersectedCellFaces;
cvf::cref<RigWellPath> m_wellPath;
};

View File

@ -0,0 +1,142 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA
// Copyright (C) Ceetron Solutions AS
//
// 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 "cvfBoundingBox.h"
#include "cvfGeometryTools.h"
#include "cvfStructGrid.h"
//==================================================================================================
/// Internal class for intersection point info
//==================================================================================================
struct HexIntersectionInfo
{
public:
HexIntersectionInfo( cvf::Vec3d intersectionPoint,
bool isIntersectionEntering,
cvf::StructGridInterface::FaceType face,
size_t hexIndex)
: m_intersectionPoint(intersectionPoint),
m_isIntersectionEntering(isIntersectionEntering),
m_face(face),
m_hexIndex(hexIndex) {}
cvf::Vec3d m_intersectionPoint;
bool m_isIntersectionEntering;
cvf::StructGridInterface::FaceType m_face;
size_t m_hexIndex;
};
//--------------------------------------------------------------------------------------------------
/// Specialized Line - Hex intersection
//--------------------------------------------------------------------------------------------------
struct RigHexIntersector
{
static int lineHexCellIntersection(const cvf::Vec3d p1, const cvf::Vec3d p2, const cvf::Vec3d hexCorners[8], const size_t hexIndex,
std::vector<HexIntersectionInfo>* intersections)
{
CVF_ASSERT(intersections != NULL);
int intersectionCount = 0;
for (int face = 0; face < 6 ; ++face)
{
cvf::ubyte faceVertexIndices[4];
cvf::StructGridInterface::cellFaceVertexIndices(static_cast<cvf::StructGridInterface::FaceType>(face), faceVertexIndices);
cvf::Vec3d intersection;
bool isEntering = false;
cvf::Vec3d faceCenter = cvf::GeometryTools::computeFaceCenter(hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]]);
for (int i = 0; i < 4; ++i)
{
int next = i < 3 ? i+1 : 0;
int intsStatus = cvf::GeometryTools::intersectLineSegmentTriangle(p1, p2,
hexCorners[faceVertexIndices[i]], hexCorners[faceVertexIndices[next]], faceCenter,
&intersection,
&isEntering);
if (intsStatus == 1)
{
intersectionCount++;
intersections->push_back(HexIntersectionInfo(intersection, isEntering, static_cast<cvf::StructGridInterface::FaceType>(face), hexIndex));
}
}
}
return intersectionCount;
}
};
//==================================================================================================
/// Class used to sort the intersections along the wellpath
//==================================================================================================
struct WellPathDepthPoint
{
WellPathDepthPoint(double md, bool entering): measuredDepth(md), isEnteringCell(entering){}
double measuredDepth;
bool isEnteringCell; // As opposed to leaving.
bool operator < (const WellPathDepthPoint& other) const
{
double depthDiff = other.measuredDepth - measuredDepth;
const double tolerance = 1e-6;
if (fabs(depthDiff) < tolerance) // Equal depth
{
if (isEnteringCell == other.isEnteringCell)
{
CVF_ASSERT(false); // For now
return false; // Completely equal
}
if(!isEnteringCell) // Leaving this cell
{
return true;
}
else
{
return false;
}
}
// The depths are not equal
if (measuredDepth < other.measuredDepth)
{
return true;
}
else if (measuredDepth > other.measuredDepth)
{
return false;
}
CVF_ASSERT(false);
return false;
}
};