mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-03 20:20:48 -06:00
01f3fb8e94
Use this concept to configure result data values to use for vizualization. Created data access object for RegGrid. p4#: 20334
464 lines
16 KiB
C++
464 lines
16 KiB
C++
//##################################################################################################
|
|
//
|
|
// Custom Visualization Core library
|
|
// Copyright (C) 2011-2012 Ceetron AS
|
|
//
|
|
// 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.
|
|
//
|
|
//##################################################################################################
|
|
|
|
#include "cvfBase.h"
|
|
|
|
#include "cvfStructGrid.h"
|
|
#include "cvfStructGridGeometryGenerator.h"
|
|
#include "cvfStructGridScalarDataAccess.h"
|
|
|
|
#include "cvfDebugTimer.h"
|
|
#include "cvfGeometryBuilderDrawableGeo.h"
|
|
#include "cvfPrimitiveSetIndexedUInt.h"
|
|
#include "cvfScalarMapper.h"
|
|
|
|
#include "cvfArray.h"
|
|
#include "cvfOutlineEdgeExtractor.h"
|
|
#include <cmath>
|
|
|
|
|
|
namespace cvf {
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class CellRangeFilter
|
|
///
|
|
//==================================================================================================
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
CellRangeFilter::CellRangeFilter()
|
|
{
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void CellRangeFilter::addCellIncludeRange(size_t minI, size_t minJ, size_t minK, size_t maxI, size_t maxJ, size_t maxK)
|
|
{
|
|
m_includeRanges.push_back(CellRange(minI, minJ, minK, maxI, maxJ, maxK));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void CellRangeFilter::addCellExcludeRange(size_t minI, size_t minJ, size_t minK, size_t maxI, size_t maxJ, size_t maxK)
|
|
{
|
|
m_excludeRanges.push_back(CellRange(minI, minJ, minK, maxI, maxJ, maxK));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void CellRangeFilter::addCellInclude(size_t i, size_t j, size_t k)
|
|
{
|
|
m_includeRanges.push_back(CellRange(i, j, k, i, j, k));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool CellRangeFilter::isCellRejected(size_t i, size_t j, size_t k) const
|
|
{
|
|
if (m_includeRanges.size() == 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
size_t idx;
|
|
for (idx = 0; idx < m_excludeRanges.size(); idx++)
|
|
{
|
|
if (m_excludeRanges[idx].isInRange(i, j, k))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
for (idx = 0; idx < m_includeRanges.size(); idx++)
|
|
{
|
|
if (m_includeRanges[idx].isInRange(i, j, k))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
CellRangeFilter::CellStateType CellRangeFilter::cellState(size_t i, size_t j, size_t k) const
|
|
{
|
|
if (m_includeRanges.size() == 0 && m_excludeRanges.size() == 0)
|
|
{
|
|
return INCLUDED;
|
|
}
|
|
|
|
size_t idx;
|
|
for (idx = 0; idx < m_excludeRanges.size(); idx++)
|
|
{
|
|
if (m_excludeRanges[idx].isInRange(i, j, k))
|
|
{
|
|
return EXCLUDED;
|
|
}
|
|
}
|
|
|
|
for (idx = 0; idx < m_includeRanges.size(); idx++)
|
|
{
|
|
if (m_includeRanges[idx].isInRange(i, j, k))
|
|
{
|
|
return INCLUDED;
|
|
}
|
|
}
|
|
|
|
return NOT_INCLUDED;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
CellRangeFilter::CellStateType CellRangeFilter::combine(CellRangeFilter::CellStateType a, CellRangeFilter::CellStateType b)
|
|
{
|
|
if (a == EXCLUDED || b == EXCLUDED) return EXCLUDED;
|
|
if (a == INCLUDED || b == INCLUDED) return INCLUDED;
|
|
return NOT_INCLUDED;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::StructGridGeometry
|
|
/// \ingroup StructGrid
|
|
///
|
|
///
|
|
///
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
StructGridGeometryGenerator::StructGridGeometryGenerator(const StructGridInterface* grid)
|
|
: m_grid(grid)
|
|
{
|
|
CVF_ASSERT(grid);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
StructGridGeometryGenerator::~StructGridGeometryGenerator()
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Generate surface drawable geo from the specified region
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
ref<DrawableGeo> StructGridGeometryGenerator::generateSurface()
|
|
{
|
|
computeArrays();
|
|
|
|
CVF_ASSERT(m_vertices.notNull());
|
|
|
|
if (m_vertices->size() == 0) return NULL;
|
|
|
|
ref<DrawableGeo> geo = new DrawableGeo;
|
|
geo->setFromQuadVertexArray(m_vertices.p());
|
|
|
|
return geo;
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Generates simplified mesh as line drawing
|
|
/// Must call generateSurface first
|
|
//--------------------------------------------------------------------------------------------------
|
|
ref<DrawableGeo> StructGridGeometryGenerator::createMeshDrawable()
|
|
{
|
|
|
|
if (!(m_vertices.notNull() && m_vertices->size() != 0)) return NULL;
|
|
|
|
ref<DrawableGeo> geo = new DrawableGeo;
|
|
geo->setVertexArray(m_vertices.p());
|
|
|
|
ref<UIntArray> indices = lineIndicesFromQuadVertexArray(m_vertices.p());
|
|
ref<PrimitiveSetIndexedUInt> prim = new PrimitiveSetIndexedUInt(PT_LINES);
|
|
prim->setIndices(indices.p());
|
|
|
|
geo->addPrimitiveSet(prim.p());
|
|
return geo;
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
ref<DrawableGeo> StructGridGeometryGenerator::createOutlineMeshDrawable(double creaseAngle)
|
|
{
|
|
if (!(m_vertices.notNull() && m_vertices->size() != 0)) return NULL;
|
|
|
|
cvf::OutlineEdgeExtractor ee(creaseAngle, *m_vertices);
|
|
|
|
ref<UIntArray> indices = lineIndicesFromQuadVertexArray(m_vertices.p());
|
|
ee.addPrimitives(4, *indices);
|
|
|
|
ref<cvf::UIntArray> lineIndices = ee.lineIndices();
|
|
if (lineIndices->size() == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
ref<PrimitiveSetIndexedUInt> prim = new PrimitiveSetIndexedUInt(PT_LINES);
|
|
prim->setIndices(lineIndices.p());
|
|
|
|
ref<DrawableGeo> geo = new DrawableGeo;
|
|
geo->setVertexArray(m_vertices.p());
|
|
geo->addPrimitiveSet(prim.p());
|
|
|
|
return geo;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
///
|
|
///
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
ref<UIntArray> StructGridGeometryGenerator::lineIndicesFromQuadVertexArray(const Vec3fArray* vertexArray)
|
|
{
|
|
CVF_ASSERT(vertexArray);
|
|
|
|
size_t numVertices = vertexArray->size();
|
|
int numQuads = static_cast<int>(numVertices/4);
|
|
CVF_ASSERT(numVertices%4 == 0);
|
|
|
|
ref<UIntArray> indices = new UIntArray;
|
|
indices->resize(numQuads*8);
|
|
|
|
#pragma omp parallel for
|
|
for (int i = 0; i < numQuads; i++)
|
|
{
|
|
int idx = 8*i;
|
|
indices->set(idx + 0, i*4 + 0);
|
|
indices->set(idx + 1, i*4 + 1);
|
|
indices->set(idx + 2, i*4 + 1);
|
|
indices->set(idx + 3, i*4 + 2);
|
|
indices->set(idx + 4, i*4 + 2);
|
|
indices->set(idx + 5, i*4 + 3);
|
|
indices->set(idx + 6, i*4 + 3);
|
|
indices->set(idx + 7, i*4 + 0);
|
|
}
|
|
|
|
return indices;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void StructGridGeometryGenerator::addFaceVisibilityFilter(const CellFaceVisibilityFilter* cellVisibilityFilter)
|
|
{
|
|
m_cellVisibilityFilters.push_back(cellVisibilityFilter);
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool StructGridGeometryGenerator::isCellFaceVisible(size_t i, size_t j, size_t k, StructGridInterface::FaceType face) const
|
|
{
|
|
size_t idx;
|
|
for (idx = 0; idx < m_cellVisibilityFilters.size(); idx++)
|
|
{
|
|
const cvf::CellFaceVisibilityFilter* cellFilter = m_cellVisibilityFilters[idx];
|
|
if (cellFilter->isFaceVisible(i, j, k, face, m_cellVisibility.p()))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void StructGridGeometryGenerator::computeArrays()
|
|
{
|
|
std::vector<Vec3f> vertices;
|
|
m_quadsToGridCells.clear();
|
|
m_quadsToFace.clear();
|
|
|
|
cvf::Vec3d offset = m_grid->displayModelOffset();
|
|
|
|
#pragma omp parallel for schedule(dynamic)
|
|
for (int k = 0; k < static_cast<int>(m_grid->cellCountK()); k++)
|
|
{
|
|
size_t j;
|
|
for (j = 0; j < m_grid->cellCountJ(); j++)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < m_grid->cellCountI(); i++)
|
|
{
|
|
size_t cellIndex = m_grid->cellIndexFromIJK(i, j, k);
|
|
if (m_cellVisibility.notNull() && !(*m_cellVisibility)[cellIndex])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
std::vector<StructGridInterface::FaceType> visibleFaces;
|
|
visibleFaces.reserve(6);
|
|
|
|
if (isCellFaceVisible(i, j, k, StructGridInterface::NEG_I)) visibleFaces.push_back(cvf::StructGridInterface::NEG_I);
|
|
if (isCellFaceVisible(i, j, k, StructGridInterface::POS_I)) visibleFaces.push_back(cvf::StructGridInterface::POS_I);
|
|
if (isCellFaceVisible(i, j, k, StructGridInterface::NEG_J)) visibleFaces.push_back(cvf::StructGridInterface::NEG_J);
|
|
if (isCellFaceVisible(i, j, k, StructGridInterface::POS_J)) visibleFaces.push_back(cvf::StructGridInterface::POS_J);
|
|
if (isCellFaceVisible(i, j, k, StructGridInterface::NEG_K)) visibleFaces.push_back(cvf::StructGridInterface::NEG_K);
|
|
if (isCellFaceVisible(i, j, k, StructGridInterface::POS_K)) visibleFaces.push_back(cvf::StructGridInterface::POS_K);
|
|
|
|
if (visibleFaces.size() > 0)
|
|
{
|
|
size_t cellIndex = m_grid->cellIndexFromIJK(i, j, k);
|
|
|
|
cvf::Vec3d cornerVerts[8];
|
|
m_grid->cellCornerVertices(cellIndex, cornerVerts);
|
|
|
|
size_t idx;
|
|
for (idx = 0; idx < visibleFaces.size(); idx++)
|
|
{
|
|
cvf::StructGridInterface::FaceType face = visibleFaces[idx];
|
|
|
|
ubyte faceConn[4];
|
|
m_grid->cellFaceVertexIndices(face, faceConn);
|
|
|
|
// Critical section to avoid two threads accessing the arrays at the same time.
|
|
#pragma omp critical
|
|
{
|
|
int n;
|
|
for (n = 0; n < 4; n++)
|
|
{
|
|
vertices.push_back(cvf::Vec3f(cornerVerts[faceConn[n]] - offset));
|
|
}
|
|
|
|
// Keep track of the source cell index per quad
|
|
m_quadsToGridCells.push_back(cellIndex);
|
|
m_quadsToFace.push_back(face);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_vertices = new cvf::Vec3fArray;
|
|
m_vertices->assign(vertices);
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* dataAccessObject, const ScalarMapper* mapper) const
|
|
{
|
|
if (!dataAccessObject) return;
|
|
|
|
size_t numVertices = m_quadsToGridCells.size()*4;
|
|
|
|
textureCoords->resize(numVertices);
|
|
cvf::Vec2f* rawPtr = textureCoords->ptr();
|
|
|
|
double cellScalarValue;
|
|
cvf::Vec2f texCoord;
|
|
|
|
#pragma omp parallel for private(texCoord, cellScalarValue)
|
|
for (int i = 0; i < static_cast<int>(m_quadsToGridCells.size()); i++)
|
|
{
|
|
cellScalarValue = dataAccessObject->cellScalar(m_quadsToGridCells[i]);
|
|
texCoord = mapper->mapToTextureCoord(cellScalarValue);
|
|
if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's
|
|
{
|
|
texCoord[1] = 1.0f;
|
|
}
|
|
|
|
size_t j;
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
rawPtr[i*4 + j] = texCoord;
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
ref<cvf::Array<size_t> > StructGridGeometryGenerator::triangleToSourceGridCellMap() const
|
|
{
|
|
ref<Array<size_t> > triangles = new Array<size_t>(2*m_quadsToGridCells.size());
|
|
#pragma omp parallel for
|
|
for (int i = 0; i < static_cast<int>(m_quadsToGridCells.size()); i++)
|
|
{
|
|
triangles->set(i*2, m_quadsToGridCells[i]);
|
|
triangles->set(i*2+1, m_quadsToGridCells[i]);
|
|
}
|
|
|
|
return triangles;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void StructGridGeometryGenerator::setCellVisibility(const UByteArray* cellVisibility)
|
|
{
|
|
m_cellVisibility = cellVisibility;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<size_t>& StructGridGeometryGenerator::quadToGridCellIndices() const
|
|
{
|
|
return m_quadsToGridCells;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<StructGridInterface::FaceType>& StructGridGeometryGenerator::quadToFace() const
|
|
{
|
|
return m_quadsToFace;
|
|
}
|
|
|
|
} // namespace cvf
|
|
|