mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Merge pull request #5351 from OPM/feature-reservoir-surface-results
Feature reservoir surface results
This commit is contained in:
commit
1095165a64
@ -100,8 +100,6 @@ Rim3dView* RicNewViewFeature::createReservoirView( RimEclipseCase* eclipseCase,
|
||||
insertedView = geomCase->createAndAddReservoirView();
|
||||
}
|
||||
|
||||
insertedView->updateSurfacesInViewTreeItems();
|
||||
|
||||
// Must be run before buildViewItems, as wells are created in this function
|
||||
insertedView->loadDataAndUpdate();
|
||||
|
||||
|
@ -190,21 +190,27 @@ void RivIntersectionResultsColoringTools::calculateNodeOrElementNodeBasedGeoMech
|
||||
#pragma omp parallel for schedule( dynamic )
|
||||
for ( int triangleVxIdx = 0; triangleVxIdx < vxCount; ++triangleVxIdx )
|
||||
{
|
||||
float resValue = 0;
|
||||
int weightCount = vertexWeights[triangleVxIdx].size();
|
||||
for ( int wIdx = 0; wIdx < weightCount; ++wIdx )
|
||||
{
|
||||
size_t resIdx;
|
||||
if ( isElementNodalResult )
|
||||
{
|
||||
resIdx = vertexWeights[triangleVxIdx].vxId( wIdx );
|
||||
}
|
||||
else
|
||||
{
|
||||
resIdx = femPart->nodeIdxFromElementNodeResultIdx( vertexWeights[triangleVxIdx].vxId( wIdx ) );
|
||||
}
|
||||
float resValue = HUGE_VAL;
|
||||
|
||||
resValue += resultValues[resIdx] * vertexWeights[triangleVxIdx].weight( wIdx );
|
||||
int weightCount = vertexWeights[triangleVxIdx].size();
|
||||
if ( weightCount )
|
||||
{
|
||||
resValue = 0;
|
||||
|
||||
for ( int wIdx = 0; wIdx < weightCount; ++wIdx )
|
||||
{
|
||||
size_t resIdx;
|
||||
if ( isElementNodalResult )
|
||||
{
|
||||
resIdx = vertexWeights[triangleVxIdx].vxId( wIdx );
|
||||
}
|
||||
else
|
||||
{
|
||||
resIdx = femPart->nodeIdxFromElementNodeResultIdx( vertexWeights[triangleVxIdx].vxId( wIdx ) );
|
||||
}
|
||||
|
||||
resValue += resultValues[resIdx] * vertexWeights[triangleVxIdx].weight( wIdx );
|
||||
}
|
||||
}
|
||||
|
||||
if ( resValue == HUGE_VAL || resValue != resValue ) // a != a is true for NAN's
|
||||
@ -590,8 +596,8 @@ void RivExtrudedCurveIntersectionPartMgr::createExtrusionDirParts( bool useBuffe
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivExtrudedCurveIntersectionPartMgr::appendNativeIntersectionFacesToModel( cvf::ModelBasicList* model,
|
||||
cvf::Transform* scaleTransform )
|
||||
void RivExtrudedCurveIntersectionPartMgr::appendIntersectionFacesToModel( cvf::ModelBasicList* model,
|
||||
cvf::Transform* scaleTransform )
|
||||
{
|
||||
if ( m_intersectionFaces.isNull() )
|
||||
{
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
const cvf::ScalarMapper* explicitScalarColorMapper,
|
||||
const RivTernaryScalarMapper* explicitTernaryColorMapper );
|
||||
|
||||
void appendNativeIntersectionFacesToModel( cvf::ModelBasicList* model, cvf::Transform* scaleTransform );
|
||||
void appendIntersectionFacesToModel( cvf::ModelBasicList* model, cvf::Transform* scaleTransform );
|
||||
void appendMeshLinePartsToModel( cvf::ModelBasicList* model, cvf::Transform* scaleTransform );
|
||||
void appendPolylinePartsToModel( Rim3dView& view, cvf::ModelBasicList* model, cvf::Transform* scaleTransform );
|
||||
|
||||
|
@ -123,7 +123,7 @@ public:
|
||||
|
||||
Where the k's are normalized distances along the edge, from the edge start vertex .
|
||||
|
||||
This is the interpolation sceme:
|
||||
This is the interpolation scheme:
|
||||
|
||||
v = (1 - k )* v1 + k *v2;
|
||||
|
||||
@ -205,6 +205,13 @@ public:
|
||||
m_weights[1] = ( (float)( normDistFromE1V1 ) );
|
||||
}
|
||||
|
||||
explicit RivIntersectionVertexWeights( const std::array<size_t, 8> vxIds, const std::array<double, 8> explicitWeights )
|
||||
: m_count( 8 )
|
||||
, m_vxIds( vxIds )
|
||||
{
|
||||
std::copy( explicitWeights.begin(), explicitWeights.end(), m_weights.begin() );
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
return m_count;
|
||||
|
@ -1,10 +1,14 @@
|
||||
|
||||
set (SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivSurfacePartMgr.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivSurfaceIntersectionGeometryGenerator.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivReservoirSurfaceIntersectionSourceInfo.h
|
||||
)
|
||||
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivSurfacePartMgr.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivSurfaceIntersectionGeometryGenerator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RivReservoirSurfaceIntersectionSourceInfo.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
@ -16,3 +20,4 @@ ${SOURCE_GROUP_SOURCE_FILES}
|
||||
)
|
||||
|
||||
source_group( "ModelVisualization\\Surfaces" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake )
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RivReservoirSurfaceIntersectionSourceInfo.h"
|
||||
|
||||
#include "RivSurfaceIntersectionGeometryGenerator.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RivReservoirSurfaceIntersectionSourceInfo::RivReservoirSurfaceIntersectionSourceInfo(
|
||||
RivSurfaceIntersectionGeometryGenerator* geometryGenerator )
|
||||
: m_intersectionGeometryGenerator( geometryGenerator )
|
||||
{
|
||||
CVF_ASSERT( m_intersectionGeometryGenerator.notNull() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<size_t>& RivReservoirSurfaceIntersectionSourceInfo::triangleToCellIndex() const
|
||||
{
|
||||
CVF_ASSERT( m_intersectionGeometryGenerator.notNull() );
|
||||
|
||||
return m_intersectionGeometryGenerator->triangleToCellIndex();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::array<cvf::Vec3f, 3> RivReservoirSurfaceIntersectionSourceInfo::triangle( int triangleIdx ) const
|
||||
{
|
||||
std::array<cvf::Vec3f, 3> tri;
|
||||
tri[0] = ( *m_intersectionGeometryGenerator->triangleVxes() )[triangleIdx * 3];
|
||||
tri[1] = ( *m_intersectionGeometryGenerator->triangleVxes() )[triangleIdx * 3 + 1];
|
||||
tri[2] = ( *m_intersectionGeometryGenerator->triangleVxes() )[triangleIdx * 3 + 2];
|
||||
|
||||
return tri;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimSurfaceInView* RivReservoirSurfaceIntersectionSourceInfo::intersection() const
|
||||
{
|
||||
return m_intersectionGeometryGenerator->intersection();
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "cvfArray.h"
|
||||
#include "cvfObject.h"
|
||||
#include <array>
|
||||
|
||||
class RivSurfaceIntersectionGeometryGenerator;
|
||||
class RimSurfaceInView;
|
||||
|
||||
class RivReservoirSurfaceIntersectionSourceInfo : public cvf::Object
|
||||
{
|
||||
public:
|
||||
explicit RivReservoirSurfaceIntersectionSourceInfo( RivSurfaceIntersectionGeometryGenerator* geometryGenerator );
|
||||
|
||||
const std::vector<size_t>& triangleToCellIndex() const;
|
||||
std::array<cvf::Vec3f, 3> triangle( int triangleIdx ) const;
|
||||
RimSurfaceInView* intersection() const;
|
||||
|
||||
private:
|
||||
cvf::cref<RivSurfaceIntersectionGeometryGenerator> m_intersectionGeometryGenerator;
|
||||
};
|
@ -0,0 +1,397 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RivSurfaceIntersectionGeometryGenerator.h"
|
||||
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigResultAccessor.h"
|
||||
|
||||
#include "RigSurface.h"
|
||||
#include "Rim3dView.h"
|
||||
#include "RimCase.h"
|
||||
#include "RimGridView.h"
|
||||
#include "RimSurface.h"
|
||||
#include "RimSurfaceInView.h"
|
||||
|
||||
#include "RivExtrudedCurveIntersectionPartMgr.h"
|
||||
#include "RivHexGridIntersectionTools.h"
|
||||
#include "RivPolylineGenerator.h"
|
||||
|
||||
#include "cafDisplayCoordTransform.h"
|
||||
#include "cafHexGridIntersectionTools/cafHexGridIntersectionTools.h"
|
||||
|
||||
#include "cvfDrawableGeo.h"
|
||||
#include "cvfGeometryTools.h"
|
||||
#include "cvfPlane.h"
|
||||
#include "cvfPrimitiveSetDirect.h"
|
||||
#include "cvfPrimitiveSetIndexedUInt.h"
|
||||
#include "cvfRay.h"
|
||||
#include "cvfScalarMapper.h"
|
||||
|
||||
#include "../cafHexInterpolator/cafHexInterpolator.h"
|
||||
#include "RivSectionFlattner.h"
|
||||
|
||||
cvf::ref<caf::DisplayCoordTransform> displayCoordTransform( const RimIntersection* intersection )
|
||||
{
|
||||
Rim3dView* rimView = nullptr;
|
||||
intersection->firstAncestorOrThisOfType( rimView );
|
||||
CVF_ASSERT( rimView );
|
||||
|
||||
cvf::ref<caf::DisplayCoordTransform> transForm = rimView->displayCoordTransform();
|
||||
return transForm;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RivSurfaceIntersectionGeometryGenerator::RivSurfaceIntersectionGeometryGenerator( RimSurfaceInView* surfInView,
|
||||
const RivIntersectionHexGridInterface* grid )
|
||||
: m_surfaceInView( surfInView )
|
||||
, m_hexGrid( grid )
|
||||
{
|
||||
m_triangleVxes = new cvf::Vec3fArray;
|
||||
m_cellBorderLineVxes = new cvf::Vec3fArray;
|
||||
m_faultCellBorderLineVxes = new cvf::Vec3fArray;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RivSurfaceIntersectionGeometryGenerator::~RivSurfaceIntersectionGeometryGenerator() {}
|
||||
|
||||
class MeshLinesAccumulator
|
||||
{
|
||||
public:
|
||||
MeshLinesAccumulator( const RivIntersectionHexGridInterface* hexGrid )
|
||||
: m_hexGrid( hexGrid )
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<cvf::Vec3f> cellBorderLineVxes;
|
||||
std::vector<cvf::Vec3f> faultCellBorderLineVxes;
|
||||
std::map<const RigFault*, cvf::Vec3d> faultToHighestFaultMeshVxMap;
|
||||
|
||||
void accumulateMeshLines( const std::vector<int>& cellFaceForEachClippedTriangleEdge,
|
||||
uint triVxIdx,
|
||||
size_t globalCellIdx,
|
||||
const cvf::Vec3d& p0,
|
||||
const cvf::Vec3d& p1 )
|
||||
{
|
||||
#define isFace( faceEnum ) ( 0 <= faceEnum && faceEnum <= 5 )
|
||||
using FaceType = cvf::StructGridInterface::FaceType;
|
||||
|
||||
if ( isFace( cellFaceForEachClippedTriangleEdge[triVxIdx] ) )
|
||||
{
|
||||
const RigFault* fault =
|
||||
m_hexGrid->findFaultFromCellIndexAndCellFace( globalCellIdx,
|
||||
(FaceType)cellFaceForEachClippedTriangleEdge[triVxIdx] );
|
||||
if ( fault )
|
||||
{
|
||||
cvf::Vec3d highestVx = p0.z() > p1.z() ? p0 : p1;
|
||||
|
||||
auto itIsInsertedPair = faultToHighestFaultMeshVxMap.insert( {fault, highestVx} );
|
||||
if ( !itIsInsertedPair.second )
|
||||
{
|
||||
if ( itIsInsertedPair.first->second.z() < highestVx.z() )
|
||||
{
|
||||
itIsInsertedPair.first->second = highestVx;
|
||||
}
|
||||
}
|
||||
|
||||
faultCellBorderLineVxes.emplace_back( p0 );
|
||||
faultCellBorderLineVxes.emplace_back( p1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cellBorderLineVxes.emplace_back( p0 );
|
||||
cellBorderLineVxes.emplace_back( p1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
cvf::cref<RivIntersectionHexGridInterface> m_hexGrid;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivSurfaceIntersectionGeometryGenerator::calculateArrays()
|
||||
{
|
||||
if ( m_triangleVxes->size() ) return;
|
||||
if ( m_hexGrid.isNull() ) return;
|
||||
|
||||
std::vector<cvf::Vec3f> outputTriangleVertices;
|
||||
|
||||
MeshLinesAccumulator meshAcc( m_hexGrid.p() );
|
||||
|
||||
cvf::BoundingBox gridBBox = m_hexGrid->boundingBox();
|
||||
|
||||
m_usedSurfaceData = m_surfaceInView->surface()->surfaceData();
|
||||
|
||||
const std::vector<cvf::Vec3d>& nativeVertices = m_usedSurfaceData->vertices();
|
||||
const std::vector<unsigned>& nativeTriangleIndices = m_usedSurfaceData->triangleIndices();
|
||||
cvf::Vec3d displayModelOffset = m_hexGrid->displayOffset();
|
||||
|
||||
for ( size_t ntVxIdx = 0; ntVxIdx < nativeTriangleIndices.size(); ntVxIdx += 3 )
|
||||
{
|
||||
cvf::Vec3d p0 = nativeVertices[nativeTriangleIndices[ntVxIdx + 0]];
|
||||
cvf::Vec3d p1 = nativeVertices[nativeTriangleIndices[ntVxIdx + 1]];
|
||||
cvf::Vec3d p2 = nativeVertices[nativeTriangleIndices[ntVxIdx + 2]];
|
||||
|
||||
cvf::BoundingBox triangleBBox;
|
||||
triangleBBox.add( p0 );
|
||||
triangleBBox.add( p1 );
|
||||
triangleBBox.add( p2 );
|
||||
|
||||
cvf::Vec3d maxHeightVec;
|
||||
|
||||
std::vector<size_t> triIntersectedCellCandidates;
|
||||
m_hexGrid->findIntersectingCells( triangleBBox, &triIntersectedCellCandidates );
|
||||
|
||||
cvf::Plane plane;
|
||||
plane.setFromPoints( p0, p1, p2 );
|
||||
|
||||
std::vector<caf::HexGridIntersectionTools::ClipVx> hexPlaneCutTriangleVxes;
|
||||
hexPlaneCutTriangleVxes.reserve( 5 * 3 );
|
||||
|
||||
std::vector<int> cellFaceForEachTriangleEdge;
|
||||
cellFaceForEachTriangleEdge.reserve( 5 * 3 );
|
||||
|
||||
std::array<cvf::Vec3d, 8> cellCorners;
|
||||
std::array<size_t, 8> cornerIndices;
|
||||
|
||||
size_t startOfGeneratedTrianglesForNativeTriangles = outputTriangleVertices.size();
|
||||
|
||||
for ( size_t ticIdx = 0; ticIdx < triIntersectedCellCandidates.size(); ++ticIdx )
|
||||
{
|
||||
size_t globalCellIdx = triIntersectedCellCandidates[ticIdx];
|
||||
|
||||
if ( !m_hexGrid->useCell( globalCellIdx ) ) continue;
|
||||
|
||||
m_hexGrid->cellCornerVertices( globalCellIdx, &cellCorners[0] );
|
||||
m_hexGrid->cellCornerIndices( globalCellIdx, &cornerIndices[0] );
|
||||
|
||||
hexPlaneCutTriangleVxes.clear();
|
||||
int triangleCount = caf::HexGridIntersectionTools::planeHexIntersectionMC( plane,
|
||||
&cellCorners[0],
|
||||
&cornerIndices[0],
|
||||
&hexPlaneCutTriangleVxes,
|
||||
&cellFaceForEachTriangleEdge );
|
||||
|
||||
if ( triangleCount == 0 ) continue;
|
||||
|
||||
std::vector<cvf::Vec3d> cellCutTriangles;
|
||||
for ( const auto& clipVx : hexPlaneCutTriangleVxes )
|
||||
{
|
||||
cellCutTriangles.push_back( clipVx.vx );
|
||||
}
|
||||
|
||||
std::vector<cvf::Vec3d> clippedTriangleVxes;
|
||||
std::vector<int> cellFaceForEachClippedTriangleEdge;
|
||||
|
||||
caf::HexGridIntersectionTools::clipPlanarTrianglesWithInPlaneTriangle( cellCutTriangles,
|
||||
cellFaceForEachTriangleEdge,
|
||||
p0,
|
||||
p1,
|
||||
p2,
|
||||
&clippedTriangleVxes,
|
||||
&cellFaceForEachClippedTriangleEdge );
|
||||
|
||||
size_t clippedTriangleCount = clippedTriangleVxes.size() / 3;
|
||||
|
||||
for ( uint clippTrIdx = 0; clippTrIdx < clippedTriangleCount; ++clippTrIdx )
|
||||
{
|
||||
uint triVxIdx = clippTrIdx * 3;
|
||||
|
||||
// Accumulate triangle vertices
|
||||
|
||||
cvf::Vec3d point0( clippedTriangleVxes[triVxIdx + 0] - displayModelOffset );
|
||||
cvf::Vec3d point1( clippedTriangleVxes[triVxIdx + 1] - displayModelOffset );
|
||||
cvf::Vec3d point2( clippedTriangleVxes[triVxIdx + 2] - displayModelOffset );
|
||||
|
||||
outputTriangleVertices.emplace_back( point0 );
|
||||
outputTriangleVertices.emplace_back( point1 );
|
||||
outputTriangleVertices.emplace_back( point2 );
|
||||
|
||||
// Accumulate mesh lines
|
||||
|
||||
meshAcc.accumulateMeshLines( cellFaceForEachClippedTriangleEdge, triVxIdx + 0, globalCellIdx, point0, point1 );
|
||||
meshAcc.accumulateMeshLines( cellFaceForEachClippedTriangleEdge, triVxIdx + 1, globalCellIdx, point1, point2 );
|
||||
meshAcc.accumulateMeshLines( cellFaceForEachClippedTriangleEdge, triVxIdx + 2, globalCellIdx, point2, point0 );
|
||||
|
||||
// Mapping to cell index
|
||||
|
||||
m_triangleToCellIdxMap.push_back( globalCellIdx );
|
||||
|
||||
// Interpolation from nodes
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
cvf::Vec3d cvx = clippedTriangleVxes[triVxIdx + i];
|
||||
|
||||
std::array<double, 8> cornerWeights = caf::HexInterpolator::vertexWeights( cellCorners, cvx );
|
||||
m_triVxToCellCornerWeights.push_back( RivIntersectionVertexWeights( cornerIndices, cornerWeights ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add triangles for the part of the native triangle outside any gridcells
|
||||
|
||||
if ( startOfGeneratedTrianglesForNativeTriangles == outputTriangleVertices.size() )
|
||||
{
|
||||
// No triangles created, use the complete native triangle
|
||||
outputTriangleVertices.push_back( cvf::Vec3f( p0 - displayModelOffset ) );
|
||||
outputTriangleVertices.push_back( cvf::Vec3f( p1 - displayModelOffset ) );
|
||||
outputTriangleVertices.push_back( cvf::Vec3f( p2 - displayModelOffset ) );
|
||||
|
||||
m_triangleToCellIdxMap.push_back( cvf::UNDEFINED_SIZE_T );
|
||||
|
||||
m_triVxToCellCornerWeights.push_back( RivIntersectionVertexWeights() );
|
||||
m_triVxToCellCornerWeights.push_back( RivIntersectionVertexWeights() );
|
||||
m_triVxToCellCornerWeights.push_back( RivIntersectionVertexWeights() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Todo:
|
||||
// Subtract the created triangles from the native triangle
|
||||
// Add the remains
|
||||
}
|
||||
}
|
||||
|
||||
m_triangleVxes->assign( outputTriangleVertices );
|
||||
m_cellBorderLineVxes->assign( meshAcc.cellBorderLineVxes );
|
||||
m_faultCellBorderLineVxes->assign( meshAcc.faultCellBorderLineVxes );
|
||||
|
||||
for ( const auto& it : meshAcc.faultToHighestFaultMeshVxMap )
|
||||
{
|
||||
m_faultMeshLabelAndAnchorPositions.push_back( {it.first->name(), it.second} );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Generate surface drawable geo from the specified region
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<cvf::DrawableGeo> RivSurfaceIntersectionGeometryGenerator::generateSurface()
|
||||
{
|
||||
calculateArrays();
|
||||
|
||||
CVF_ASSERT( m_triangleVxes.notNull() );
|
||||
|
||||
if ( m_triangleVxes->size() == 0 ) return nullptr;
|
||||
|
||||
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
|
||||
geo->setFromTriangleVertexArray( m_triangleVxes.p() );
|
||||
|
||||
return geo;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<cvf::DrawableGeo> RivSurfaceIntersectionGeometryGenerator::createMeshDrawable()
|
||||
{
|
||||
if ( !( m_cellBorderLineVxes.notNull() && m_cellBorderLineVxes->size() != 0 ) ) return nullptr;
|
||||
|
||||
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
|
||||
geo->setVertexArray( m_cellBorderLineVxes.p() );
|
||||
|
||||
cvf::ref<cvf::PrimitiveSetDirect> prim = new cvf::PrimitiveSetDirect( cvf::PT_LINES );
|
||||
prim->setIndexCount( m_cellBorderLineVxes->size() );
|
||||
|
||||
geo->addPrimitiveSet( prim.p() );
|
||||
return geo;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<cvf::DrawableGeo> RivSurfaceIntersectionGeometryGenerator::createFaultMeshDrawable()
|
||||
{
|
||||
if ( !( m_faultCellBorderLineVxes.notNull() && m_faultCellBorderLineVxes->size() != 0 ) ) return nullptr;
|
||||
|
||||
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
|
||||
geo->setVertexArray( m_faultCellBorderLineVxes.p() );
|
||||
|
||||
cvf::ref<cvf::PrimitiveSetDirect> prim = new cvf::PrimitiveSetDirect( cvf::PT_LINES );
|
||||
prim->setIndexCount( m_faultCellBorderLineVxes->size() );
|
||||
|
||||
geo->addPrimitiveSet( prim.p() );
|
||||
return geo;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<std::pair<QString, cvf::Vec3d>>&
|
||||
RivSurfaceIntersectionGeometryGenerator::faultMeshLabelAndAnchorPositions()
|
||||
{
|
||||
return m_faultMeshLabelAndAnchorPositions;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<size_t>& RivSurfaceIntersectionGeometryGenerator::triangleToCellIndex() const
|
||||
{
|
||||
CVF_ASSERT( m_triangleVxes->size() );
|
||||
return m_triangleToCellIdxMap;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<RivIntersectionVertexWeights>&
|
||||
RivSurfaceIntersectionGeometryGenerator::triangleVxToCellCornerInterpolationWeights() const
|
||||
{
|
||||
CVF_ASSERT( m_triangleVxes->size() );
|
||||
return m_triVxToCellCornerWeights;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const cvf::Vec3fArray* RivSurfaceIntersectionGeometryGenerator::triangleVxes() const
|
||||
{
|
||||
CVF_ASSERT( m_triangleVxes->size() );
|
||||
return m_triangleVxes.p();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimSurfaceInView* RivSurfaceIntersectionGeometryGenerator::intersection() const
|
||||
{
|
||||
return m_surfaceInView;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RivSurfaceIntersectionGeometryGenerator::isAnyGeometryPresent() const
|
||||
{
|
||||
if ( m_triangleVxes->size() == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "cafPdmPointer.h"
|
||||
|
||||
#include "RivHexGridIntersectionTools.h"
|
||||
|
||||
#include "cvfArray.h"
|
||||
#include "cvfBoundingBox.h"
|
||||
#include "cvfObject.h"
|
||||
#include "cvfVector3.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RigMainGrid;
|
||||
class RigActiveCellInfo;
|
||||
class RigResultAccessor;
|
||||
class RigSurface;
|
||||
|
||||
class RimSurfaceInView;
|
||||
class RivIntersectionHexGridInterface;
|
||||
class RivIntersectionVertexWeights;
|
||||
|
||||
namespace cvf
|
||||
{
|
||||
class ScalarMapper;
|
||||
class DrawableGeo;
|
||||
} // namespace cvf
|
||||
|
||||
class RivSurfaceIntersectionGeometryGenerator : public cvf::Object, public RivIntersectionGeometryGeneratorIF
|
||||
{
|
||||
public:
|
||||
RivSurfaceIntersectionGeometryGenerator( RimSurfaceInView* surfInView, const RivIntersectionHexGridInterface* grid );
|
||||
|
||||
~RivSurfaceIntersectionGeometryGenerator() override;
|
||||
|
||||
// Generate geometry
|
||||
cvf::ref<cvf::DrawableGeo> generateSurface();
|
||||
cvf::ref<cvf::DrawableGeo> createMeshDrawable();
|
||||
cvf::ref<cvf::DrawableGeo> createFaultMeshDrawable();
|
||||
|
||||
const std::vector<std::pair<QString, cvf::Vec3d>>& faultMeshLabelAndAnchorPositions();
|
||||
|
||||
RimSurfaceInView* intersection() const;
|
||||
|
||||
// GeomGen Interface
|
||||
bool isAnyGeometryPresent() const override;
|
||||
|
||||
const std::vector<size_t>& triangleToCellIndex() const override;
|
||||
const std::vector<RivIntersectionVertexWeights>& triangleVxToCellCornerInterpolationWeights() const override;
|
||||
const cvf::Vec3fArray* triangleVxes() const override;
|
||||
|
||||
private:
|
||||
void calculateArrays();
|
||||
|
||||
RimSurfaceInView* m_surfaceInView;
|
||||
cvf::ref<RigSurface> m_usedSurfaceData; // Store the reference to the old data, to know when new data has arrived.
|
||||
|
||||
cvf::cref<RivIntersectionHexGridInterface> m_hexGrid;
|
||||
|
||||
// Output arrays
|
||||
cvf::ref<cvf::Vec3fArray> m_triangleVxes;
|
||||
cvf::ref<cvf::Vec3fArray> m_cellBorderLineVxes;
|
||||
cvf::ref<cvf::Vec3fArray> m_faultCellBorderLineVxes;
|
||||
std::vector<size_t> m_triangleToCellIdxMap;
|
||||
std::vector<RivIntersectionVertexWeights> m_triVxToCellCornerWeights;
|
||||
|
||||
std::vector<std::pair<QString, cvf::Vec3d>> m_faultMeshLabelAndAnchorPositions;
|
||||
};
|
@ -18,12 +18,38 @@
|
||||
|
||||
#include "RivSurfacePartMgr.h"
|
||||
|
||||
#include "RigSurface.h"
|
||||
#include "RimSurface.h"
|
||||
#include "RimSurfaceInView.h"
|
||||
#include "RiaApplication.h"
|
||||
#include "RiaPreferences.h"
|
||||
|
||||
#include "RimCase.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseCellColors.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimGeoMechCellColors.h"
|
||||
#include "RimGeoMechResultDefinition.h"
|
||||
#include "RimGeoMechView.h"
|
||||
#include "RimRegularLegendConfig.h"
|
||||
#include "RimSurface.h"
|
||||
#include "RimSurfaceInView.h"
|
||||
#include "RimTernaryLegendConfig.h"
|
||||
|
||||
#include "RigHexIntersectionTools.h"
|
||||
#include "RigResultAccessor.h"
|
||||
#include "RigResultAccessorFactory.h"
|
||||
#include "RigSurface.h"
|
||||
|
||||
#include "RivHexGridIntersectionTools.h"
|
||||
#include "RivIntersectionResultsColoringTools.h"
|
||||
#include "RivMeshLinesSourceInfo.h"
|
||||
#include "RivPartPriority.h"
|
||||
#include "RivReservoirSurfaceIntersectionSourceInfo.h"
|
||||
#include "RivScalarMapperUtils.h"
|
||||
#include "RivSurfaceIntersectionGeometryGenerator.h"
|
||||
#include "RivTernaryScalarMapper.h"
|
||||
|
||||
#include "cafEffectGenerator.h"
|
||||
|
||||
#include "cvfDrawableGeo.h"
|
||||
#include "cvfModelBasicList.h"
|
||||
#include "cvfPart.h"
|
||||
@ -35,6 +61,12 @@
|
||||
RivSurfacePartMgr::RivSurfacePartMgr( RimSurfaceInView* surface )
|
||||
: m_surfaceInView( surface )
|
||||
{
|
||||
CVF_ASSERT( surface );
|
||||
|
||||
m_intersectionFacesTextureCoords = new cvf::Vec2fArray;
|
||||
|
||||
cvf::ref<RivIntersectionHexGridInterface> hexGrid = m_surfaceInView->createHexGridInterface();
|
||||
m_intersectionGenerator = new RivSurfaceIntersectionGeometryGenerator( m_surfaceInView, hexGrid.p() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -50,10 +82,7 @@ void RivSurfacePartMgr::appendNativeGeometryPartsToModel( cvf::ModelBasicList* m
|
||||
if ( m_nativeTrianglesPart.notNull() )
|
||||
{
|
||||
m_nativeTrianglesPart->setTransform( scaleTransform );
|
||||
|
||||
caf::SurfaceEffectGenerator surfaceGen( cvf::Color4f( m_surfaceInView->surface()->color() ), caf::PO_1 );
|
||||
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
|
||||
m_nativeTrianglesPart->setEffect( eff.p() );
|
||||
this->applySingleColor();
|
||||
|
||||
model->addPart( m_nativeTrianglesPart.p() );
|
||||
|
||||
@ -65,6 +94,275 @@ void RivSurfacePartMgr::appendNativeGeometryPartsToModel( cvf::ModelBasicList* m
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivSurfacePartMgr::updateCellResultColor( size_t timeStepIndex )
|
||||
{
|
||||
if ( m_intersectionFaces.notNull() )
|
||||
{
|
||||
RivIntersectionResultsColoringTools::calculateIntersectionResultColors( timeStepIndex,
|
||||
false,
|
||||
m_surfaceInView,
|
||||
m_intersectionGenerator.p(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
m_intersectionFaces.p(),
|
||||
m_intersectionFacesTextureCoords.p() );
|
||||
}
|
||||
|
||||
if ( m_nativeTrianglesPart.notNull() )
|
||||
{
|
||||
if ( !m_nativeVertexToCellIndexMap.size() )
|
||||
{
|
||||
generateNativeVertexToCellIndexMap();
|
||||
}
|
||||
|
||||
RimGridView* gridView = nullptr;
|
||||
m_surfaceInView->firstAncestorOrThisOfType( gridView );
|
||||
|
||||
if ( !gridView ) return;
|
||||
|
||||
bool isLightingDisabled = gridView->isLightingDisabled();
|
||||
|
||||
RimEclipseResultDefinition* eclipseResDef = nullptr;
|
||||
RimGeoMechResultDefinition* geomResultDef = nullptr;
|
||||
const cvf::ScalarMapper* scalarColorMapper = nullptr;
|
||||
const RivTernaryScalarMapper* ternaryColorMapper = nullptr;
|
||||
|
||||
// Ordinary result
|
||||
|
||||
if ( !eclipseResDef && !geomResultDef )
|
||||
{
|
||||
RimEclipseView* eclipseView = nullptr;
|
||||
m_surfaceInView->firstAncestorOrThisOfType( eclipseView );
|
||||
|
||||
if ( eclipseView )
|
||||
{
|
||||
eclipseResDef = eclipseView->cellResult();
|
||||
if ( !scalarColorMapper ) scalarColorMapper = eclipseView->cellResult()->legendConfig()->scalarMapper();
|
||||
if ( !ternaryColorMapper )
|
||||
ternaryColorMapper = eclipseView->cellResult()->ternaryLegendConfig()->scalarMapper();
|
||||
}
|
||||
|
||||
RimGeoMechView* geoView;
|
||||
m_surfaceInView->firstAncestorOrThisOfType( geoView );
|
||||
|
||||
if ( geoView )
|
||||
{
|
||||
geomResultDef = geoView->cellResult();
|
||||
if ( !scalarColorMapper ) scalarColorMapper = geoView->cellResult()->legendConfig()->scalarMapper();
|
||||
}
|
||||
}
|
||||
|
||||
cvf::ref<cvf::Vec2fArray> nativeFacesTextureCoords = new cvf::Vec2fArray();
|
||||
|
||||
if ( eclipseResDef )
|
||||
{
|
||||
if ( !eclipseResDef->isTernarySaturationSelected() )
|
||||
{
|
||||
RigEclipseCaseData* eclipseCaseData = eclipseResDef->eclipseCase()->eclipseCaseData();
|
||||
|
||||
cvf::ref<RigResultAccessor> resultAccessor;
|
||||
|
||||
if ( !RiaDefines::isPerCellFaceResult( eclipseResDef->resultVariable() ) )
|
||||
|
||||
{
|
||||
resultAccessor = RigResultAccessorFactory::createFromResultDefinition( eclipseCaseData,
|
||||
0,
|
||||
timeStepIndex,
|
||||
eclipseResDef );
|
||||
}
|
||||
|
||||
if ( resultAccessor.isNull() )
|
||||
{
|
||||
resultAccessor = new RigHugeValResultAccessor;
|
||||
}
|
||||
|
||||
RivSurfacePartMgr::calculateVertexTextureCoordinates( nativeFacesTextureCoords.p(),
|
||||
m_nativeVertexToCellIndexMap,
|
||||
resultAccessor.p(),
|
||||
scalarColorMapper );
|
||||
|
||||
RivScalarMapperUtils::applyTextureResultsToPart( m_nativeTrianglesPart.p(),
|
||||
nativeFacesTextureCoords.p(),
|
||||
scalarColorMapper,
|
||||
1.0,
|
||||
caf::FC_NONE,
|
||||
isLightingDisabled );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivSurfacePartMgr::appendIntersectionGeometryPartsToModel( cvf::ModelBasicList* model,
|
||||
cvf::Transform* scaleTransform )
|
||||
{
|
||||
if ( m_intersectionFaces.isNull() )
|
||||
{
|
||||
generatePartGeometry();
|
||||
}
|
||||
|
||||
if ( m_intersectionFaces.notNull() )
|
||||
{
|
||||
m_intersectionFaces->setTransform( scaleTransform );
|
||||
model->addPart( m_intersectionFaces.p() );
|
||||
}
|
||||
|
||||
// Mesh Lines
|
||||
|
||||
if ( m_intersectionGridLines.isNull() )
|
||||
{
|
||||
generatePartGeometry();
|
||||
}
|
||||
|
||||
if ( m_intersectionGridLines.notNull() )
|
||||
{
|
||||
m_intersectionGridLines->setTransform( scaleTransform );
|
||||
model->addPart( m_intersectionGridLines.p() );
|
||||
}
|
||||
|
||||
if ( m_intersectionFaultGridLines.notNull() )
|
||||
{
|
||||
m_intersectionFaultGridLines->setTransform( scaleTransform );
|
||||
model->addPart( m_intersectionFaultGridLines.p() );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivSurfacePartMgr::applySingleColor()
|
||||
{
|
||||
{
|
||||
caf::SurfaceEffectGenerator surfaceGen( cvf::Color4f( m_surfaceInView->surface()->color() ), caf::PO_1 );
|
||||
cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();
|
||||
|
||||
if ( m_nativeTrianglesPart.notNull() )
|
||||
{
|
||||
m_nativeTrianglesPart->setEffect( eff.p() );
|
||||
}
|
||||
|
||||
if ( m_intersectionFaces.notNull() )
|
||||
{
|
||||
m_intersectionFaces->setEffect( eff.p() );
|
||||
}
|
||||
}
|
||||
|
||||
// Update mesh colors as well, in case of change
|
||||
|
||||
RiaPreferences* prefs = RiaApplication::instance()->preferences();
|
||||
|
||||
if ( m_intersectionGridLines.notNull() )
|
||||
{
|
||||
cvf::ref<cvf::Effect> eff;
|
||||
caf::MeshEffectGenerator CrossSectionEffGen( prefs->defaultGridLineColors() );
|
||||
eff = CrossSectionEffGen.generateCachedEffect();
|
||||
|
||||
m_intersectionGridLines->setEffect( eff.p() );
|
||||
}
|
||||
|
||||
if ( m_intersectionFaultGridLines.notNull() )
|
||||
{
|
||||
cvf::ref<cvf::Effect> eff;
|
||||
caf::MeshEffectGenerator CrossSectionEffGen( prefs->defaultFaultGridLineColors() );
|
||||
eff = CrossSectionEffGen.generateCachedEffect();
|
||||
|
||||
m_intersectionFaultGridLines->setEffect( eff.p() );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivSurfacePartMgr::generatePartGeometry()
|
||||
{
|
||||
if ( m_intersectionGenerator.isNull() ) return;
|
||||
|
||||
bool useBufferObjects = true;
|
||||
// Surface geometry
|
||||
{
|
||||
cvf::ref<cvf::DrawableGeo> geo = m_intersectionGenerator->generateSurface();
|
||||
if ( geo.notNull() )
|
||||
{
|
||||
geo->computeNormals();
|
||||
|
||||
if ( useBufferObjects )
|
||||
{
|
||||
geo->setRenderMode( cvf::DrawableGeo::BUFFER_OBJECT );
|
||||
}
|
||||
|
||||
cvf::ref<cvf::Part> part = new cvf::Part;
|
||||
part->setName( "Reservoir Surface" );
|
||||
part->setDrawable( geo.p() );
|
||||
|
||||
// Set mapping from triangle face index to cell index
|
||||
cvf::ref<RivReservoirSurfaceIntersectionSourceInfo> si = new RivReservoirSurfaceIntersectionSourceInfo(
|
||||
m_intersectionGenerator.p() );
|
||||
part->setSourceInfo( si.p() );
|
||||
|
||||
part->updateBoundingBox();
|
||||
part->setEnableMask( intersectionCellFaceBit );
|
||||
part->setPriority( RivPartPriority::PartType::Intersection );
|
||||
|
||||
m_intersectionFaces = part;
|
||||
}
|
||||
}
|
||||
|
||||
// Cell Mesh geometry
|
||||
{
|
||||
cvf::ref<cvf::DrawableGeo> geoMesh = m_intersectionGenerator->createMeshDrawable();
|
||||
if ( geoMesh.notNull() )
|
||||
{
|
||||
if ( useBufferObjects )
|
||||
{
|
||||
geoMesh->setRenderMode( cvf::DrawableGeo::BUFFER_OBJECT );
|
||||
}
|
||||
|
||||
cvf::ref<cvf::Part> part = new cvf::Part;
|
||||
part->setName( "Surface intersection mesh" );
|
||||
part->setDrawable( geoMesh.p() );
|
||||
|
||||
part->updateBoundingBox();
|
||||
part->setEnableMask( intersectionCellMeshBit );
|
||||
part->setPriority( RivPartPriority::PartType::MeshLines );
|
||||
|
||||
part->setSourceInfo( new RivMeshLinesSourceInfo( m_surfaceInView ) );
|
||||
|
||||
m_intersectionGridLines = part;
|
||||
}
|
||||
}
|
||||
|
||||
// Fault Mesh geometry
|
||||
{
|
||||
cvf::ref<cvf::DrawableGeo> geoMesh = m_intersectionGenerator->createFaultMeshDrawable();
|
||||
if ( geoMesh.notNull() )
|
||||
{
|
||||
if ( useBufferObjects )
|
||||
{
|
||||
geoMesh->setRenderMode( cvf::DrawableGeo::BUFFER_OBJECT );
|
||||
}
|
||||
|
||||
cvf::ref<cvf::Part> part = new cvf::Part;
|
||||
part->setName( "Surface faultmesh" );
|
||||
part->setDrawable( geoMesh.p() );
|
||||
|
||||
part->updateBoundingBox();
|
||||
part->setEnableMask( intersectionFaultMeshBit );
|
||||
part->setPriority( RivPartPriority::PartType::FaultMeshLines );
|
||||
|
||||
part->setSourceInfo( new RivMeshLinesSourceInfo( m_surfaceInView ) );
|
||||
|
||||
m_intersectionFaultGridLines = part;
|
||||
}
|
||||
}
|
||||
|
||||
applySingleColor();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -94,5 +392,69 @@ void RivSurfacePartMgr::generateNativePartGeometry()
|
||||
drawGeo->computeNormals();
|
||||
|
||||
m_nativeTrianglesPart = new cvf::Part();
|
||||
m_nativeTrianglesPart->setName( "Native Reservoir Surface" );
|
||||
m_nativeTrianglesPart->setDrawable( drawGeo.p() );
|
||||
|
||||
m_nativeVertexToCellIndexMap.clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivSurfacePartMgr::generateNativeVertexToCellIndexMap()
|
||||
{
|
||||
cvf::ref<RivIntersectionHexGridInterface> hexGrid = m_surfaceInView->createHexGridInterface();
|
||||
|
||||
const std::vector<cvf::Vec3d>& vertices = m_usedSurfaceData->vertices();
|
||||
m_nativeVertexToCellIndexMap.resize( vertices.size(), -1 );
|
||||
|
||||
for ( size_t vxIdx = 0; vxIdx < vertices.size(); ++vxIdx )
|
||||
{
|
||||
cvf::BoundingBox box;
|
||||
box.add( vertices[vxIdx] );
|
||||
std::vector<size_t> cellCandidates;
|
||||
hexGrid->findIntersectingCells( box, &cellCandidates );
|
||||
|
||||
for ( size_t cellIdx : cellCandidates )
|
||||
{
|
||||
cvf::Vec3d cellCorners[8];
|
||||
hexGrid->cellCornerVertices( cellIdx, cellCorners );
|
||||
|
||||
if ( RigHexIntersectionTools::isPointInCell( vertices[vxIdx], cellCorners ) )
|
||||
{
|
||||
m_nativeVertexToCellIndexMap[vxIdx] = cellIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Calculates the texture coordinates in a "nearly" one dimensional texture.
|
||||
/// Undefined values are coded with a y-texturecoordinate value of 1.0 instead of the normal 0.5
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RivSurfacePartMgr::calculateVertexTextureCoordinates( cvf::Vec2fArray* textureCoords,
|
||||
const std::vector<size_t>& vertexToCellIdxMap,
|
||||
const RigResultAccessor* resultAccessor,
|
||||
const cvf::ScalarMapper* mapper )
|
||||
{
|
||||
if ( !resultAccessor ) return;
|
||||
|
||||
size_t numVertices = vertexToCellIdxMap.size();
|
||||
|
||||
textureCoords->resize( numVertices );
|
||||
cvf::Vec2f* rawPtr = textureCoords->ptr();
|
||||
|
||||
#pragma omp parallel for
|
||||
for ( int vxIdx = 0; vxIdx < numVertices; vxIdx++ )
|
||||
{
|
||||
double cellScalarValue = resultAccessor->cellScalarGlobIdx( vertexToCellIdxMap[vxIdx] );
|
||||
cvf::Vec2f texCoord = mapper->mapToTextureCoord( cellScalarValue );
|
||||
if ( cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue ) // a != a is true for NAN's
|
||||
{
|
||||
texCoord[1] = 1.0f;
|
||||
}
|
||||
|
||||
rawPtr[vxIdx] = texCoord;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "cafPdmPointer.h"
|
||||
#include "cvfArray.h"
|
||||
#include "cvfObject.h"
|
||||
|
||||
namespace cvf
|
||||
@ -31,20 +32,49 @@ class DrawableGeo;
|
||||
|
||||
class RimSurfaceInView;
|
||||
class RigSurface;
|
||||
class RigResultAccessor;
|
||||
|
||||
class RivSurfaceIntersectionGeometryGenerator;
|
||||
|
||||
class RivSurfacePartMgr : public cvf::Object
|
||||
{
|
||||
public:
|
||||
explicit RivSurfacePartMgr( RimSurfaceInView* surface );
|
||||
|
||||
void applySingleColor();
|
||||
void updateCellResultColor( size_t timeStepIndex );
|
||||
void appendIntersectionGeometryPartsToModel( cvf::ModelBasicList* model, cvf::Transform* scaleTransform );
|
||||
|
||||
void appendNativeGeometryPartsToModel( cvf::ModelBasicList* model, cvf::Transform* scaleTransform );
|
||||
|
||||
private:
|
||||
void generatePartGeometry();
|
||||
|
||||
void generateNativePartGeometry();
|
||||
void generateNativeVertexToCellIndexMap();
|
||||
|
||||
static void calculateVertexTextureCoordinates( cvf::Vec2fArray* textureCoords,
|
||||
const std::vector<size_t>& vertexToCellIdxMap,
|
||||
const RigResultAccessor* resultAccessor,
|
||||
const cvf::ScalarMapper* mapper );
|
||||
|
||||
cvf::ref<RivSurfaceIntersectionGeometryGenerator> m_intersectionGenerator;
|
||||
|
||||
caf::PdmPointer<RimSurfaceInView> m_surfaceInView;
|
||||
cvf::ref<RigSurface> m_usedSurfaceData; // Store the reference to the old data, to know when new data has arrived.
|
||||
|
||||
cvf::ref<cvf::Part> m_nativeTrianglesPart;
|
||||
cvf::ref<cvf::Part> m_nativeMeshLinesPart;
|
||||
|
||||
cvf::ref<cvf::Part> m_intersectionFaces;
|
||||
cvf::ref<cvf::Part> m_intersectionGridLines;
|
||||
cvf::ref<cvf::Part> m_intersectionFaultGridLines;
|
||||
|
||||
cvf::ref<cvf::Vec2fArray> m_intersectionFacesTextureCoords;
|
||||
|
||||
std::vector<size_t> m_nativeVertexToCellIndexMap;
|
||||
};
|
||||
|
||||
class RivReservoirSurfaceGeometryGenerator : public cvf::Object
|
||||
{
|
||||
};
|
||||
|
@ -544,7 +544,7 @@ void Rim2dIntersectionView::onCreateDisplayModel()
|
||||
|
||||
m_intersectionVizModel->removeAllParts();
|
||||
|
||||
m_flatIntersectionPartMgr->appendNativeIntersectionFacesToModel( m_intersectionVizModel.p(), scaleTransform() );
|
||||
m_flatIntersectionPartMgr->appendIntersectionFacesToModel( m_intersectionVizModel.p(), scaleTransform() );
|
||||
m_flatIntersectionPartMgr->appendMeshLinePartsToModel( m_intersectionVizModel.p(), scaleTransform() );
|
||||
m_flatIntersectionPartMgr->appendPolylinePartsToModel( *this, m_intersectionVizModel.p(), scaleTransform() );
|
||||
|
||||
|
@ -55,6 +55,8 @@ RimBoxIntersection::RimBoxIntersection()
|
||||
{
|
||||
CAF_PDM_InitObject( "Intersection Box", ":/IntersectionBox16x16.png", "", "" );
|
||||
|
||||
CAF_PDM_InitField( &m_name, "UserDescription", QString( "Intersection Name" ), "Name", "", "", "" );
|
||||
|
||||
CAF_PDM_InitField( &m_singlePlaneState,
|
||||
"singlePlaneState",
|
||||
caf::AppEnum<SinglePlaneState>( SinglePlaneState::PLANE_STATE_NONE ),
|
||||
@ -100,6 +102,30 @@ RimBoxIntersection::~RimBoxIntersection()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmFieldHandle* RimBoxIntersection::userDescriptionField()
|
||||
{
|
||||
return &m_name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimBoxIntersection::name() const
|
||||
{
|
||||
return m_name();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimBoxIntersection::setName( const QString& newName )
|
||||
{
|
||||
m_name = newName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -62,6 +62,9 @@ public:
|
||||
RimBoxIntersection();
|
||||
~RimBoxIntersection() override;
|
||||
|
||||
QString name() const override;
|
||||
void setName( const QString& newName );
|
||||
|
||||
cvf::Mat4d boxOrigin() const;
|
||||
cvf::Vec3d boxSize() const;
|
||||
SinglePlaneState singlePlaneState() const;
|
||||
@ -76,6 +79,8 @@ public:
|
||||
void setToDefaultSizeSlice( SinglePlaneState plane, const cvf::Vec3d& position );
|
||||
|
||||
protected:
|
||||
caf::PdmFieldHandle* userDescriptionField() override final;
|
||||
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute ) override;
|
||||
@ -105,6 +110,8 @@ private:
|
||||
RiuViewer* viewer();
|
||||
|
||||
private:
|
||||
caf::PdmField<QString> m_name;
|
||||
|
||||
caf::PdmField<caf::AppEnum<SinglePlaneState>> m_singlePlaneState;
|
||||
|
||||
caf::PdmField<double> m_minXCoord;
|
||||
|
@ -803,10 +803,11 @@ void RimEclipseView::updateVisibleGeometriesAndCellColors()
|
||||
|
||||
this->updateFaultColors();
|
||||
|
||||
m_intersectionCollection->updateCellResultColor( ( this->hasUserRequestedAnimation() &&
|
||||
this->cellResult()->hasResult() ) ||
|
||||
this->cellResult()->isTernarySaturationSelected(),
|
||||
m_currentTimeStep );
|
||||
bool hasGeneralCellResult = ( this->hasUserRequestedAnimation() && this->cellResult()->hasResult() ) ||
|
||||
this->cellResult()->isTernarySaturationSelected();
|
||||
|
||||
m_intersectionCollection->updateCellResultColor( hasGeneralCellResult, m_currentTimeStep );
|
||||
if ( m_surfaceCollection ) m_surfaceCollection->updateCellResultColor( hasGeneralCellResult, m_currentTimeStep );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -890,6 +891,8 @@ void RimEclipseView::appendWellsAndFracturesToModel()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEclipseView::onLoadDataAndUpdate()
|
||||
{
|
||||
this->updateSurfacesInViewTreeItems();
|
||||
|
||||
onUpdateScaleTransform();
|
||||
|
||||
if ( m_eclipseCase )
|
||||
@ -1738,6 +1741,8 @@ void RimEclipseView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin
|
||||
uiTreeOrdering.add( cellEdgeResult() );
|
||||
uiTreeOrdering.add( faultResultSettings() );
|
||||
uiTreeOrdering.add( &m_intersectionResultDefCollection );
|
||||
uiTreeOrdering.add( &m_surfaceResultDefCollection );
|
||||
|
||||
uiTreeOrdering.add( wellCollection() );
|
||||
uiTreeOrdering.add( &m_wellMeasurementCollection );
|
||||
|
||||
|
@ -83,6 +83,7 @@ CAF_PDM_SOURCE_INIT( RimExtrudedCurveIntersection, "CrossSection" );
|
||||
RimExtrudedCurveIntersection::RimExtrudedCurveIntersection()
|
||||
{
|
||||
CAF_PDM_InitObject( "Intersection", ":/CrossSection16x16.png", "", "" );
|
||||
CAF_PDM_InitField( &m_name, "UserDescription", QString( "Intersection Name" ), "Name", "", "", "" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &type, "Type", "Type", "", "", "" );
|
||||
CAF_PDM_InitFieldNoDefault( &direction, "Direction", "Direction", "", "", "" );
|
||||
@ -139,6 +140,30 @@ RimExtrudedCurveIntersection::RimExtrudedCurveIntersection()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimExtrudedCurveIntersection::~RimExtrudedCurveIntersection() {}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmFieldHandle* RimExtrudedCurveIntersection::userDescriptionField()
|
||||
{
|
||||
return &m_name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimExtrudedCurveIntersection::name() const
|
||||
{
|
||||
return m_name();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimExtrudedCurveIntersection::setName( const QString& newName )
|
||||
{
|
||||
m_name = newName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -81,6 +81,9 @@ public:
|
||||
caf::PdmField<bool> inputExtrusionPointsFromViewerEnabled;
|
||||
caf::PdmField<bool> inputTwoAzimuthPointsFromViewerEnabled;
|
||||
|
||||
QString name() const override;
|
||||
void setName( const QString& newName );
|
||||
|
||||
std::vector<std::vector<cvf::Vec3d>> polyLines( cvf::Vec3d* flattenedPolylineStartPoint = nullptr ) const;
|
||||
void appendPointToPolyLine( const cvf::Vec3d& point );
|
||||
|
||||
@ -106,6 +109,7 @@ public:
|
||||
void rebuildGeometryAndScheduleCreateDisplayModel();
|
||||
|
||||
protected:
|
||||
caf::PdmFieldHandle* userDescriptionField() override final;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue ) override;
|
||||
@ -117,6 +121,8 @@ protected:
|
||||
bool* useOptionsOnly ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<QString> m_name;
|
||||
|
||||
caf::PdmField<int> m_branchIndex;
|
||||
caf::PdmField<double> m_extentLength;
|
||||
caf::PdmField<double> m_azimuthAngle;
|
||||
|
@ -131,8 +131,11 @@ void RimGeoMechView::onLoadDataAndUpdate()
|
||||
{
|
||||
caf::ProgressInfo progress( 7, "" );
|
||||
progress.setNextProgressIncrement( 5 );
|
||||
|
||||
onUpdateScaleTransform();
|
||||
|
||||
this->updateSurfacesInViewTreeItems();
|
||||
|
||||
if ( m_geomechCase )
|
||||
{
|
||||
std::string errorMessage;
|
||||
@ -395,13 +398,20 @@ void RimGeoMechView::onUpdateDisplayModelForCurrentTimeStep()
|
||||
else
|
||||
m_vizLogic->updateStaticCellColors( m_currentTimeStep() );
|
||||
|
||||
m_intersectionCollection->updateCellResultColor( this->cellResult()->hasResult(), m_currentTimeStep );
|
||||
bool hasGeneralCellResult = this->cellResult()->hasResult();
|
||||
|
||||
m_intersectionCollection->updateCellResultColor( hasGeneralCellResult, m_currentTimeStep );
|
||||
if ( m_surfaceCollection )
|
||||
{
|
||||
m_surfaceCollection->updateCellResultColor( hasGeneralCellResult, m_currentTimeStep );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vizLogic->updateStaticCellColors( -1 );
|
||||
|
||||
m_intersectionCollection->updateCellResultColor( false, m_currentTimeStep );
|
||||
if ( m_surfaceCollection ) m_surfaceCollection->updateCellResultColor( false, m_currentTimeStep );
|
||||
|
||||
nativeOrOverrideViewer()->animationControl()->slotPause(); // To avoid animation timer spinning in the background
|
||||
}
|
||||
@ -914,6 +924,7 @@ void RimGeoMechView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin
|
||||
uiTreeOrdering.add( cellResult() );
|
||||
uiTreeOrdering.add( m_tensorResults() );
|
||||
uiTreeOrdering.add( &m_intersectionResultDefCollection );
|
||||
uiTreeOrdering.add( &m_surfaceResultDefCollection );
|
||||
uiTreeOrdering.add( &m_wellMeasurementCollection );
|
||||
|
||||
uiTreeOrdering.add( m_intersectionCollection() );
|
||||
|
@ -87,6 +87,17 @@ RimGridView::RimGridView()
|
||||
m_intersectionResultDefCollection.uiCapability()->setUiTreeHidden( true );
|
||||
m_intersectionResultDefCollection = new RimIntersectionResultsDefinitionCollection;
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_surfaceResultDefCollection,
|
||||
"ReservoirSurfaceResultDefColl",
|
||||
"Separate Surface Results",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
m_surfaceResultDefCollection.uiCapability()->setUiTreeHidden( true );
|
||||
m_surfaceResultDefCollection = new RimIntersectionResultsDefinitionCollection;
|
||||
m_surfaceResultDefCollection->uiCapability()->setUiName( "Separate Surface Results" );
|
||||
m_surfaceResultDefCollection->uiCapability()->setUiIcon( caf::QIconProvider( ":/ReservoirSurface16x16.png" ) );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_gridCollection, "GridCollection", "GridCollection", "", "", "" );
|
||||
m_gridCollection.uiCapability()->setUiHidden( true );
|
||||
m_gridCollection = new RimGridCollection();
|
||||
@ -208,6 +219,14 @@ RimIntersectionResultsDefinitionCollection* RimGridView::separateIntersectionRes
|
||||
return m_intersectionResultDefCollection;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimIntersectionResultsDefinitionCollection* RimGridView::separateSurfaceResultsCollection() const
|
||||
{
|
||||
return m_surfaceResultDefCollection;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
RimIntersectionCollection* intersectionCollection() const;
|
||||
RimSurfaceInViewCollection* surfaceInViewCollection() const;
|
||||
RimIntersectionResultsDefinitionCollection* separateIntersectionResultsCollection() const;
|
||||
RimIntersectionResultsDefinitionCollection* separateSurfaceResultsCollection() const;
|
||||
RimAnnotationInViewCollection* annotationCollection() const;
|
||||
RimWellMeasurementInViewCollection* measurementCollection() const;
|
||||
|
||||
@ -96,6 +97,7 @@ protected:
|
||||
caf::PdmChildField<RimIntersectionCollection*> m_intersectionCollection;
|
||||
|
||||
caf::PdmChildField<RimIntersectionResultsDefinitionCollection*> m_intersectionResultDefCollection;
|
||||
caf::PdmChildField<RimIntersectionResultsDefinitionCollection*> m_surfaceResultDefCollection;
|
||||
|
||||
caf::PdmChildField<Rim3dOverlayInfoConfig*> m_overlayInfoConfig;
|
||||
caf::PdmChildField<RimCellRangeFilterCollection*> m_rangeFilterCollection;
|
||||
|
@ -31,14 +31,13 @@
|
||||
#include "RimIntersectionResultsDefinitionCollection.h"
|
||||
#include "RivHexGridIntersectionTools.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimIntersection, "RimIntersectionHandle" );
|
||||
CAF_PDM_ABSTRACT_SOURCE_INIT( RimIntersection, "RimIntersectionHandle" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimIntersection::RimIntersection()
|
||||
{
|
||||
CAF_PDM_InitField( &m_name, "UserDescription", QString( "Intersection Name" ), "Name", "", "", "" );
|
||||
CAF_PDM_InitField( &m_isActive, "Active", true, "Active", "", "", "" );
|
||||
m_isActive.uiCapability()->setUiHidden( true );
|
||||
CAF_PDM_InitField( &m_showInactiveCells, "ShowInactiveCells", false, "Show Inactive Cells", "", "", "" );
|
||||
@ -51,22 +50,6 @@ RimIntersection::RimIntersection()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimIntersection::~RimIntersection() {}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimIntersection::name() const
|
||||
{
|
||||
return m_name();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimIntersection::setName( const QString& newName )
|
||||
{
|
||||
m_name = newName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -104,10 +87,9 @@ RimIntersectionResultDefinition* RimIntersection::activeSeparateResultDefinition
|
||||
|
||||
if ( !m_separateDataSource->isActive() ) return nullptr;
|
||||
|
||||
RimGridView* view;
|
||||
this->firstAncestorOrThisOfTypeAsserted( view );
|
||||
if ( !findSeparateResultsCollection() ) return nullptr;
|
||||
|
||||
if ( !view->separateIntersectionResultsCollection()->isActive() ) return nullptr;
|
||||
if ( !findSeparateResultsCollection()->isActive() ) return nullptr;
|
||||
|
||||
return m_separateDataSource;
|
||||
}
|
||||
@ -122,11 +104,8 @@ QList<caf::PdmOptionItemInfo> RimIntersection::calculateValueOptions( const caf:
|
||||
|
||||
if ( fieldNeedingOptions == &m_separateDataSource )
|
||||
{
|
||||
RimGridView* view;
|
||||
this->firstAncestorOrThisOfTypeAsserted( view );
|
||||
|
||||
std::vector<RimIntersectionResultDefinition*> iResDefs =
|
||||
view->separateIntersectionResultsCollection()->intersectionResultsDefinitions();
|
||||
findSeparateResultsCollection()->intersectionResultsDefinitions();
|
||||
|
||||
for ( auto iresdef : iResDefs )
|
||||
{
|
||||
@ -140,9 +119,11 @@ QList<caf::PdmOptionItemInfo> RimIntersection::calculateValueOptions( const caf:
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmFieldHandle* RimIntersection::userDescriptionField()
|
||||
RimIntersectionResultsDefinitionCollection* RimIntersection::findSeparateResultsCollection()
|
||||
{
|
||||
return &m_name;
|
||||
RimGridView* view;
|
||||
this->firstAncestorOrThisOfTypeAsserted( view );
|
||||
return view->separateIntersectionResultsCollection();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -188,18 +169,12 @@ void RimIntersection::updateDefaultSeparateDataSource()
|
||||
{
|
||||
if ( m_separateDataSource() == nullptr )
|
||||
{
|
||||
RimGridView* view;
|
||||
this->firstAncestorOrThisOfType( view );
|
||||
std::vector<RimIntersectionResultDefinition*> iResDefs =
|
||||
findSeparateResultsCollection()->intersectionResultsDefinitions();
|
||||
|
||||
if ( view )
|
||||
if ( iResDefs.size() )
|
||||
{
|
||||
std::vector<RimIntersectionResultDefinition*> iResDefs =
|
||||
view->separateIntersectionResultsCollection()->intersectionResultsDefinitions();
|
||||
|
||||
if ( iResDefs.size() )
|
||||
{
|
||||
m_separateDataSource = iResDefs[0];
|
||||
}
|
||||
m_separateDataSource = iResDefs[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
class RimIntersectionResultDefinition;
|
||||
class RivIntersectionHexGridInterface;
|
||||
class RimIntersectionResultsDefinitionCollection;
|
||||
|
||||
class RimIntersection : public caf::PdmObject
|
||||
{
|
||||
@ -35,17 +36,18 @@ public:
|
||||
RimIntersection();
|
||||
~RimIntersection() override;
|
||||
|
||||
QString name() const;
|
||||
void setName( const QString& newName );
|
||||
bool isActive() const;
|
||||
void setActive( bool isActive );
|
||||
bool isInactiveCellsVisible() const;
|
||||
virtual QString name() const = 0;
|
||||
|
||||
bool isActive() const;
|
||||
void setActive( bool isActive );
|
||||
bool isInactiveCellsVisible() const;
|
||||
|
||||
RimIntersectionResultDefinition* activeSeparateResultDefinition();
|
||||
cvf::ref<RivIntersectionHexGridInterface> createHexGridInterface();
|
||||
|
||||
protected:
|
||||
caf::PdmFieldHandle* userDescriptionField() override final;
|
||||
virtual RimIntersectionResultsDefinitionCollection* findSeparateResultsCollection();
|
||||
|
||||
caf::PdmFieldHandle* objectToggleField() override final;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
|
||||
bool* useOptionsOnly ) override;
|
||||
@ -54,7 +56,6 @@ protected:
|
||||
void defineSeparateDataSourceUi( QString uiConfigName, caf::PdmUiOrdering& uiOrdering );
|
||||
void updateDefaultSeparateDataSource();
|
||||
|
||||
caf::PdmField<QString> m_name;
|
||||
caf::PdmField<bool> m_isActive;
|
||||
caf::PdmField<bool> m_showInactiveCells;
|
||||
caf::PdmField<bool> m_useSeparateDataSource;
|
||||
|
@ -150,7 +150,7 @@ void RimIntersectionCollection::appendPartsToModel( Rim3dView& view,
|
||||
{
|
||||
if ( cs->isActive() )
|
||||
{
|
||||
cs->intersectionPartMgr()->appendNativeIntersectionFacesToModel( model, scaleTransform );
|
||||
cs->intersectionPartMgr()->appendIntersectionFacesToModel( model, scaleTransform );
|
||||
cs->intersectionPartMgr()->appendMeshLinePartsToModel( model, scaleTransform );
|
||||
cs->intersectionPartMgr()->appendPolylinePartsToModel( view, model, scaleTransform );
|
||||
}
|
||||
|
@ -21,6 +21,10 @@
|
||||
#include "RimGridView.h"
|
||||
#include "RimSurface.h"
|
||||
|
||||
#include "RigFemPartCollection.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimGeoMechView.h"
|
||||
#include "RivHexGridIntersectionTools.h"
|
||||
#include "RivSurfacePartMgr.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimSurfaceInView, "SurfaceInView" );
|
||||
@ -32,11 +36,9 @@ RimSurfaceInView::RimSurfaceInView()
|
||||
{
|
||||
CAF_PDM_InitObject( "Surface", ":/ReservoirSurface16x16.png", "", "" );
|
||||
|
||||
CAF_PDM_InitField( &m_isActive, "IsActive", true, "Visible", "", "", "" );
|
||||
m_isActive.uiCapability()->setUiHidden( true );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_name, "Name", "Name", "", "", "" );
|
||||
m_name.registerGetMethod( this, &RimSurfaceInView::name );
|
||||
m_name.uiCapability()->setUiReadOnly( true );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_surface, "SurfaceRef", "Surface", "", "", "" );
|
||||
m_surface.uiCapability()->setUiHidden( true );
|
||||
@ -57,11 +59,6 @@ QString RimSurfaceInView::name() const
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSurfaceInView::loadDataAndUpdate() {}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -78,14 +75,6 @@ void RimSurfaceInView::setSurface( RimSurface* surf )
|
||||
m_surface = surf;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimSurfaceInView::isActive()
|
||||
{
|
||||
return m_isActive();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -117,6 +106,37 @@ void RimSurfaceInView::fieldChangedByUi( const caf::PdmFieldHandle* changedField
|
||||
this->firstAncestorOrThisOfTypeAsserted( ownerView );
|
||||
ownerView->scheduleCreateDisplayModelAndRedraw();
|
||||
}
|
||||
else if ( changedField == &m_showInactiveCells )
|
||||
{
|
||||
m_surfacePartMgr = nullptr;
|
||||
RimGridView* ownerView;
|
||||
this->firstAncestorOrThisOfTypeAsserted( ownerView );
|
||||
ownerView->scheduleCreateDisplayModelAndRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSurfaceInView::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_name );
|
||||
|
||||
uiOrdering.add( &m_showInactiveCells );
|
||||
|
||||
this->defineSeparateDataSourceUi( uiConfigName, uiOrdering );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimIntersectionResultsDefinitionCollection* RimSurfaceInView::findSeparateResultsCollection()
|
||||
{
|
||||
RimGridView* view;
|
||||
this->firstAncestorOrThisOfTypeAsserted( view );
|
||||
return view->separateSurfaceResultsCollection();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -126,11 +146,3 @@ caf::PdmFieldHandle* RimSurfaceInView::userDescriptionField()
|
||||
{
|
||||
return &m_name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmFieldHandle* RimSurfaceInView::objectToggleField()
|
||||
{
|
||||
return &m_isActive;
|
||||
}
|
||||
|
@ -24,10 +24,14 @@
|
||||
|
||||
#include "cvfObject.h"
|
||||
|
||||
class RimSurface;
|
||||
class RivSurfacePartMgr;
|
||||
#include "RimIntersection.h"
|
||||
|
||||
class RimSurfaceInView : public caf::PdmObject
|
||||
class RimSurface;
|
||||
|
||||
class RivSurfacePartMgr;
|
||||
class RivIntersectionHexGridInterface;
|
||||
|
||||
class RimSurfaceInView : public RimIntersection
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
@ -35,25 +39,23 @@ public:
|
||||
RimSurfaceInView();
|
||||
~RimSurfaceInView() override;
|
||||
|
||||
void loadDataAndUpdate();
|
||||
|
||||
QString name() const;
|
||||
QString name() const override;
|
||||
RimSurface* surface() const;
|
||||
void setSurface( RimSurface* surf );
|
||||
bool isActive();
|
||||
|
||||
void clearGeometry();
|
||||
RivSurfacePartMgr* surfacePartMgr();
|
||||
|
||||
private:
|
||||
virtual RimIntersectionResultsDefinitionCollection* findSeparateResultsCollection() override;
|
||||
|
||||
caf::PdmFieldHandle* userDescriptionField() override;
|
||||
caf::PdmFieldHandle* objectToggleField() override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue ) override;
|
||||
virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
caf::PdmProxyValueField<QString> m_name;
|
||||
caf::PdmField<bool> m_isActive;
|
||||
caf::PdmPtrField<RimSurface*> m_surface;
|
||||
|
||||
cvf::ref<RivSurfacePartMgr> m_surfacePartMgr;
|
||||
|
@ -102,7 +102,8 @@ void RimSurfaceInViewCollection::appendPartsToModel( cvf::ModelBasicList* model,
|
||||
{
|
||||
if ( surf->isActive() )
|
||||
{
|
||||
surf->surfacePartMgr()->appendNativeGeometryPartsToModel( model, scaleTransform );
|
||||
// surf->surfacePartMgr()->appendNativeGeometryPartsToModel( model, scaleTransform );
|
||||
surf->surfacePartMgr()->appendIntersectionGeometryPartsToModel( model, scaleTransform );
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,3 +148,28 @@ caf::PdmFieldHandle* RimSurfaceInViewCollection::objectToggleField()
|
||||
{
|
||||
return &m_isActive;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSurfaceInViewCollection::updateCellResultColor( bool hasGeneralCellResult, size_t timeStepIndex )
|
||||
{
|
||||
if ( !this->m_isActive() ) return;
|
||||
|
||||
for ( RimSurfaceInView* surf : m_surfacesInView )
|
||||
{
|
||||
if ( surf->isActive() )
|
||||
{
|
||||
bool hasSeparateInterResult = false; // surf->activeSeparateResultDefinition() &&
|
||||
// surf->activeSeparateResultDefinition()->hasResult();
|
||||
if ( hasSeparateInterResult || hasGeneralCellResult )
|
||||
{
|
||||
surf->surfacePartMgr()->updateCellResultColor( timeStepIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
surf->surfacePartMgr()->applySingleColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
void updateFromSurfaceCollection();
|
||||
|
||||
void appendPartsToModel( cvf::ModelBasicList* surfaceVizModel, cvf::Transform* scaleTransform );
|
||||
void updateCellResultColor( bool hasGeneralCellResult, size_t timeStepIndex );
|
||||
|
||||
private:
|
||||
caf::PdmFieldHandle* objectToggleField() override;
|
||||
|
@ -525,3 +525,137 @@ TEST( RigWellPathStimplanIntersector, intersection )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Test of whether we can transport edge information trough clipper clipping
|
||||
// Seems as if it might be possible, but clipper will ignore the edge information
|
||||
// processed by the callback if one of the edges is horizontal
|
||||
//
|
||||
|
||||
#include "clipper/clipper.hpp"
|
||||
double clipperConversionFactor2 = 10000; // For transform to clipper int
|
||||
|
||||
ClipperLib::IntPoint toClipperEdgePoint( const cvf::Vec3d& cvfPoint )
|
||||
{
|
||||
int xInt = cvfPoint.x() * clipperConversionFactor2;
|
||||
int yInt = cvfPoint.y() * clipperConversionFactor2;
|
||||
int zInt = cvfPoint.z();
|
||||
return ClipperLib::IntPoint( xInt, yInt, zInt );
|
||||
}
|
||||
|
||||
cvf::Vec3d fromClipperEdgePoint( const ClipperLib::IntPoint& clipPoint )
|
||||
{
|
||||
double zDValue;
|
||||
|
||||
if ( clipPoint.Z == std::numeric_limits<int>::max() )
|
||||
{
|
||||
zDValue = HUGE_VAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
zDValue = clipPoint.Z;
|
||||
}
|
||||
|
||||
return cvf::Vec3d( clipPoint.X / clipperConversionFactor2, clipPoint.Y / clipperConversionFactor2, zDValue );
|
||||
}
|
||||
|
||||
void swapPointsIfNeedeed( ClipperLib::IntPoint*& p1, ClipperLib::IntPoint*& p2 )
|
||||
{
|
||||
if ( p1->Z > p2->Z )
|
||||
{
|
||||
std::swap( p1, p2 );
|
||||
}
|
||||
|
||||
if ( ( p2->Z - p1->Z ) > 1 ) // End edge of polygon
|
||||
{
|
||||
std::swap( p1, p2 ); // Swap back
|
||||
}
|
||||
}
|
||||
|
||||
void clipperEdgeIntersectCallback( ClipperLib::IntPoint& e1bot,
|
||||
ClipperLib::IntPoint& e1top,
|
||||
ClipperLib::IntPoint& e2bot,
|
||||
ClipperLib::IntPoint& e2top,
|
||||
ClipperLib::IntPoint& pt )
|
||||
{
|
||||
ClipperLib::IntPoint* e11 = &e1bot;
|
||||
ClipperLib::IntPoint* e12 = &e1top;
|
||||
ClipperLib::IntPoint* e21 = &e2bot;
|
||||
ClipperLib::IntPoint* e22 = &e2top;
|
||||
|
||||
swapPointsIfNeedeed( e11, e12 );
|
||||
swapPointsIfNeedeed( e21, e22 );
|
||||
|
||||
cvf::Vec3f e1( e12->X - e11->X, e12->Y - e11->Y, 0.0 );
|
||||
cvf::Vec3f e2( e22->X - e21->X, e22->Y - e21->Y, 0.0 );
|
||||
|
||||
cvf::Vec3f up = e1 ^ e2;
|
||||
if ( up.z() > 0 )
|
||||
{
|
||||
pt.Z = e12->Z;
|
||||
std::cout << "E1 :" << e11->Z << " " << e12->Z << std::endl;
|
||||
std::cout << "E2 :" << e21->Z << " " << e22->Z << std::endl << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
pt.Z = e22->Z;
|
||||
std::cout << "E1 :" << e21->Z << " " << e22->Z << std::endl;
|
||||
std::cout << "E2 :" << e11->Z << " " << e12->Z << std::endl << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
TEST( RigCellGeometryTools, ClipperEdgeTracking )
|
||||
{
|
||||
// If the first edges of the polygons are horizontal, the edge tracking will fail.
|
||||
// Encode polygon and edge into Z coordinate of the vertex
|
||||
|
||||
std::vector<cvf::Vec3d> polygon1 = {{0.0, 0.51, 1002.0}, {1.0, 0.5, 1000.0}, {0.0, 1.0, 1001.0}};
|
||||
std::vector<cvf::Vec3d> polygon2 = {{0.5, 0.01, 2002.0}, {1.0, 0.0, 2000.0}, {0.5, 1.0, 2001.0}};
|
||||
|
||||
std::vector<std::vector<cvf::Vec3d>> clippedPolygons;
|
||||
|
||||
// Convert to int for clipper library and store as clipper "path"
|
||||
ClipperLib::Path polygon1path;
|
||||
for ( const cvf::Vec3d& v : polygon1 )
|
||||
{
|
||||
polygon1path.push_back( toClipperEdgePoint( v ) );
|
||||
}
|
||||
|
||||
ClipperLib::Path polygon2path;
|
||||
for ( const cvf::Vec3d& v : polygon2 )
|
||||
{
|
||||
polygon2path.push_back( toClipperEdgePoint( v ) );
|
||||
}
|
||||
|
||||
ClipperLib::Clipper clpr;
|
||||
clpr.AddPath( polygon1path, ClipperLib::ptSubject, true );
|
||||
clpr.AddPath( polygon2path, ClipperLib::ptClip, true );
|
||||
|
||||
clpr.ZFillFunction( &clipperEdgeIntersectCallback );
|
||||
|
||||
ClipperLib::Paths solution;
|
||||
clpr.Execute( ClipperLib::ctIntersection, solution, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd );
|
||||
|
||||
// Convert back to std::vector<std::vector<cvf::Vec3d> >
|
||||
for ( ClipperLib::Path pathInSol : solution )
|
||||
{
|
||||
std::vector<cvf::Vec3d> clippedPolygon;
|
||||
for ( ClipperLib::IntPoint IntPosition : pathInSol )
|
||||
{
|
||||
clippedPolygon.push_back( fromClipperEdgePoint( IntPosition ) );
|
||||
}
|
||||
clippedPolygons.push_back( clippedPolygon );
|
||||
}
|
||||
|
||||
int pIdx = 1;
|
||||
for ( auto& polygon : clippedPolygons )
|
||||
{
|
||||
std::cout << "Polygon: " << pIdx << std::endl;
|
||||
for ( auto& point : polygon )
|
||||
{
|
||||
std::cout << " [ " << point[0] << ", " << point[1] << ", " << point[2] << " ]" << std::endl;
|
||||
}
|
||||
pIdx++;
|
||||
}
|
||||
}
|
||||
|
@ -381,6 +381,7 @@ set_property(TARGET cafCommandFeatures PROPERTY FOLDER "AppFwk")
|
||||
#add_subdirectory(Fwk/AppFwk/cafTests/cafTestCvfApplication)
|
||||
|
||||
add_subdirectory(Fwk/AppFwk/cafTensor)
|
||||
add_subdirectory(Fwk/AppFwk/cafHexInterpolator)
|
||||
|
||||
list(APPEND APP_FWK_LIBRARIES
|
||||
cafPdmCore
|
||||
@ -401,6 +402,7 @@ list(APPEND APP_FWK_LIBRARIES
|
||||
|
||||
set_property(TARGET
|
||||
${APP_FWK_LIBRARIES}
|
||||
cafHexInterpolator
|
||||
PROPERTY FOLDER "AppFwk"
|
||||
)
|
||||
|
||||
|
21
Fwk/AppFwk/cafHexInterpolator/CMakeLists.txt
Normal file
21
Fwk/AppFwk/cafHexInterpolator/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
cmake_minimum_required (VERSION 2.8.12)
|
||||
|
||||
project (cafHexInterpolator)
|
||||
|
||||
set( PROJECT_FILES
|
||||
cafHexInterpolator.h
|
||||
)
|
||||
|
||||
|
||||
add_library( ${PROJECT_NAME}
|
||||
${PROJECT_FILES}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries( ${PROJECT_NAME} LibCore )
|
||||
|
||||
source_group("" FILES ${PROJECT_FILES})
|
381
Fwk/AppFwk/cafHexInterpolator/cafHexInterpolator.h
Normal file
381
Fwk/AppFwk/cafHexInterpolator/cafHexInterpolator.h
Normal file
@ -0,0 +1,381 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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.
|
||||
//
|
||||
// This library 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.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
/*
|
||||
Interpolating inside a general 8 node hexahedral element
|
||||
Calculating an interpolated value at a position inside the element from values at each corner.
|
||||
Author Jacob Støren
|
||||
|
||||
| v1 |
|
||||
Vectors: [v] = | v2 | = { v1, v2, v3 }
|
||||
| v3 |
|
||||
|
||||
the {} means that the elment list are a standing vector, but written as a row for convenience
|
||||
[] means matrix or vector quantity
|
||||
|
||||
// HEX8
|
||||
// 7---------6
|
||||
// /| /| |k, z,
|
||||
// / | / | | /j, y
|
||||
// 4---------5 | |/
|
||||
// | 3------|--2 *---i, x,
|
||||
// | / | /
|
||||
// |/ |/
|
||||
// 0---------1
|
||||
|
||||
Normalized coordinates i, j, k
|
||||
Normalized origo in center of element
|
||||
Normalized cell corners NCn in :
|
||||
|
||||
[NC0] = {-1,-1,-1}
|
||||
[NC1] = { 1,-1,-1}
|
||||
[NC2] = { 1, 1,-1}
|
||||
[NC3] = {-1, 1,-1}
|
||||
[NC4] = {-1,-1, 1}
|
||||
[NC5] = { 1,-1, 1}
|
||||
[NC6] = { 1, 1, 1}
|
||||
[NC7] = {-1, 1, 1}
|
||||
|
||||
Thus Interpolation polynomials (follows sign of corner position) Nn =
|
||||
|
||||
N0 = 1/8 *(1-i)(1-j)(1-k) = 1/8 * ( 1 - i - j - k + ij + ik + jk - ijk )
|
||||
N1 = 1/8 *(1+i)(1-j)(1-k) = 1/8 * ( 1 + i - j - k - ij - ik + jk + ijk )
|
||||
N2 = 1/8 *(1+i)(1+j)(1-k) = 1/8 * ( 1 + i + j - k + ij - ik - jk - ijk )
|
||||
N3 = 1/8 *(1-i)(1+j)(1-k) = 1/8 * ( 1 - i + j - k - ij + ik - jk + ijk )
|
||||
N4 = 1/8 *(1-i)(1-j)(1+k) = 1/8 * ( 1 - i - j + k + ij - ik - jk + ijk )
|
||||
N5 = 1/8 *(1+i)(1-j)(1+k) = 1/8 * ( 1 + i - j + k - ij + ik - jk - ijk )
|
||||
N6 = 1/8 *(1+i)(1+j)(1+k) = 1/8 * ( 1 + i + j + k + ij + ik + jk + ijk )
|
||||
N7 = 1/8 *(1-i)(1+j)(1+k) = 1/8 * ( 1 - i + j + k - ij - ik + jk - ijk )
|
||||
|
||||
To calculate an interpolated value R at position { i, j, k } from values Vn in each corner of the cell
|
||||
we use i,j,k to calculate all Nn, and then :
|
||||
|
||||
R = sum_n(Nn * Vn)
|
||||
|
||||
A point [P] = {x,y,z} inside a general element can then be calculated by the {i,j,k} coordinates correponding to the point and the corner positions Cn = {Cx_n, Cy_n, Cz_n} (n = 0..7) of the general hex as:
|
||||
|
||||
x = sum_n(Nn * Cn_x)
|
||||
y = sum_n(Nn * Cn_y)
|
||||
z = sum_n(Nn * Cn_z)
|
||||
|
||||
If we define
|
||||
|
||||
[Cn] = | [C0] ... [C7] |
|
||||
|
||||
Where
|
||||
| Cx_0 | | Cx_7 |
|
||||
[C0] = | Cy_0 |, ... , [C7] = | Cy_7 |
|
||||
| Cz_0 | | Cz_7 |
|
||||
And
|
||||
| N0 |
|
||||
[Nn] = | .. |
|
||||
| N7 |
|
||||
|
||||
it can be written
|
||||
|
||||
[P] = [Cn]*[Nn]
|
||||
|
||||
As seen, we need to know the { i, j, k} position of the point. This can only be calculated using some sort of iterative solution, eg. Newton-Rapson.
|
||||
Using m as iteration number we can use { im, jm, km } to evaluate [Nn] and name it [Nnm].
|
||||
We use an initial guess of {im,jm,km} = { 0.5, 0.5, 0.5} // But why ? the element origo is at 0,0,0 !
|
||||
|
||||
[Pm] = {xm, ym, zm} = sum_n(Nnm * Cn_x), sum_n(Nnm * Cn_y), sum_n(Nnm * Cn_z) } When using im,jm,km to evaluate Nnm
|
||||
|
||||
P is the position we want to calculate i,j,k for.
|
||||
So our function to solve for roots become F = Pm - P = 0
|
||||
|
||||
Then multidimensional Newton-Rapson says:
|
||||
|
||||
{im, jm, km}_new = {im,jm,km} - [J-1]_m * ( [Pm] - [P] ) }
|
||||
|
||||
Where [J-1] is the inverse Jacobian giving the change in i,j,k when varying x,y,z (The partial derivatives)
|
||||
|
||||
The Jacobian is the partially derived x, y, z with respect to i, j, k as follows:
|
||||
( The organization of the Jacobi is not quite concistent in the litterature.
|
||||
It seems as if NTNU uses the following, while others use the Transpose.
|
||||
(Seems as if the correct one to use in the newton-rapson iteration is the transpose of the following: )
|
||||
|
||||
| dx/di dy/di dz/di |
|
||||
J = | dx/dj dy/dj dz/dj |
|
||||
| dx/dk dy/dk dz/dk |
|
||||
|
||||
The partial derivatives are calculated by deriving the function [F(i,j,k)] = [Pm(i,j,k)] - [P]
|
||||
Since [P] is constant, this is the same as deriving [Pm(i,j,k)] = [Cn]*[Nnm]
|
||||
Explicitly:
|
||||
|
||||
|xm| | N0m*C0_x + ... + N7m*C7_x |
|
||||
[Pm] = |ym| = | N0m*C0_y + ... + N7m*C7_y |
|
||||
|zm| | N0m*C0_z + ... + N7m*C7_z |
|
||||
|
||||
|
||||
In the following we remove the iteration index m for simplicity
|
||||
The elements of the Jacobi can be calculated by partially deriving the polynomials for each of the components x, y, z
|
||||
|
||||
dx/di = (dN0/di)*C0_x + ... + (dN7/di)*C7_x
|
||||
dx/dj = (dN0/dj)*C0_x + ... + (dN7/dj)*C7_x
|
||||
dx/dk = (dN0/dk)*C0_x + ... + (dN7/dk)*C7_x
|
||||
|
||||
dy/di = (dN0/di)*C0_y + ... + (dN7/di)*C7_y
|
||||
dy/dj = (dN0/dj)*C0_y + ... + (dN7/dj)*C7_y
|
||||
dy/dk = (dN0/dk)*C0_y + ... + (dN7/dk)*C7_y
|
||||
|
||||
dz/di = (dN0/di)*C0_z + ... + (dN7/di)*C7_z
|
||||
dz/dj = (dN0/dj)*C0_z + ... + (dN7/dj)*C7_z
|
||||
dz/dk = (dN0/dk)*C0_z + ... + (dN7/dk)*C7_z
|
||||
|
||||
Which can be written in more compact form:
|
||||
| dx/di |
|
||||
| dy/di | = [Cn]*[dNn/di]
|
||||
| dz/di |
|
||||
|
||||
, etc.
|
||||
|
||||
|
||||
And in detail every partial derivative of the polynomials:
|
||||
|
||||
dN0/di = 1/8 * ( - 1 + j + k - jk )
|
||||
dN1/di = 1/8 * ( + 1 - j - k + jk )
|
||||
dN2/di = 1/8 * ( + i + j - k - jk )
|
||||
dN3/di = 1/8 * ( - 1 - j + k + jk )
|
||||
dN4/di = 1/8 * ( - 1 + j - k + jk )
|
||||
dN5/di = 1/8 * ( + 1 - j + k - jk )
|
||||
dN6/di = 1/8 * ( + 1 + j + k + jk )
|
||||
dN7/di = 1/8 * ( - 1 - j - k - jk )
|
||||
|
||||
dN0/dj = 1/8 * ( - 1 + i + k - ik )
|
||||
dN1/dj = 1/8 * ( - 1 - i + k + ik )
|
||||
dN2/dj = 1/8 * ( + 1 + i - k - ik )
|
||||
dN3/dj = 1/8 * ( + 1 - i - k + ik )
|
||||
dN4/dj = 1/8 * ( - 1 + i - k + ik )
|
||||
dN5/dj = 1/8 * ( - 1 - i - k - ik )
|
||||
dN6/dj = 1/8 * ( + 1 + i + k + ik )
|
||||
dN7/dj = 1/8 * ( + 1 - i + k - ik )
|
||||
|
||||
dN0/dk = 1/8 * ( - 1 + i + j - ij )
|
||||
dN1/dk = 1/8 * ( - 1 - i + j + ij )
|
||||
dN2/dk = 1/8 * ( - 1 - i - j - ij )
|
||||
dN3/dk = 1/8 * ( - 1 + i - j + ij )
|
||||
dN4/dk = 1/8 * ( + 1 - i - j + ij )
|
||||
dN5/dk = 1/8 * ( + 1 + i - j - ij )
|
||||
dN6/dk = 1/8 * ( + 1 + i + j + ij )
|
||||
dN7/dk = 1/8 * ( + 1 - i + j - ij )
|
||||
|
||||
The inverse Jacobian can be calculated by inverting the resulting Jacobian matrix for a specifically chosen set of i,j,k
|
||||
*/
|
||||
|
||||
#include "cvfVector3.h"
|
||||
#include "cvfMatrix3.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace caf {
|
||||
|
||||
class HexInterpolator
|
||||
{
|
||||
public:
|
||||
static double interpolateHex(const std::array<cvf::Vec3d, 8>& hexCorners,
|
||||
const std::array<double, 8>& values,
|
||||
const cvf::Vec3d& point)
|
||||
{
|
||||
cvf::Vec3d pointInNormElm = findNormalizedCoords(hexCorners, point);
|
||||
return interpolateInNormElm( pointInNormElm, values);
|
||||
}
|
||||
|
||||
static std::array<double, 8> vertexWeights(const std::array<cvf::Vec3d, 8>& hexCorners,
|
||||
const cvf::Vec3d& point )
|
||||
{
|
||||
cvf::Vec3d pointInNormElm = findNormalizedCoords(hexCorners, point);
|
||||
return interpolationCoeffs(pointInNormElm);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static double interpolateInNormElm( const cvf::Vec3d & pointInNormElm, const std::array<double, 8>& values)
|
||||
{
|
||||
std::array<double, 8> Ni = interpolationCoeffs(pointInNormElm);
|
||||
|
||||
double result = 0.0;
|
||||
|
||||
for (int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
result += values[i]*Ni[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static cvf::Vec3d interpolateInNormElm( const cvf::Vec3d & pointInNormElm, const std::array<cvf::Vec3d, 8>& values)
|
||||
{
|
||||
std::array<double, 8> Ni = interpolationCoeffs(pointInNormElm);
|
||||
|
||||
cvf::Vec3d result(cvf::Vec3d::ZERO);
|
||||
|
||||
for (int i = 0 ; i < 8 ; ++i )
|
||||
{
|
||||
result += values[i]*Ni[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::array<double, 8> interpolationCoeffs( const cvf::Vec3d & pointInNormalizedElement)
|
||||
{
|
||||
const double k_1_8 = 0.125;
|
||||
|
||||
double i = pointInNormalizedElement[0];
|
||||
double j = pointInNormalizedElement[1];
|
||||
double k = pointInNormalizedElement[2];
|
||||
|
||||
// could use as optimization ... >> double oni = 1 - i;
|
||||
// could use as optimization ... >> double opi = 1 + i;
|
||||
// could use as optimization ... >> double onj = 1 - j;
|
||||
// could use as optimization ... >> double opj = 1 + j;
|
||||
// could use as optimization ... >> double onk = 1 - k;
|
||||
// could use as optimization ... >> double opk = 1 + k;
|
||||
|
||||
return {
|
||||
k_1_8 *(1-i)*(1-j)*(1-k),
|
||||
k_1_8 *(1+i)*(1-j)*(1-k),
|
||||
k_1_8 *(1+i)*(1+j)*(1-k),
|
||||
k_1_8 *(1-i)*(1+j)*(1-k),
|
||||
k_1_8 *(1-i)*(1-j)*(1+k),
|
||||
k_1_8 *(1+i)*(1-j)*(1+k),
|
||||
k_1_8 *(1+i)*(1+j)*(1+k),
|
||||
k_1_8 *(1-i)*(1+j)*(1+k)
|
||||
};
|
||||
}
|
||||
|
||||
static cvf::Vec3d findNormalizedCoords(const std::array<cvf::Vec3d, 8>& hexCorners, const cvf::Vec3d& P)
|
||||
{
|
||||
cvf::Vec3d normPoint = {0.0, 0.0, 0.0}; // Start value
|
||||
int m = 0;
|
||||
while ( m < 5 )
|
||||
{
|
||||
cvf::Vec3d Pm = interpolateInNormElm(normPoint, hexCorners);
|
||||
cvf::Vec3d Pdiff = Pm - P;
|
||||
|
||||
cvf::Mat3d J_inv = jacobi(hexCorners, normPoint) ;
|
||||
bool inversionOk = J_inv.invert();
|
||||
if ( !inversionOk ) break;
|
||||
|
||||
cvf::Vec3d ijkStep = Pdiff.getTransformedVector(J_inv);
|
||||
|
||||
normPoint = normPoint - ijkStep;
|
||||
|
||||
m++;
|
||||
}
|
||||
|
||||
return normPoint;
|
||||
}
|
||||
|
||||
static cvf::Mat3d jacobi(const std::array<cvf::Vec3d, 8>& hexCorners, const cvf::Vec3d & pointInNormalizedElement)
|
||||
{
|
||||
const double k_1_8 = 0.125;
|
||||
|
||||
double i = pointInNormalizedElement[0];
|
||||
double j = pointInNormalizedElement[1];
|
||||
double k = pointInNormalizedElement[2];
|
||||
|
||||
double ij = i*j;
|
||||
double ik = i*k;
|
||||
double jk = j*k;
|
||||
|
||||
double C0_x = hexCorners[0][0]; double C0_y = hexCorners[0][1]; double C0_z = hexCorners[0][2];
|
||||
double C1_x = hexCorners[1][0]; double C1_y = hexCorners[1][1]; double C1_z = hexCorners[1][2];
|
||||
double C2_x = hexCorners[2][0]; double C2_y = hexCorners[2][1]; double C2_z = hexCorners[2][2];
|
||||
double C3_x = hexCorners[3][0]; double C3_y = hexCorners[3][1]; double C3_z = hexCorners[3][2];
|
||||
double C4_x = hexCorners[4][0]; double C4_y = hexCorners[4][1]; double C4_z = hexCorners[4][2];
|
||||
double C5_x = hexCorners[5][0]; double C5_y = hexCorners[5][1]; double C5_z = hexCorners[5][2];
|
||||
double C6_x = hexCorners[6][0]; double C6_y = hexCorners[6][1]; double C6_z = hexCorners[6][2];
|
||||
double C7_x = hexCorners[7][0]; double C7_y = hexCorners[7][1]; double C7_z = hexCorners[7][2];
|
||||
|
||||
double dN0_di = k_1_8 * (- 1 + j + k - jk);
|
||||
double dN1_di = k_1_8 * (+ 1 - j - k + jk);
|
||||
double dN2_di = k_1_8 * (+ 1 + j - k - jk);
|
||||
double dN3_di = k_1_8 * (- 1 - j + k + jk);
|
||||
double dN4_di = k_1_8 * (- 1 + j - k + jk);
|
||||
double dN5_di = k_1_8 * (+ 1 - j + k - jk);
|
||||
double dN6_di = k_1_8 * (+ 1 + j + k + jk);
|
||||
double dN7_di = k_1_8 * (- 1 - j - k - jk);
|
||||
|
||||
double dN0_dj = k_1_8 * (- 1 + i + k - ik);
|
||||
double dN1_dj = k_1_8 * (- 1 - i + k + ik);
|
||||
double dN2_dj = k_1_8 * (+ 1 + i - k - ik);
|
||||
double dN3_dj = k_1_8 * (+ 1 - i - k + ik);
|
||||
double dN4_dj = k_1_8 * (- 1 + i - k + ik);
|
||||
double dN5_dj = k_1_8 * (- 1 - i - k - ik);
|
||||
double dN6_dj = k_1_8 * (+ 1 + i + k + ik);
|
||||
double dN7_dj = k_1_8 * (+ 1 - i + k - ik);
|
||||
|
||||
double dN0_dk = k_1_8 * (- 1 + i + j - ij);
|
||||
double dN1_dk = k_1_8 * (- 1 - i + j + ij);
|
||||
double dN2_dk = k_1_8 * (- 1 - i - j - ij);
|
||||
double dN3_dk = k_1_8 * (- 1 + i - j + ij);
|
||||
double dN4_dk = k_1_8 * (+ 1 - i - j + ij);
|
||||
double dN5_dk = k_1_8 * (+ 1 + i - j - ij);
|
||||
double dN6_dk = k_1_8 * (+ 1 + i + j + ij);
|
||||
double dN7_dk = k_1_8 * (+ 1 - i + j - ij);
|
||||
|
||||
double dx_di = (dN0_di) * C0_x + (dN1_di) * C1_x + (dN2_di) * C2_x + (dN3_di) * C3_x + (dN4_di) * C4_x + (dN5_di) * C5_x + (dN6_di) * C6_x + (dN7_di) * C7_x;
|
||||
double dx_dj = (dN0_dj) * C0_x + (dN1_dj) * C1_x + (dN2_dj) * C2_x + (dN3_dj) * C3_x + (dN4_dj) * C4_x + (dN5_dj) * C5_x + (dN6_dj) * C6_x + (dN7_dj) * C7_x;
|
||||
double dx_dk = (dN0_dk) * C0_x + (dN1_dk) * C1_x + (dN2_dk) * C2_x + (dN3_dk) * C3_x + (dN4_dk) * C4_x + (dN5_dk) * C5_x + (dN6_dk) * C6_x + (dN7_dk) * C7_x;
|
||||
|
||||
double dy_di = (dN0_di) * C0_y + (dN1_di) * C1_y + (dN2_di) * C2_y + (dN3_di) * C3_y + (dN4_di) * C4_y + (dN5_di) * C5_y + (dN6_di) * C6_y + (dN7_di) * C7_y;
|
||||
double dy_dj = (dN0_dj) * C0_y + (dN1_dj) * C1_y + (dN2_dj) * C2_y + (dN3_dj) * C3_y + (dN4_dj) * C4_y + (dN5_dj) * C5_y + (dN6_dj) * C6_y + (dN7_dj) * C7_y;
|
||||
double dy_dk = (dN0_dk) * C0_y + (dN1_dk) * C1_y + (dN2_dk) * C2_y + (dN3_dk) * C3_y + (dN4_dk) * C4_y + (dN5_dk) * C5_y + (dN6_dk) * C6_y + (dN7_dk) * C7_y;
|
||||
|
||||
double dz_di = (dN0_di) * C0_z + (dN1_di) * C1_z + (dN2_di) * C2_z + (dN3_di) * C3_z + (dN4_di) * C4_z + (dN5_di) * C5_z + (dN6_di) * C6_z + (dN7_di) * C7_z;
|
||||
double dz_dj = (dN0_dj) * C0_z + (dN1_dj) * C1_z + (dN2_dj) * C2_z + (dN3_dj) * C3_z + (dN4_dj) * C4_z + (dN5_dj) * C5_z + (dN6_dj) * C6_z + (dN7_dj) * C7_z;
|
||||
double dz_dk = (dN0_dk) * C0_z + (dN1_dk) * C1_z + (dN2_dk) * C2_z + (dN3_dk) * C3_z + (dN4_dk) * C4_z + (dN5_dk) * C5_z + (dN6_dk) * C6_z + (dN7_dk) * C7_z;
|
||||
|
||||
// Do not know which ordering ends up as correct
|
||||
|
||||
#if 1 // Use literature jacobi ordering
|
||||
return cvf::Mat3d(
|
||||
dx_di, dx_dj, dx_dk,
|
||||
dy_di, dy_dj, dy_dk,
|
||||
dz_di, dz_dj, dz_dk
|
||||
);
|
||||
#else // use NTNU ordering
|
||||
return cvf::Mat3d(
|
||||
dx_di, dy_di, dz_di,
|
||||
dx_dj, dy_dj, dz_dj,
|
||||
dx_dk, dy_dk, dz_dk
|
||||
);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
cmake_minimum_required (VERSION 2.8.12)
|
||||
|
||||
project ( cafHexInterpolator_UnitTests )
|
||||
|
||||
if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11))
|
||||
# VS 2017 : Disable warnings from from gtest code, using deprecated code related to TR1
|
||||
add_definitions(-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
|
||||
message(STATUS "Add flag to disable warings from gtest - _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING")
|
||||
endif()
|
||||
|
||||
set (VIZ_MODULES_FOLDER_NAME ../../../../Fwk/VizFwk)
|
||||
add_subdirectory(${VIZ_MODULES_FOLDER_NAME}/LibCore LibCoreDir})
|
||||
|
||||
include_directories (
|
||||
${CMAKE_CURRENT_SOURCE_DIR} # required for gtest-all.cpp
|
||||
)
|
||||
|
||||
set( PROJECT_FILES
|
||||
cafHexInterpolatorBasicTest.cpp
|
||||
cafHexInterpolator_UnitTests_main.cpp
|
||||
)
|
||||
|
||||
# add the executable
|
||||
add_executable (${PROJECT_NAME}
|
||||
${PROJECT_FILES}
|
||||
gtest/gtest-all.cpp
|
||||
)
|
||||
|
||||
target_link_libraries ( ${PROJECT_NAME}
|
||||
LibCore
|
||||
)
|
||||
|
||||
source_group("" FILES ${PROJECT_FILES})
|
||||
|
@ -0,0 +1,331 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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.
|
||||
//
|
||||
// This library 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.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include <iostream>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "../cafHexInterpolator.h"
|
||||
#include "cvfMatrix4.h"
|
||||
|
||||
namespace caf {
|
||||
class HexInterpolatorTester
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
void testHex(const std::array<cvf::Vec3d, 8>& hexCorners, double tolerance = 1e-6)
|
||||
{
|
||||
double result = 0.0;
|
||||
result = caf::HexInterpolator::interpolateHex(hexCorners, {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0 }, hexCorners[0]);
|
||||
EXPECT_NEAR(result, 0.0, tolerance);
|
||||
result = caf::HexInterpolator::interpolateHex(hexCorners, {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0 }, hexCorners[1]);
|
||||
EXPECT_NEAR(result, 1.0, tolerance);
|
||||
result = caf::HexInterpolator::interpolateHex(hexCorners, {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0 }, hexCorners[2]);
|
||||
EXPECT_NEAR(result, 2.0, tolerance);
|
||||
result = caf::HexInterpolator::interpolateHex(hexCorners, {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0 }, hexCorners[3]);
|
||||
EXPECT_NEAR(result, 3.0, tolerance);
|
||||
result = caf::HexInterpolator::interpolateHex(hexCorners, {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0 }, hexCorners[4]);
|
||||
EXPECT_NEAR(result, 4.0, tolerance);
|
||||
result = caf::HexInterpolator::interpolateHex(hexCorners, {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0 }, hexCorners[5]);
|
||||
EXPECT_NEAR(result, 5.0, tolerance);
|
||||
result = caf::HexInterpolator::interpolateHex(hexCorners, {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0 }, hexCorners[6]);
|
||||
EXPECT_NEAR(result, 6.0, tolerance);
|
||||
result = caf::HexInterpolator::interpolateHex(hexCorners, {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0 }, hexCorners[7]);
|
||||
EXPECT_NEAR(result, 7.0, tolerance);
|
||||
|
||||
cvf::Vec3d avg = cvf::Vec3d::ZERO;
|
||||
for ( const auto & v : hexCorners) avg += v;
|
||||
avg *= 0.125;
|
||||
result = caf::HexInterpolator::interpolateHex(hexCorners, {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0 }, avg);
|
||||
EXPECT_NEAR(result, 3.5, tolerance);
|
||||
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, UnitElement)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
testHex(hexCorners);
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, ScaledElement)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
for ( auto & v : hexCorners) v *= 2;
|
||||
|
||||
testHex(hexCorners);
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, TranslatedElement)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
for ( auto & v : hexCorners) v += {2.2, 4.4, -7.6};
|
||||
|
||||
testHex(hexCorners);
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, RotatedElement)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
cvf::Mat4d rot = cvf::Mat4d::fromRotation({1,1, 0}, 3.14159);
|
||||
|
||||
for ( auto & v : hexCorners) v.transformPoint(rot);
|
||||
|
||||
testHex(hexCorners);
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, CombinedUndeformed)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
for ( auto & v : hexCorners) v *= 2;
|
||||
|
||||
for ( auto & v : hexCorners) v += {2.2, 4.4, -7.6};
|
||||
|
||||
cvf::Mat4d rot = cvf::Mat4d::fromRotation({1,1, 0}, 3.14159);
|
||||
|
||||
for ( auto & v : hexCorners) v.transformPoint(rot);
|
||||
|
||||
testHex(hexCorners);
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, Compressed)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
for ( auto & v : hexCorners) v[0] *= 0.1;
|
||||
|
||||
testHex(hexCorners);
|
||||
|
||||
for ( auto & v : hexCorners) v[0] *= 10.0;
|
||||
for ( auto & v : hexCorners) v[1] *= 0.1;
|
||||
|
||||
testHex(hexCorners);
|
||||
|
||||
for ( auto & v : hexCorners) v[1] *= 10.0;
|
||||
for ( auto & v : hexCorners) v[2] *= 0.1;
|
||||
|
||||
testHex(hexCorners);
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, Scewed)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
for ( int i = 4 ; i< 8 ; ++i) hexCorners[i] += {1.0, 0.0, 0.0};
|
||||
|
||||
testHex(hexCorners);
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, Screwed)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
cvf::Mat4d rot = cvf::Mat4d::fromRotation({0, 0, 1}, 1.0*0.25*3.14159);
|
||||
|
||||
for ( int i = 4 ; i< 8 ; ++i) hexCorners[i].transformPoint(rot);
|
||||
|
||||
testHex(hexCorners);
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, Warp)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
{
|
||||
std::array<cvf::Vec3d, 8> cornerCopy = hexCorners;
|
||||
// Compress x
|
||||
for ( auto & v : cornerCopy ) v[0] *= 0.1;
|
||||
|
||||
cornerCopy[0][0] += 0.25;
|
||||
cornerCopy[1][0] += 0.20;
|
||||
cornerCopy[7][0] += 0.25;
|
||||
cornerCopy[6][0] += 0.4;
|
||||
|
||||
testHex(cornerCopy);
|
||||
}
|
||||
|
||||
{
|
||||
std::array<cvf::Vec3d, 8> cornerCopy = hexCorners;
|
||||
// Compress z
|
||||
for ( auto & v : cornerCopy ) v[2] *= 0.1;
|
||||
|
||||
cornerCopy[0][2] += 0.25;
|
||||
cornerCopy[2][2] += 0.25;
|
||||
cornerCopy[4][2] += 0.2;
|
||||
cornerCopy[6][2] += 0.4;
|
||||
|
||||
testHex(cornerCopy);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InterpolationTest, TotalCombined)
|
||||
{
|
||||
// Identity element
|
||||
std::array<cvf::Vec3d, 8> hexCorners = {
|
||||
cvf::Vec3d(-1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0,-1.0,-1.0),
|
||||
cvf::Vec3d( 1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0, 1.0,-1.0),
|
||||
cvf::Vec3d(-1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0,-1.0, 1.0),
|
||||
cvf::Vec3d( 1.0, 1.0, 1.0),
|
||||
cvf::Vec3d(-1.0, 1.0, 1.0)
|
||||
};
|
||||
|
||||
cvf::Mat4d rot = cvf::Mat4d::fromRotation({0, 0, 1}, 1.0*0.25*3.14159);
|
||||
|
||||
for ( int i = 4 ; i< 8 ; ++i) hexCorners[i].transformPoint(rot);
|
||||
|
||||
for ( int i = 4 ; i< 8 ; ++i) hexCorners[i] += {0.2, 0.0, 0.0};
|
||||
|
||||
|
||||
{
|
||||
std::array<cvf::Vec3d, 8> cornerCopy = hexCorners;
|
||||
// Compress z
|
||||
for ( auto & v : hexCorners ) v[2] *= 0.3;
|
||||
|
||||
hexCorners[0][2] += 0.25;
|
||||
hexCorners[2][2] += 0.25;
|
||||
hexCorners[4][2] += 0.2;
|
||||
hexCorners[6][2] += 0.4;
|
||||
}
|
||||
|
||||
for ( auto & v : hexCorners) v *= 200;
|
||||
|
||||
for ( auto & v : hexCorners) v += {2.3e5, 4.7e6, -2000};
|
||||
|
||||
cvf::Mat4d rot2 = cvf::Mat4d::fromRotation({1,1, 0}, 3.14159);
|
||||
|
||||
for ( auto & v : hexCorners) v.transformPoint(rot2);
|
||||
|
||||
|
||||
testHex(hexCorners);
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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.
|
||||
//
|
||||
// This library 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.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
int result = RUN_ALL_TESTS();
|
||||
|
||||
char text[5];
|
||||
std::cin.getline(text, 5);
|
||||
|
||||
return result;
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
|
||||
|
||||
|
||||
namespace cvftest {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
static cvf::String getTestDataDir(const cvf::String& unitTestFolder)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::string exe = std::string(testing::internal::GetArgvs()[0]);
|
||||
#else
|
||||
std::string dir = std::string(testing::internal::FilePath::GetCurrentDir().ToString());
|
||||
std::string exe = dir + std::string("/") + std::string(testing::internal::GetArgvs()[0]);
|
||||
#endif
|
||||
std::string testPath = exe.substr(0, exe.find(unitTestFolder.toStdString())) + std::string("TestData/");
|
||||
|
||||
return testPath;
|
||||
}
|
||||
|
||||
static cvf::String getGLSLDir(const cvf::String& unitTestFolder)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::string exe = std::string(testing::internal::GetArgvs()[0]);
|
||||
#else
|
||||
std::string dir = std::string(testing::internal::FilePath::GetCurrentDir().ToString());
|
||||
std::string exe = dir + std::string("/") + std::string(testing::internal::GetArgvs()[0]);
|
||||
#endif
|
||||
std::string glslPath = exe.substr(0, exe.find(unitTestFolder.toStdString())) + std::string("../LibRender/glsl/");
|
||||
|
||||
return glslPath;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
18007
Fwk/AppFwk/cafHexInterpolator/cafHexInterpolator_UnitTest/gtest/gtest.h
Normal file
18007
Fwk/AppFwk/cafHexInterpolator/cafHexInterpolator_UnitTest/gtest/gtest.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@
|
||||
#include <cmath>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
namespace caf {
|
||||
|
||||
@ -502,6 +503,157 @@ void HexGridIntersectionTools::clipTrianglesBetweenTwoParallelPlanes(const std::
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Creates a plane with normal perpendicular to the edge, pointing in the direction of the pointInNormalDirection
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::Plane createPlaneFromEdgeAndPointInNormalDirection(cvf::Vec3d ep1, cvf::Vec3d ep2, cvf::Vec3d pointInNormalDirection)
|
||||
{
|
||||
cvf::Vec3d ep1ep2 = ep2 - ep1;
|
||||
cvf::Vec3d ep1pointforNorm = pointInNormalDirection - ep1;
|
||||
cvf::Vec3d triNormal = ep1ep2^ep1pointforNorm;
|
||||
cvf::Vec3d pointInPlane = ep1 + triNormal;
|
||||
|
||||
cvf::Plane plane;
|
||||
plane.setFromPoints(ep1, pointInPlane, ep2);
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Clips the supplied triangles into new triangles returned in clippedTriangleVxes.
|
||||
// New vertices have set isVxIdsNative = false and their vxIds is indices into triangleVxes
|
||||
// The cellFaceForEachTriangleEdge refer to the edge after the corresponding triangle vertex.
|
||||
// This method will keep the faces provided, while added edges is marked with no face = 6
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void HexGridIntersectionTools::clipPlanarTrianglesWithInPlaneTriangle(const std::vector<cvf::Vec3d>& triangleVxes,
|
||||
const std::vector<int>& cellFaceForEachTriangleEdge,
|
||||
const cvf::Vec3d& tp1,
|
||||
const cvf::Vec3d& tp2,
|
||||
const cvf::Vec3d& tp3,
|
||||
std::vector<cvf::Vec3d>* clippedTriangleVxes,
|
||||
std::vector<int>* cellFaceForEachClippedTriangleEdge)
|
||||
{
|
||||
#define HT_NO_FACE 6
|
||||
|
||||
size_t triangleCount = triangleVxes.size() / 3;
|
||||
|
||||
// Creating a plane for each of the edges of the clipping triangle
|
||||
std::array<cvf::Plane, 3> clipTrianglePlanes;
|
||||
|
||||
clipTrianglePlanes[0] = createPlaneFromEdgeAndPointInNormalDirection (tp1, tp2, tp3);
|
||||
clipTrianglePlanes[1] = createPlaneFromEdgeAndPointInNormalDirection (tp2, tp3, tp1);
|
||||
clipTrianglePlanes[2] = createPlaneFromEdgeAndPointInNormalDirection (tp3, tp1, tp2);
|
||||
|
||||
|
||||
for (size_t tIdx = 0; tIdx < triangleCount; ++tIdx)
|
||||
{
|
||||
size_t triVxIdx = tIdx * 3;
|
||||
|
||||
std::vector<cvf::Vec3d> currentInputTriangleVxes;
|
||||
std::vector<int> currentInputCellFaceForEachTriangleEdge;
|
||||
std::vector<cvf::Vec3d> currentOutputTriangleVxes;
|
||||
std::vector<int> currentOutputCellFaceForEachTriangleEdge;
|
||||
|
||||
|
||||
currentInputTriangleVxes.push_back(triangleVxes[triVxIdx + 0]);
|
||||
currentInputTriangleVxes.push_back(triangleVxes[triVxIdx + 1]);
|
||||
currentInputTriangleVxes.push_back(triangleVxes[triVxIdx + 2]);
|
||||
|
||||
currentInputCellFaceForEachTriangleEdge.push_back(cellFaceForEachTriangleEdge[triVxIdx + 0]);
|
||||
currentInputCellFaceForEachTriangleEdge.push_back(cellFaceForEachTriangleEdge[triVxIdx + 1]);
|
||||
currentInputCellFaceForEachTriangleEdge.push_back(cellFaceForEachTriangleEdge[triVxIdx + 2]);
|
||||
|
||||
|
||||
for ( int planeIdx = 0; planeIdx < 3; ++planeIdx )
|
||||
{
|
||||
size_t inTriangleCount = currentInputTriangleVxes.size()/3;
|
||||
|
||||
currentOutputTriangleVxes.clear();
|
||||
currentOutputCellFaceForEachTriangleEdge.clear();
|
||||
|
||||
for ( size_t inTrIdx = 0; inTrIdx < inTriangleCount ; ++inTrIdx )
|
||||
{
|
||||
size_t inTriVxIdx = inTrIdx * 3;
|
||||
|
||||
ClipVx newVx1;
|
||||
newVx1.isVxIdsNative = false;
|
||||
ClipVx newVx2;
|
||||
newVx2.isVxIdsNative = false;
|
||||
|
||||
bool isMostVxesOnPositiveSide = false;
|
||||
|
||||
bool isIntersectingPlane = planeTriangleIntersection(clipTrianglePlanes[planeIdx],
|
||||
currentInputTriangleVxes[inTriVxIdx + 0], inTriVxIdx + 0,
|
||||
currentInputTriangleVxes[inTriVxIdx + 1], inTriVxIdx + 1,
|
||||
currentInputTriangleVxes[inTriVxIdx + 2], inTriVxIdx + 2,
|
||||
&newVx1, &newVx2, &isMostVxesOnPositiveSide);
|
||||
|
||||
|
||||
if ( !isIntersectingPlane)
|
||||
{
|
||||
// All on negative side: Discard triangle
|
||||
|
||||
if (!isMostVxesOnPositiveSide)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else // All on positive side: keep all
|
||||
{
|
||||
currentOutputTriangleVxes.push_back(currentInputTriangleVxes[inTriVxIdx + 0]);
|
||||
currentOutputTriangleVxes.push_back(currentInputTriangleVxes[inTriVxIdx + 1]);
|
||||
currentOutputTriangleVxes.push_back(currentInputTriangleVxes[inTriVxIdx + 2]);
|
||||
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(currentInputCellFaceForEachTriangleEdge[inTriVxIdx + 0]);
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(currentInputCellFaceForEachTriangleEdge[inTriVxIdx + 1]);
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(currentInputCellFaceForEachTriangleEdge[inTriVxIdx + 2]);
|
||||
}
|
||||
}
|
||||
else // intersecting
|
||||
{
|
||||
if ( isMostVxesOnPositiveSide )
|
||||
{
|
||||
// We need the Quad
|
||||
|
||||
currentOutputTriangleVxes.push_back(newVx2.vx);
|
||||
currentOutputTriangleVxes.push_back(newVx1.vx);
|
||||
currentOutputTriangleVxes.push_back(currentInputTriangleVxes[newVx1.clippedEdgeVx2Id]);
|
||||
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(HT_NO_FACE);
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(currentInputCellFaceForEachTriangleEdge[newVx1.clippedEdgeVx1Id]);
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(HT_NO_FACE);
|
||||
|
||||
currentOutputTriangleVxes.push_back(currentInputTriangleVxes[newVx1.clippedEdgeVx2Id]);
|
||||
currentOutputTriangleVxes.push_back(currentInputTriangleVxes[newVx2.clippedEdgeVx2Id]);
|
||||
currentOutputTriangleVxes.push_back(newVx2.vx);
|
||||
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(currentInputCellFaceForEachTriangleEdge[newVx1.clippedEdgeVx2Id]);
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(currentInputCellFaceForEachTriangleEdge[newVx2.clippedEdgeVx2Id]);
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(HT_NO_FACE);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentOutputTriangleVxes.push_back(newVx1.vx);
|
||||
currentOutputTriangleVxes.push_back(newVx2.vx);
|
||||
currentOutputTriangleVxes.push_back(currentInputTriangleVxes[newVx1.clippedEdgeVx1Id]);
|
||||
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(HT_NO_FACE);
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(currentInputCellFaceForEachTriangleEdge[newVx2.clippedEdgeVx2Id]);
|
||||
currentOutputCellFaceForEachTriangleEdge.push_back(currentInputCellFaceForEachTriangleEdge[newVx1.clippedEdgeVx1Id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentInputTriangleVxes = currentOutputTriangleVxes;
|
||||
currentInputCellFaceForEachTriangleEdge = currentOutputCellFaceForEachTriangleEdge;
|
||||
}
|
||||
|
||||
// Append the result of the completely clipped triangle to the output
|
||||
|
||||
clippedTriangleVxes->insert(clippedTriangleVxes->end(), currentOutputTriangleVxes.begin(), currentOutputTriangleVxes.end());
|
||||
cellFaceForEachClippedTriangleEdge->insert(cellFaceForEachClippedTriangleEdge->end(), currentOutputCellFaceForEachTriangleEdge.begin(), currentOutputCellFaceForEachTriangleEdge.end());
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Will return the intersection point. If the plane is outside the line, it returns the closest line endpoint
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -65,7 +65,15 @@ public:
|
||||
std::vector<ClipVx>* clippedTriangleVxes,
|
||||
std::vector<int>* cellFaceForEachClippedTriangleEdge);
|
||||
|
||||
static cvf::Vec3d planeLineIntersectionForMC(const cvf::Plane& plane,
|
||||
static void clipPlanarTrianglesWithInPlaneTriangle(const std::vector<cvf::Vec3d>& triangleVxes,
|
||||
const std::vector<int>& cellFaceForEachTriangleEdge,
|
||||
const cvf::Vec3d& tp1,
|
||||
const cvf::Vec3d& tp2,
|
||||
const cvf::Vec3d& tp3,
|
||||
std::vector<cvf::Vec3d>* clippedTriangleVxes,
|
||||
std::vector<int>* cellFaceForEachClippedTriangleEdge);
|
||||
|
||||
static cvf::Vec3d planeLineIntersectionForMC(const cvf::Plane& plane,
|
||||
const cvf::Vec3d& p1,
|
||||
const cvf::Vec3d& p2,
|
||||
double* normalizedDistFromP1);
|
||||
|
@ -0,0 +1,36 @@
|
||||
cmake_minimum_required (VERSION 2.8.12)
|
||||
|
||||
project ( cafHexGridIntersectionTools_UnitTests )
|
||||
|
||||
if (MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.11))
|
||||
# VS 2017 : Disable warnings from from gtest code, using deprecated code related to TR1
|
||||
add_definitions(-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
|
||||
message(STATUS "Add flag to disable warings from gtest - _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING")
|
||||
endif()
|
||||
|
||||
set (VIZ_MODULES_FOLDER_NAME ../../../../../Fwk/VizFwk)
|
||||
add_subdirectory(${VIZ_MODULES_FOLDER_NAME}/LibCore LibCoreDir})
|
||||
|
||||
include_directories (
|
||||
${CMAKE_CURRENT_SOURCE_DIR} # required for gtest-all.cpp
|
||||
)
|
||||
|
||||
set( PROJECT_FILES
|
||||
cafHexGridIntersectionToolsBasicTests.cpp
|
||||
cafHexGridIntersectionTools_UnitTests_main.cpp
|
||||
../cafHexGridIntersectionTools.cpp
|
||||
../cafHexGridIntersectionTools.h
|
||||
)
|
||||
|
||||
# add the executable
|
||||
add_executable (${PROJECT_NAME}
|
||||
${PROJECT_FILES}
|
||||
gtest/gtest-all.cpp
|
||||
)
|
||||
|
||||
target_link_libraries ( ${PROJECT_NAME}
|
||||
LibCore
|
||||
)
|
||||
|
||||
source_group("" FILES ${PROJECT_FILES})
|
||||
|
@ -0,0 +1,100 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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.
|
||||
//
|
||||
// This library 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.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include <iostream>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "../cafHexGridIntersectionTools.h"
|
||||
|
||||
TEST(cafHexIntersectionTools, basic)
|
||||
{
|
||||
|
||||
std::vector<cvf::Vec3d> triangleVxes = {{0.0, 0.5, 0.0}, {1.0, 0.5, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.5, 0.0}, {1.0, 0.8, 0.0}, {0.0, 1.0, 0.0} };
|
||||
std::vector<cvf::Vec3d> polygon2 = {{0.5, 0.0, 2002.0}, {1.0, 0.0, 2000.0}, {0.5, 1.0, 2001.0}};
|
||||
|
||||
const std::vector<int> cellFaceForEachTriangleEdge = { 1, 6, 4, 2, 3, 6 };
|
||||
const cvf::Vec3d tp1 = {0.5, 0.01, 0.0};
|
||||
const cvf::Vec3d tp2 = {1.0, 0.0, 0.0};
|
||||
const cvf::Vec3d tp3 = {0.5, 1.0, 0.0};
|
||||
std::vector<cvf::Vec3d> clippedTriangleVxes;
|
||||
std::vector<int> cellFaceForEachClippedTriangleEdge;
|
||||
|
||||
caf::HexGridIntersectionTools::clipPlanarTrianglesWithInPlaneTriangle(triangleVxes,
|
||||
cellFaceForEachTriangleEdge,
|
||||
tp1,
|
||||
tp2,
|
||||
tp3,
|
||||
&clippedTriangleVxes,
|
||||
&cellFaceForEachClippedTriangleEdge);
|
||||
|
||||
|
||||
for ( auto& point : clippedTriangleVxes )
|
||||
{
|
||||
//std::cout << " ( " << point[0] << ", " << point[1] << ", " << point[2] << " )" << std::endl;
|
||||
}
|
||||
|
||||
for ( auto& face : cellFaceForEachClippedTriangleEdge )
|
||||
{
|
||||
//std::cout << " [ " << face << " ]" << std::endl;
|
||||
}
|
||||
EXPECT_NEAR(0.5, clippedTriangleVxes[7][0], 1e-7);
|
||||
EXPECT_NEAR(0.5, clippedTriangleVxes[7][1], 1e-7);
|
||||
EXPECT_NEAR(0.75, clippedTriangleVxes[2][0], 1e-7);
|
||||
EXPECT_NEAR(0.5, clippedTriangleVxes[2][1], 1e-7);
|
||||
|
||||
EXPECT_NEAR(0.555555, clippedTriangleVxes[13][0], 1e-5);
|
||||
EXPECT_NEAR(0.888888, clippedTriangleVxes[13][1], 1e-5);
|
||||
EXPECT_NEAR(0.5, clippedTriangleVxes[9][0], 1e-7);
|
||||
EXPECT_NEAR(0.9, clippedTriangleVxes[9][1], 1e-7);
|
||||
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[0]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[1]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[2]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[3]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[4]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[5]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[6]);
|
||||
|
||||
EXPECT_EQ(1, cellFaceForEachClippedTriangleEdge[7]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[8]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[9]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[10]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[11]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[12]);
|
||||
EXPECT_EQ(3, cellFaceForEachClippedTriangleEdge[13]);
|
||||
EXPECT_EQ(6, cellFaceForEachClippedTriangleEdge[14]);
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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.
|
||||
//
|
||||
// This library 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.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
int result = RUN_ALL_TESTS();
|
||||
|
||||
char text[5];
|
||||
std::cin.getline(text, 5);
|
||||
|
||||
return result;
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
|
||||
|
||||
|
||||
namespace cvftest {
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
static cvf::String getTestDataDir(const cvf::String& unitTestFolder)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::string exe = std::string(testing::internal::GetArgvs()[0]);
|
||||
#else
|
||||
std::string dir = std::string(testing::internal::FilePath::GetCurrentDir().ToString());
|
||||
std::string exe = dir + std::string("/") + std::string(testing::internal::GetArgvs()[0]);
|
||||
#endif
|
||||
std::string testPath = exe.substr(0, exe.find(unitTestFolder.toStdString())) + std::string("TestData/");
|
||||
|
||||
return testPath;
|
||||
}
|
||||
|
||||
static cvf::String getGLSLDir(const cvf::String& unitTestFolder)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::string exe = std::string(testing::internal::GetArgvs()[0]);
|
||||
#else
|
||||
std::string dir = std::string(testing::internal::FilePath::GetCurrentDir().ToString());
|
||||
std::string exe = dir + std::string("/") + std::string(testing::internal::GetArgvs()[0]);
|
||||
#endif
|
||||
std::string glslPath = exe.substr(0, exe.find(unitTestFolder.toStdString())) + std::string("../LibRender/glsl/");
|
||||
|
||||
return glslPath;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user