Merged down changes from Resinsight dev branch

This commit is contained in:
sigurdp 2013-12-04 16:06:48 +01:00
commit cc72c7b2f6
60 changed files with 4221 additions and 112 deletions

View File

@ -38,6 +38,9 @@
#include "RigCaseData.h"
#include "RifReaderEclipseInput.h"
#include "RifEclipseInputFileTools.h"
#include <QFile>
#if 0
//--------------------------------------------------------------------------------------------------
@ -100,6 +103,8 @@ TEST(RigReservoirTest, WellTestErt)
well_info_free( well_info );
}
//--------------------------------------------------------------------------------------------------
/// This file contains test code taken from the test cases in ERT source code.
// There is a typedef issue (center) between ERT and QTextStream, so this file does not include any
@ -107,12 +112,88 @@ TEST(RigReservoirTest, WellTestErt)
//--------------------------------------------------------------------------------------------------
TEST(RigReservoirTest, ElipseInputGridFile)
{
RigReservoir res;
RigCaseData res;
RifReaderEclipseInput inputReader;
bool result = inputReader.open("TEST10K_FLT_LGR_NNC.grdecl", &res);
EXPECT_TRUE(result);
EXPECT_EQ(size_t(1), res.mainGrid()->cells().size());
EXPECT_EQ(size_t(1), res.mainGrid()->globalMatrixModelActiveCellCount());
}
TEST(RigReservoirTest, ReadFaults)
{
// QString filename("d:/Models/Statoil/testcase_juli_2011/data/grid_local.grdecl");
//
// std::vector< RifKeywordAndFilePos > fileKeywords;
// RifEclipseInputFileTools::findKeywordsOnFile(filename, fileKeywords);
//
// cvf::Collection<RigFault> faults;
//
// RifEclipseInputFileTools::readFaults(filename, faults, fileKeywords);
// for (size_t j = 0; j < faults.size(); j++)
// {
// printf(faults.at(j)->name().toLatin1());
// printf("\n");
// }
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST(RigReservoirTest, ReadFaultsRecursively)
{
//TODO: Establish a way to define location of test model files
QString filename("d:/Models/Statoil/TEST_RKMFAULTS/TEST_RKMFAULTS.DATA");
// QString filename("d:/gitroot/ResInsight/TestModels/fault_test/regular27cell.DATA");
QString outFilename = "c:/tmp/TestModels/TEST_RKMFAULTS/msj_faults.txt";
QFile outputFile(outFilename);
{
if (!outputFile.open(QIODevice::WriteOnly))
{
return;
}
}
QTextStream outStream(&outputFile);
cvf::Collection<RigFault> faults;
RifEclipseInputFileTools::readFaultsInGridSection(filename, faults);
// EXPECT_EQ(4, faults.size());
for (size_t j = 0; j < faults.size(); j++)
{
const RigFault* rigFault = faults.at(j);
printf(rigFault->name().toLatin1());
for (size_t faceType = 0; faceType < 6; faceType++)
{
cvf::StructGridInterface::FaceType faceEnum = cvf::StructGridInterface::FaceType(faceType);
const std::vector<cvf::CellRange>& cellRanges = rigFault->cellRangeForFace(faceEnum);
for (size_t i = 0; i < cellRanges.size(); i++)
{
cvf::Vec3st min, max;
cellRanges[i].range(min, max);
QString tmp;
tmp = tmp.sprintf("min i=%3d j=%3d k=%3d - max i=%3d j=%3d k=%3d \n", min.x(), min.y(), min.z(), max.x(), max.y(), max.z());
outStream << tmp;
// printf("min i=%3d j=%3d k=%3d - max i=%3d j=%3d k=%3d ", min.x(), min.y(), min.z(), max.x(), max.y(), max.z());
// printf("\n");
}
}
}
}
#endif

View File

@ -28,6 +28,8 @@
#include <iostream>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QTextStream>
#include <QDebug>
@ -35,10 +37,14 @@
#include "well_state.h"
#include "util.h"
#include <fstream>
#include "RigGridScalarDataAccess.h"
QString includeKeyword("INCLUDE");
QString faultsKeyword("FAULTS");
QString editKeyword("EDIT");
QString gridKeyword("GRID");
//--------------------------------------------------------------------------------------------------
/// Constructor
@ -65,13 +71,16 @@ bool RifEclipseInputFileTools::openGridFile(const QString& fileName, RigCaseData
{
CVF_ASSERT(eclipseCase);
std::vector< RifKeywordAndFilePos > keywordsAndFilePos;
findKeywordsOnFile(fileName, keywordsAndFilePos);
qint64 coordPos = -1;
qint64 zcornPos = -1;
qint64 specgridPos = -1;
qint64 actnumPos = -1;
qint64 mapaxesPos = -1;
findGridKeywordPositions(fileName, &coordPos, &zcornPos, &specgridPos, &actnumPos, &mapaxesPos);
findGridKeywordPositions(keywordsAndFilePos, &coordPos, &zcornPos, &specgridPos, &actnumPos, &mapaxesPos);
if (coordPos < 0 || zcornPos < 0 || specgridPos < 0)
{
@ -99,7 +108,7 @@ bool RifEclipseInputFileTools::openGridFile(const QString& fileName, RigCaseData
ecl_kw_type* mapAxesKw = NULL;
// Try to read all the needed keywords. Early exit if some are not found
caf::ProgressInfo progress(7, "Read Grid from Eclipse Input file");
caf::ProgressInfo progress(8, "Read Grid from Eclipse Input file");
@ -157,6 +166,15 @@ bool RifEclipseInputFileTools::openGridFile(const QString& fileName, RigCaseData
RifReaderEclipseOutput::transferGeometry(inputGrid, eclipseCase);
progress.setProgress(7);
progress.setProgressDescription("Read faults ...");
cvf::Collection<RigFault> faults;
RifEclipseInputFileTools::readFaults(fileName, faults, keywordsAndFilePos);
RigMainGrid* mainGrid = eclipseCase->mainGrid();
mainGrid->setFaults(faults);
progress.setProgress(8);
progress.setProgressDescription("Cleaning up ...");
ecl_kw_free(specGridKw);
@ -189,7 +207,8 @@ std::map<QString, QString> RifEclipseInputFileTools::readProperties(const QStri
caf::ProgressInfo mainProgress(2, "Reading Eclipse Input properties");
caf::ProgressInfo startProgress(knownKeywordSet.size(), "Scanning for known properties");
std::vector<RifKeywordAndFilePos> fileKeywords = RifEclipseInputFileTools::findKeywordsOnFile(fileName);
std::vector<RifKeywordAndFilePos> fileKeywords;
RifEclipseInputFileTools::findKeywordsOnFile(fileName, fileKeywords);
mainProgress.setProgress(1);
caf::ProgressInfo progress(fileKeywords.size(), "Reading properties");
@ -242,10 +261,8 @@ std::map<QString, QString> RifEclipseInputFileTools::readProperties(const QStri
// https://bugreports.qt-project.org/browse/QTBUG-9814
//
//--------------------------------------------------------------------------------------------------
std::vector< RifKeywordAndFilePos > RifEclipseInputFileTools::findKeywordsOnFile(const QString &fileName)
void RifEclipseInputFileTools::findKeywordsOnFile(const QString &fileName, std::vector< RifKeywordAndFilePos >& keywords)
{
std::vector< RifKeywordAndFilePos > keywords;
char buf[1024];
QFile data(fileName);
@ -274,8 +291,6 @@ std::vector< RifKeywordAndFilePos > RifEclipseInputFileTools::findKeywordsOnFile
}
}
while (lineLength != -1);
return keywords;
}
//--------------------------------------------------------------------------------------------------
@ -484,12 +499,10 @@ void RifEclipseInputFileTools::writeDataToTextFile(QFile* file, const QString& e
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifEclipseInputFileTools::findGridKeywordPositions(const QString& filename, qint64* coordPos, qint64* zcornPos, qint64* specgridPos, qint64* actnumPos, qint64* mapaxesPos)
void RifEclipseInputFileTools::findGridKeywordPositions(const std::vector< RifKeywordAndFilePos >& keywordsAndFilePos, qint64* coordPos, qint64* zcornPos, qint64* specgridPos, qint64* actnumPos, qint64* mapaxesPos)
{
CVF_ASSERT(coordPos && zcornPos && specgridPos && actnumPos && mapaxesPos);
std::vector< RifKeywordAndFilePos > keywordsAndFilePos = findKeywordsOnFile(filename);
size_t i;
for (i = 0; i < keywordsAndFilePos.size(); i++)
{
@ -549,3 +562,294 @@ bool RifEclipseInputFileTools::readPropertyAtFilePosition(const QString& fileNam
util_fclose(filePointer);
return isOk;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifEclipseInputFileTools::readFaults(const QString& fileName, cvf::Collection<RigFault>& faults, const std::vector<RifKeywordAndFilePos>& fileKeywords)
{
QFile data(fileName);
if (!data.open(QFile::ReadOnly))
{
return;
}
for (size_t i = 0; i < fileKeywords.size(); i++)
{
if (fileKeywords[i].keyword.compare(editKeyword, Qt::CaseInsensitive) == 0)
{
return;
}
else if (fileKeywords[i].keyword.compare(faultsKeyword, Qt::CaseInsensitive) != 0)
{
continue;
}
qint64 filePos = fileKeywords[i].filePos;
bool isEditKeywordDetected = false;
readFaults(data, filePos, faults, &isEditKeywordDetected);
if (isEditKeywordDetected)
{
return;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifEclipseInputFileTools::readFaultsInGridSection(const QString& fileName, cvf::Collection<RigFault>& faults)
{
QFile data(fileName);
if (!data.open(QFile::ReadOnly))
{
return;
}
QString gridKeyword("GRID");
// Search for keyword grid
qint64 gridPos = findKeyword(gridKeyword, data);
if (gridPos < 0)
{
return;
}
bool isEditKeywordDetected = false;
readFaultsAndParseIncludeStatementsRecursively(data, gridPos, faults, &isEditKeywordDetected);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RifEclipseInputFileTools::findFaultByName(const cvf::Collection<RigFault>& faults, const QString& name)
{
for (size_t i = 0; i < faults.size(); i++)
{
if (faults.at(i)->name() == name)
{
return i;
}
}
return cvf::UNDEFINED_SIZE_T;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
qint64 RifEclipseInputFileTools::findKeyword(const QString& keyword, QFile& file)
{
QString line;
do
{
line = file.readLine();
if (line.startsWith("--", Qt::CaseInsensitive))
{
continue;
}
line = line.trimmed();
if (line.startsWith(keyword, Qt::CaseInsensitive))
{
return file.pos();
}
} while (!file.atEnd());
return -1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifEclipseInputFileTools::readFaultsAndParseIncludeStatementsRecursively(QFile& file, qint64 startPos, cvf::Collection<RigFault>& faults, bool* isEditKeywordDetected)
{
QString line;
if (!file.seek(startPos))
{
return false;
}
bool continueParsing = true;
do
{
line = file.readLine();
if (line.startsWith("--", Qt::CaseInsensitive))
{
continue;
}
else if (line.startsWith(editKeyword, Qt::CaseInsensitive))
{
if (isEditKeywordDetected)
{
*isEditKeywordDetected = true;
}
return false;
}
line = line.trimmed();
if (line.startsWith(includeKeyword, Qt::CaseInsensitive))
{
QString nextLine = file.readLine();
int firstQuote = nextLine.indexOf("'");
int lastQuote = nextLine.lastIndexOf("'");
if (!(firstQuote < 0 || lastQuote < 0 || firstQuote == lastQuote))
{
QDir currentFileFolder;
{
QFileInfo fi(file.fileName());
currentFileFolder = fi.absoluteDir();
}
// Read include file name, and both relative and absolute path is supported
QString includeFilename = nextLine.mid(firstQuote + 1, lastQuote - firstQuote - 1);
QFileInfo fi(currentFileFolder, includeFilename);
if (fi.exists())
{
QString absoluteFilename = fi.canonicalFilePath();
QFile includeFile(absoluteFilename);
if (includeFile.open(QFile::ReadOnly))
{
qDebug() << "Found include statement, and start parsing of\n " << absoluteFilename;
if (!readFaultsAndParseIncludeStatementsRecursively(includeFile, 0, faults, isEditKeywordDetected))
{
qDebug() << "Error when parsing include file : " << absoluteFilename;
}
}
}
}
}
else if (line.startsWith(faultsKeyword, Qt::CaseInsensitive))
{
readFaults(file, file.pos(), faults, isEditKeywordDetected);
}
if (isEditKeywordDetected && *isEditKeywordDetected)
{
continueParsing = false;
}
if (file.atEnd())
{
continueParsing = false;
}
} while (continueParsing);
return true;
}
//--------------------------------------------------------------------------------------------------
/// The file pointer is pointing at the line following the FAULTS keyword.
/// Parse content of this keyword until end of file or
/// end of keyword when a single line with '/' is found
//--------------------------------------------------------------------------------------------------
void RifEclipseInputFileTools::readFaults(QFile &data, qint64 filePos, cvf::Collection<RigFault> &faults, bool* isEditKeywordDetected)
{
if (!data.seek(filePos))
{
return;
}
qDebug() << "Reading faults from\n " << data.fileName();
RigFault* fault = NULL;
do
{
QString line = data.readLine();
line = line.trimmed();
if (line.startsWith("--", Qt::CaseInsensitive))
{
// Skip comment lines
continue;
}
else if (line.startsWith("/", Qt::CaseInsensitive))
{
// Detected end of keyword data section
return;
}
else if (line.startsWith(editKeyword, Qt::CaseInsensitive))
{
// End parsing when edit keyword is detected
if (isEditKeywordDetected)
{
*isEditKeywordDetected = true;
}
return;
}
// Replace tab with space to be able to split the string using space as splitter
line.replace("\t", " ");
QStringList entries = line.split(" ", QString::SkipEmptyParts);
if (entries.size() < 8)
{
continue;
}
QString name = entries[0];
name.remove("'");
int i1, i2, j1, j2, k1, k2;
i1 = entries[1].toInt();
i2 = entries[2].toInt();
j1 = entries[3].toInt();
j2 = entries[4].toInt();
k1 = entries[5].toInt();
k2 = entries[6].toInt();
QString faceString = entries[7];
faceString.remove("'");
cvf::StructGridInterface::FaceEnum cellFaceEnum = cvf::StructGridInterface::FaceEnum::fromText(faceString);
cvf::CellRange cellrange(i1 - 1, j1 - 1, k1 - 1, i2 - 1, j2 - 1, k2 - 1); // Adjust from 1-based to 0-based cell indices
if (!(fault && fault->name() == name))
{
if (findFaultByName(faults, name) == cvf::UNDEFINED_SIZE_T)
{
RigFault* newFault = new RigFault;
newFault->setName(name);
faults.push_back(newFault);
}
size_t faultIndex = findFaultByName(faults, name);
if (faultIndex == cvf::UNDEFINED_SIZE_T)
{
CVF_ASSERT(faultIndex != cvf::UNDEFINED_SIZE_T);
continue;
}
fault = faults.at(faultIndex);
}
CVF_ASSERT(fault);
fault->addCellRangeForFace(cellFaceEnum, cellrange);
} while (!data.atEnd());
}

View File

@ -25,6 +25,7 @@
#include <QString>
#include "RifReaderInterface.h"
#include "RigFault.h"
class RigCaseData;
@ -58,15 +59,27 @@ public:
static std::map<QString, QString> readProperties(const QString& fileName, RigCaseData* eclipseCase);
static bool readProperty (const QString& fileName, RigCaseData* eclipseCase, const QString& eclipseKeyWord, const QString& resultName );
static bool readPropertyAtFilePosition (const QString& fileName, RigCaseData* eclipseCase, const QString& eclipseKeyWord, qint64 filePos, const QString& resultName );
static void readFaultsInGridSection(const QString& fileName, cvf::Collection<RigFault>& faults);
static void readFaults(const QString& fileName, cvf::Collection<RigFault>& faults, const std::vector< RifKeywordAndFilePos >& fileKeywords);
static std::vector< RifKeywordAndFilePos > findKeywordsOnFile(const QString &fileName);
static void readFaults(QFile &data, qint64 filePos, cvf::Collection<RigFault> &faults, bool* isEditKeywordDetected);
static void findKeywordsOnFile(const QString &fileName, std::vector< RifKeywordAndFilePos >& keywords);
static const std::vector<QString>& knownPropertyKeywords();
static bool writePropertyToTextFile(const QString& fileName, RigCaseData* eclipseCase, size_t timeStep, const QString& resultName, const QString& eclipseKeyWord);
static bool writeBinaryResultToTextFile(const QString& fileName, RigCaseData* eclipseCase, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStep, const QString& resultName, const QString& eclipseKeyWord, const double undefinedValue);
static bool readFaultsAndParseIncludeStatementsRecursively(QFile& file, qint64 startPos, cvf::Collection<RigFault>& faults, bool* isEditKeywordDetected);
private:
static void writeDataToTextFile(QFile* file, const QString& eclipseKeyWord, const std::vector<double>& resultData);
static void findGridKeywordPositions(const QString& filename, qint64* coordPos, qint64* zcornPos, qint64* specgridPos, qint64* actnumPos, qint64* mapaxesPos);
static void findGridKeywordPositions(const std::vector< RifKeywordAndFilePos >& keywords, qint64* coordPos, qint64* zcornPos, qint64* specgridPos, qint64* actnumPos, qint64* mapaxesPos);
static size_t findFaultByName(const cvf::Collection<RigFault>& faults, const QString& name);
static qint64 findKeyword(const QString& keyword, QFile& file);
};

View File

@ -36,6 +36,7 @@
#include "cafProgressInfo.h"
#include <map>
#include "RifEclipseInputFileTools.h"
//--------------------------------------------------------------------------------------------------
/// ECLIPSE cell numbering layout:
@ -368,17 +369,37 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigCaseData* eclipseC
progInfo.setProgressDescription("Transferring grid geometry");
if (!transferGeometry(mainEclGrid, eclipseCase)) return false;
progInfo.incrementProgress();
progInfo.setProgressDescription("Reading faults");
progInfo.setNextProgressIncrement(10);
foreach (QString fname, fileSet)
{
if (fname.endsWith(".DATA"))
{
cvf::Collection<RigFault> faults;
RifEclipseInputFileTools::readFaultsInGridSection(fname, faults);
RigMainGrid* mainGrid = eclipseCase->mainGrid();
mainGrid->setFaults(faults);
}
}
progInfo.incrementProgress();
m_eclipseCase = eclipseCase;
progInfo.setProgressDescription("Reading Result index");
progInfo.setNextProgressIncrement(60);
progInfo.setNextProgressIncrement(50);
// Build results meta data
buildMetaData();
progInfo.incrementProgress();
progInfo.incrementProgress();
progInfo.setNextProgressIncrement(8);
progInfo.setProgressDescription("Reading Well information");
readWellCells(mainEclGrid);

View File

@ -6,6 +6,10 @@ endif()
set (SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RivCellEdgeEffectGenerator.h
${CEE_CURRENT_LIST_DIR}RivColorTableArray.h
${CEE_CURRENT_LIST_DIR}RivFaultPart.h
${CEE_CURRENT_LIST_DIR}RivFaultPartMgr.h
${CEE_CURRENT_LIST_DIR}RivFaultGeometryGenerator.h
${CEE_CURRENT_LIST_DIR}RivGridPartMgr.h
${CEE_CURRENT_LIST_DIR}RivReservoirPartMgr.h
${CEE_CURRENT_LIST_DIR}RivReservoirViewPartMgr.h
@ -19,6 +23,10 @@ ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.h
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RivCellEdgeEffectGenerator.cpp
${CEE_CURRENT_LIST_DIR}RivColorTableArray.cpp
${CEE_CURRENT_LIST_DIR}RivFaultPart.cpp
${CEE_CURRENT_LIST_DIR}RivFaultPartMgr.cpp
${CEE_CURRENT_LIST_DIR}RivFaultGeometryGenerator.cpp
${CEE_CURRENT_LIST_DIR}RivGridPartMgr.cpp
${CEE_CURRENT_LIST_DIR}RivReservoirPartMgr.cpp
${CEE_CURRENT_LIST_DIR}RivReservoirViewPartMgr.cpp

View File

@ -0,0 +1,43 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, 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 "RivColorTableArray.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Color3fArray> RivColorTableArray::colorTableArray()
{
cvf::ref<cvf::Color3fArray> partColors = new cvf::Color3fArray();
partColors->reserve(10);
partColors->add(cvf::Color3f(101.0f/255, 132.0f/255, 96.0f/255)); // Dark green
partColors->add(cvf::Color3f(255.0f/255, 131.0f/255, 140.0f/255)); // Old pink
partColors->add(cvf::Color3f(210.0f/255, 176.0f/255, 112.0f/255)); // Light Brown
partColors->add(cvf::Color3f(140.0f/255, 171.0f/255, 238.0f/255)); // Light gray blue
partColors->add(cvf::Color3f(255.0f/255, 205.0f/255, 131.0f/255)); // Peach
partColors->add(cvf::Color3f(220.0f/255, 212.0f/255, 166.0f/255)); // Dark off white
partColors->add(cvf::Color3f(130.0f/255, 255.0f/255, 120.0f/255)); // Light green
partColors->add(cvf::Color3f(166.0f/255, 220.0f/255, 215.0f/255)); // Light gray torquise
partColors->add(cvf::Color3f(168.0f/255, 220.0f/255, 166.0f/255)); // Light gray green
partColors->add(cvf::Color3f(255.0f/255, 64.0f/255, 236.0f/255)); // Magneta
return partColors;
}

View File

@ -0,0 +1,29 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, Ceetron Solutions AS
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfArray.h"
class RivColorTableArray
{
public:
static cvf::ref<cvf::Color3fArray> colorTableArray();
};

View File

@ -0,0 +1,309 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, 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 "RivFaultGeometryGenerator.h"
#include <cmath>
#include "cvfDrawableGeo.h"
#include "cvfPrimitiveSetIndexedUInt.h"
#include "cvfOutlineEdgeExtractor.h"
#include "cvfStructGridScalarDataAccess.h"
#include "cvfScalarMapper.h"
#include "RigFault.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivFaultGeometryGenerator::RivFaultGeometryGenerator(const cvf::StructGridInterface* grid, const RigFault* fault)
: m_grid(grid),
m_fault(fault)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivFaultGeometryGenerator::~RivFaultGeometryGenerator()
{
}
//--------------------------------------------------------------------------------------------------
/// Generate surface drawable geo from the specified region
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableGeo> RivFaultGeometryGenerator::generateSurface()
{
computeArrays();
CVF_ASSERT(m_vertices.notNull());
if (m_vertices->size() == 0) return NULL;
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
geo->setFromQuadVertexArray(m_vertices.p());
return geo;
}
//--------------------------------------------------------------------------------------------------
/// Generates simplified mesh as line drawing
/// Must call generateSurface first
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableGeo> RivFaultGeometryGenerator::createMeshDrawable()
{
if (!(m_vertices.notNull() && m_vertices->size() != 0)) return NULL;
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
geo->setVertexArray(m_vertices.p());
cvf::ref<cvf::UIntArray> indices = lineIndicesFromQuadVertexArray(m_vertices.p());
cvf::ref<cvf::PrimitiveSetIndexedUInt> prim = new cvf::PrimitiveSetIndexedUInt(cvf::PT_LINES);
prim->setIndices(indices.p());
geo->addPrimitiveSet(prim.p());
return geo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableGeo> RivFaultGeometryGenerator::createOutlineMeshDrawable(double creaseAngle)
{
if (!(m_vertices.notNull() && m_vertices->size() != 0)) return NULL;
cvf::OutlineEdgeExtractor ee(creaseAngle, *m_vertices);
cvf::ref<cvf::UIntArray> indices = lineIndicesFromQuadVertexArray(m_vertices.p());
ee.addPrimitives(4, *indices);
cvf::ref<cvf::UIntArray> lineIndices = ee.lineIndices();
if (lineIndices->size() == 0)
{
return NULL;
}
cvf::ref<cvf::PrimitiveSetIndexedUInt> prim = new cvf::PrimitiveSetIndexedUInt(cvf::PT_LINES);
prim->setIndices(lineIndices.p());
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
geo->setVertexArray(m_vertices.p());
geo->addPrimitiveSet(prim.p());
return geo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::UIntArray> RivFaultGeometryGenerator::lineIndicesFromQuadVertexArray(const cvf::Vec3fArray* vertexArray)
{
CVF_ASSERT(vertexArray);
size_t numVertices = vertexArray->size();
int numQuads = static_cast<int>(numVertices/4);
CVF_ASSERT(numVertices%4 == 0);
cvf::ref<cvf::UIntArray> indices = new cvf::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 RivFaultGeometryGenerator::computeArrays()
{
std::vector<cvf::Vec3f> vertices;
m_quadsToGridCells.clear();
m_quadsToFace.clear();
cvf::Vec3d offset = m_grid->displayModelOffset();
for (size_t faceType = 0; faceType < 6; faceType++)
{
cvf::StructGridInterface::FaceType faceEnum = cvf::StructGridInterface::FaceType(faceType);
const std::vector<cvf::CellRange>& cellRanges = m_fault->cellRangeForFace(faceEnum);
for (size_t i = 0; i < cellRanges.size(); i++)
{
const cvf::CellRange& cellRange = cellRanges[i];
std::vector<size_t> gridCellIndices;
computeGlobalCellIndices(cellRange, gridCellIndices);
for (size_t gIdx = 0; gIdx < gridCellIndices.size(); gIdx++)
{
size_t cellIndex = gridCellIndices[gIdx];
if (!(*m_cellVisibility)[cellIndex]) continue;
cvf::Vec3d cornerVerts[8];
m_grid->cellCornerVertices(cellIndex, cornerVerts);
cvf::ubyte faceConn[4];
m_grid->cellFaceVertexIndices(faceEnum, 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(faceEnum);
}
}
}
}
m_vertices = new cvf::Vec3fArray;
m_vertices->assign(vertices);
}
//--------------------------------------------------------------------------------------------------
/// Calculates the texture coordinates in a "nearly" one dimensional texture.
/// Undefined values are coded with a y-texture coordinate value of 1.0 instead of the normal 0.5
//--------------------------------------------------------------------------------------------------
void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoords, const cvf::StructGridScalarDataAccess* dataAccessObject, const cvf::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;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Array<size_t> > RivFaultGeometryGenerator::triangleToSourceGridCellMap() const
{
cvf::ref<cvf::Array<size_t> > triangles = new cvf::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 RivFaultGeometryGenerator::setCellVisibility(const cvf::UByteArray* cellVisibility)
{
m_cellVisibility = cellVisibility;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<size_t>& RivFaultGeometryGenerator::quadToGridCellIndices() const
{
return m_quadsToGridCells;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<cvf::StructGridInterface::FaceType>& RivFaultGeometryGenerator::quadToFace() const
{
return m_quadsToFace;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultGeometryGenerator::computeGlobalCellIndices(const cvf::CellRange& cellRange, std::vector<size_t>& gridCellIndices) const
{
cvf::Vec3st min, max;
cellRange.range(min, max);
for (size_t i = min.x(); i <= max.x(); i++)
{
if (i >= m_grid->cellCountI())
{
continue;
}
for (size_t j = min.y(); j <= max.y(); j++)
{
if (j >= m_grid->cellCountJ())
{
continue;
}
for (size_t k = min.z(); k <= max.z(); k++)
{
if (k >= m_grid->cellCountK())
{
continue;
}
gridCellIndices.push_back(m_grid->cellIndexFromIJK(i, j, k));
}
}
}
}

View File

@ -0,0 +1,85 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, Ceetron Solutions AS
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfStructGridGeometryGenerator.h"
#include "cvfCellRange.h"
namespace cvf
{
class StructGridInterface;
class ModelBasicList;
class Transform;
class Part;
}
class RigFault;
//==================================================================================================
///
///
//==================================================================================================
class RivFaultGeometryGenerator : public cvf::Object
{
public:
RivFaultGeometryGenerator(const cvf::StructGridInterface* grid, const RigFault* fault);
~RivFaultGeometryGenerator();
void setCellVisibility(const cvf::UByteArray* cellVisibilities );
void textureCoordinates(cvf::Vec2fArray* textureCoords,
const cvf::StructGridScalarDataAccess* dataAccessObject,
const cvf::ScalarMapper* mapper) const;
// Mapping between cells and geometry
cvf::ref<cvf::Array<size_t> > triangleToSourceGridCellMap() const;
const std::vector<size_t>& quadToGridCellIndices() const;
const std::vector<cvf::StructGridInterface::FaceType>& quadToFace() const;
// Generated geometry
cvf::ref<cvf::DrawableGeo> generateSurface();
cvf::ref<cvf::DrawableGeo> createMeshDrawable();
cvf::ref<cvf::DrawableGeo> createOutlineMeshDrawable(double creaseAngle);
private:
static cvf::ref<cvf::UIntArray> lineIndicesFromQuadVertexArray(const cvf::Vec3fArray* vertexArray);
void computeGlobalCellIndices(const cvf::CellRange& cellRange, std::vector<size_t>& gridCellIndices) const;
void computeArrays();
private:
// Input
cvf::cref<cvf::StructGridInterface> m_grid;
cvf::cref<RigFault> m_fault;
cvf::cref<cvf::UByteArray> m_cellVisibility;
// Created arrays
cvf::ref<cvf::Vec3fArray> m_vertices;
// Mappings
std::vector<size_t> m_triangleIndexToGridCellIndex;
std::vector<size_t> m_quadsToGridCells;
std::vector<cvf::StructGridInterface::FaceType> m_quadsToFace;
};

View File

@ -0,0 +1,289 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, 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 "RivFaultPart.h"
#include "cvfPart.h"
#include "cafEffectGenerator.h"
#include "cvfStructGrid.h"
#include "cvfDrawableGeo.h"
#include "cvfModelBasicList.h"
#include "RivCellEdgeEffectGenerator.h"
#include "RimReservoirView.h"
#include "RimResultSlot.h"
#include "RimCellEdgeResultSlot.h"
#include "RigCaseCellResultsData.h"
#include "RigCaseData.h"
#include "RiaApplication.h"
#include "RiaPreferences.h"
#include "RimCase.h"
#include "RimWellCollection.h"
#include "cafPdmFieldCvfMat4d.h"
#include "cafPdmFieldCvfColor.h"
#include "RimCellRangeFilterCollection.h"
#include "RimCellPropertyFilterCollection.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimReservoirCellResultsCacher.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivFaultPart::RivFaultPart(const RigGridBase* grid, const RimFault* rimFault)
: m_faultGenerator(grid, rimFault->faultGeometry()),
m_grid(grid),
m_rimFault(rimFault),
m_opacityLevel(1.0f),
m_defaultColor(cvf::Color3::WHITE)
{
m_faultFacesTextureCoords = new cvf::Vec2fArray;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPart::setCellVisibility(cvf::UByteArray* cellVisibilities)
{
m_faultGenerator.setCellVisibility(cellVisibilities);
generatePartGeometry();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPart::updateCellColor(cvf::Color4f color)
{
m_defaultColor = color;
updatePartEffect();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPart::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot)
{
CVF_ASSERT(cellResultSlot);
size_t scalarSetIndex = cellResultSlot->gridScalarIndex();
const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper();
// If the result is static, only read that.
size_t resTimeStepIdx = timeStepIndex;
if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0;
RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel());
RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData();
cvf::ref<cvf::StructGridScalarDataAccess> dataAccessObject = eclipseCase->dataAccessObject(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex);
if (dataAccessObject.isNull()) return;
// Faults
if (m_faultFaces.notNull())
{
m_faultGenerator.textureCoordinates(m_faultFacesTextureCoords.p(), dataAccessObject.p(), mapper);
if (m_opacityLevel < 1.0f )
{
const std::vector<cvf::ubyte>& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex);
cvf::ref<cvf::UIntArray> gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex());
const std::vector<size_t>& quadsToGridCells = m_faultGenerator.quadToGridCellIndices();
for(size_t i = 0; i < m_faultFacesTextureCoords->size(); ++i)
{
if ((*m_faultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values
size_t quadIdx = i/4;
size_t cellIndex = quadsToGridCells[quadIdx];
cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex);
if (wellIndex != cvf::UNDEFINED_UINT)
{
if ( !isWellPipeVisible[wellIndex])
{
(*m_faultFacesTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture
}
}
}
}
cvf::DrawableGeo* dg = dynamic_cast<cvf::DrawableGeo*>(m_faultFaces->drawable());
if (dg) dg->setTextureCoordArray(m_faultFacesTextureCoords.p());
bool usePolygonOffset = true;
caf::ScalarMapperEffectGenerator scalarEffgen(mapper, usePolygonOffset);
scalarEffgen.setOpacityLevel(m_opacityLevel);
cvf::ref<cvf::Effect> scalarEffect = scalarEffgen.generateEffect();
m_faultFaces->setEffect(scalarEffect.p());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPart::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot)
{
/*
if (m_faultFaces.notNull())
{
cvf::DrawableGeo* dg = dynamic_cast<cvf::DrawableGeo*>(m_faultFaces->drawable());
if (dg)
{
RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot,
&m_faultGenerator, dg, m_grid->gridIndex(), m_opacityLevel);
cvf::ScalarMapper* cellScalarMapper = NULL;
if (cellResultSlot->hasResult()) cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper();
CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper(), cellScalarMapper);
cellFaceEffectGen.setOpacityLevel(m_opacityLevel);
cellFaceEffectGen.setDefaultCellColor(m_defaultColor);
cvf::ref<cvf::Effect> eff = cellFaceEffectGen.generateEffect();
m_faultFaces->setEffect(eff.p());
}
}
*/
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPart::appendPartsToModel(cvf::ModelBasicList* model)
{
CVF_ASSERT(model != NULL);
if (m_rimFault && m_rimFault->showFault())
{
if(m_faultFaces.notNull() ) model->addPart(m_faultFaces.p() );
if(m_faultGridLines.notNull() ) model->addPart(m_faultGridLines.p() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPart::generatePartGeometry()
{
bool useBufferObjects = true;
// Surface geometry
{
cvf::ref<cvf::DrawableGeo> geo = m_faultGenerator.generateSurface();
if (geo.notNull())
{
geo->computeNormals();
if (useBufferObjects)
{
geo->setRenderMode(cvf::DrawableGeo::BUFFER_OBJECT);
}
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName("Grid " + cvf::String(static_cast<int>(m_grid->gridIndex())));
part->setId(m_grid->gridIndex()); // !! For now, use grid index as part ID (needed for pick info)
part->setDrawable(geo.p());
//part->setTransform(m_scaleTransform.p());
// Set mapping from triangle face index to cell index
part->setSourceInfo(m_faultGenerator.triangleToSourceGridCellMap().p());
part->updateBoundingBox();
part->setEnableMask(faultBit);
m_faultFaces = part;
}
}
// Mesh geometry
{
cvf::ref<cvf::DrawableGeo> geoMesh = m_faultGenerator.createMeshDrawable();
if (geoMesh.notNull())
{
if (useBufferObjects)
{
geoMesh->setRenderMode(cvf::DrawableGeo::BUFFER_OBJECT);
}
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName("Grid mesh" + cvf::String(static_cast<int>(m_grid->gridIndex())));
part->setDrawable(geoMesh.p());
//part->setTransform(m_scaleTransform.p());
part->updateBoundingBox();
part->setEnableMask(meshFaultBit);
m_faultGridLines = part;
}
}
updatePartEffect();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPart::updatePartEffect()
{
if (m_faultFaces.notNull())
{
cvf::Color3f partColor = m_defaultColor.toColor3f();
if (m_rimFault->showFaultColor())
{
partColor = m_rimFault->faultColor();
}
if (m_defaultColor.a() < 1.0f)
{
// Set priority to make sure this transparent geometry are rendered last
m_faultFaces->setPriority(100);
}
m_opacityLevel = m_defaultColor.a();
// Set default effect
caf::SurfaceEffectGenerator geometryEffgen(partColor, true);
cvf::ref<cvf::Effect> geometryOnlyEffect = geometryEffgen.generateEffect();
m_faultFaces->setEffect(geometryOnlyEffect.p());
}
if (m_faultGridLines.notNull())
{
// Update mesh colors as well, in case of change
RiaPreferences* prefs = RiaApplication::instance()->preferences();
cvf::ref<cvf::Effect> eff;
caf::MeshEffectGenerator faultEffGen(prefs->defaultFaultGridLineColors());
eff = faultEffGen.generateEffect();
m_faultGridLines->setEffect(eff.p());
}
}

View File

@ -0,0 +1,79 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, Ceetron Solutions AS
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "RigGridBase.h"
#include "RimFault.h"
#include "RivFaultGeometryGenerator.h"
#include "cvfColor4.h"
namespace cvf
{
class StructGridInterface;
class ModelBasicList;
class Transform;
class Part;
}
class RimResultSlot;
class RimCellEdgeResultSlot;
class RimFaultCollection;
//==================================================================================================
///
///
//==================================================================================================
class RivFaultPart : public cvf::Object
{
public:
RivFaultPart(const RigGridBase* grid, const RimFault* rimFault);
void setCellVisibility(cvf::UByteArray* cellVisibilities);
void updatePartEffect();
void updateCellColor(cvf::Color4f color);
void updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot);
void updateCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot);
void appendPartsToModel(cvf::ModelBasicList* model);
private:
void generatePartGeometry();
private:
cvf::cref<RigGridBase> m_grid;
RivFaultGeometryGenerator m_faultGenerator;
cvf::ref<cvf::Part> m_faultFaces;
cvf::ref<cvf::Vec2fArray> m_faultFacesTextureCoords;
float m_opacityLevel;
cvf::Color4f m_defaultColor;
cvf::ref<cvf::Part> m_faultGridLines;
cvf::ref<cvf::UByteArray> m_cellVisibility;
const RimFault* m_rimFault;
};

View File

@ -0,0 +1,140 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, 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 "RivFaultPartMgr.h"
#include "cvfPart.h"
#include "cvfModelBasicList.h"
#include "cvfColor3.h"
#include "cvfTransform.h"
#include "cafPdmFieldCvfColor.h"
#include "RimFaultCollection.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivFaultPartMgr::RivFaultPartMgr(const RigGridBase* grid, size_t gridIdx, const RimFaultCollection* faultCollection)
: m_gridIdx(gridIdx),
m_grid(grid),
m_faultCollection(faultCollection)
{
CVF_ASSERT(grid);
if (faultCollection)
{
for (size_t i = 0; i < faultCollection->faults.size(); i++)
{
m_faultParts.push_back(new RivFaultPart(grid, faultCollection->faults[i]));
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivFaultPartMgr::~RivFaultPartMgr()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPartMgr::setTransform(cvf::Transform* scaleTransform)
{
m_scaleTransform = scaleTransform;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPartMgr::setCellVisibility(cvf::UByteArray* cellVisibilities)
{
CVF_ASSERT(cellVisibilities);
for (size_t i = 0; i < m_faultParts.size(); i++)
{
m_faultParts.at(i)->setCellVisibility(cellVisibilities);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPartMgr::appendPartsToModel(cvf::ModelBasicList* model)
{
CVF_ASSERT(model != NULL);
// Faults are only present for main grid
if (!m_grid->isMainGrid()) return;
if (!m_faultCollection->showFaultCollection()) return;
cvf::ModelBasicList parts;
for (size_t i = 0; i < m_faultParts.size(); i++)
{
m_faultParts[i]->appendPartsToModel(&parts);
}
for (size_t i = 0; i < parts.partCount(); i++)
{
cvf::Part* part = parts.part(i);
part->setTransform(m_scaleTransform.p());
model->addPart(part);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPartMgr::updateCellColor(cvf::Color4f color)
{
for (size_t i = 0; i < m_faultParts.size(); i++)
{
m_faultParts[i]->updateCellColor(color);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot)
{
for (size_t i = 0; i < m_faultParts.size(); i++)
{
m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivFaultPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot)
{
for (size_t i = 0; i < m_faultParts.size(); i++)
{
m_faultParts[i]->updateCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot);
}
}

View File

@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, Ceetron Solutions AS
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "RigGridBase.h"
#include "RivFaultPart.h"
namespace cvf
{
class Transform;
}
class RimResultSlot;
class RimCellEdgeResultSlot;
class RimFaultCollection;
//==================================================================================================
///
//==================================================================================================
class RivFaultPartMgr : public cvf::Object
{
public:
RivFaultPartMgr(const RigGridBase* grid, size_t gridIdx, const RimFaultCollection* faultCollection);
~RivFaultPartMgr();
void setTransform(cvf::Transform* scaleTransform);
void setCellVisibility(cvf::UByteArray* cellVisibilities);
void updateCellColor(cvf::Color4f color);
void updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot);
void updateCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot,
RimCellEdgeResultSlot* cellEdgeResultSlot);
void appendPartsToModel(cvf::ModelBasicList* model);
private:
size_t m_gridIdx;
cvf::cref<RigGridBase> m_grid;
cvf::ref<cvf::Transform> m_scaleTransform;
const RimFaultCollection* m_faultCollection;
cvf::Collection<RivFaultPart> m_faultParts;
};

View File

@ -47,7 +47,7 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RivGridPartMgr::RivGridPartMgr(const RigGridBase* grid, size_t gridIdx)
RivGridPartMgr::RivGridPartMgr(const RigGridBase* grid, size_t gridIdx, const RimFaultCollection* rimFaultCollection)
: m_surfaceGenerator(grid),
m_faultGenerator(grid),
m_gridIdx(gridIdx),
@ -55,7 +55,8 @@ RivGridPartMgr::RivGridPartMgr(const RigGridBase* grid, size_t gridIdx)
m_surfaceFaceFilter(grid),
m_faultFaceFilter(grid),
m_opacityLevel(1.0f),
m_defaultColor(cvf::Color3::WHITE)
m_defaultColor(cvf::Color3::WHITE),
m_rimFaultCollection(rimFaultCollection)
{
CVF_ASSERT(grid);
m_cellVisibility = new cvf::UByteArray;
@ -82,13 +83,9 @@ void RivGridPartMgr::setCellVisibility(cvf::UByteArray* cellVisibilities)
m_cellVisibility = cellVisibilities;
m_surfaceGenerator.setCellVisibility(cellVisibilities);
m_surfaceFaceFilter.m_showExternalFaces = true;
m_surfaceFaceFilter.m_showFaultFaces = false;
m_surfaceGenerator.addFaceVisibilityFilter(&m_surfaceFaceFilter);
m_faultGenerator.setCellVisibility(cellVisibilities);
m_faultFaceFilter.m_showExternalFaces = false;
m_faultFaceFilter.m_showFaultFaces = true;
m_faultGenerator.addFaceVisibilityFilter(&m_faultFaceFilter);
generatePartGeometry(m_surfaceGenerator, false);
@ -192,8 +189,12 @@ void RivGridPartMgr::appendPartsToModel(cvf::ModelBasicList* model)
if(m_surfaceFaces.notNull() ) model->addPart(m_surfaceFaces.p() );
if(m_surfaceGridLines.notNull()) model->addPart(m_surfaceGridLines.p());
if(m_faultFaces.notNull() ) model->addPart(m_faultFaces.p() );
if(m_faultGridLines.notNull() ) model->addPart(m_faultGridLines.p() );
if (m_rimFaultCollection && m_rimFaultCollection->showGeometryDetectedFaults())
{
if(m_faultFaces.notNull() ) model->addPart(m_faultFaces.p() );
if(m_faultGridLines.notNull() ) model->addPart(m_faultGridLines.p() );
}
}
//--------------------------------------------------------------------------------------------------

View File

@ -33,6 +33,7 @@ namespace cvf
class RimResultSlot;
class RimCellEdgeResultSlot;
class RimFaultCollection;
//==================================================================================================
///
@ -45,7 +46,7 @@ class RimCellEdgeResultSlot;
class RivGridPartMgr: public cvf::Object
{
public:
RivGridPartMgr(const RigGridBase* grid, size_t gridIdx);
RivGridPartMgr(const RigGridBase* grid, size_t gridIdx, const RimFaultCollection* rimFaultCollection);
~RivGridPartMgr();
void setTransform(cvf::Transform* scaleTransform);
void setCellVisibility(cvf::UByteArray* cellVisibilities );
@ -58,13 +59,6 @@ public:
void appendPartsToModel(cvf::ModelBasicList* model);
enum PartRenderMaskEnum
{
surfaceBit = 0x00000001,
meshSurfaceBit = 0x00000002,
faultBit = 0x00000004,
meshFaultBit = 0x00000008,
};
private:
void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder, bool faultGeometry);
@ -87,13 +81,13 @@ private:
// Fault visualization
cvf::StructGridGeometryGenerator m_faultGenerator;
RigGridCellFaceVisibilityFilter m_faultFaceFilter;
RigFaultFaceVisibilityFilter m_faultFaceFilter;
cvf::ref<cvf::Part> m_faultFaces;
cvf::ref<cvf::Vec2fArray> m_faultFacesTextureCoords;
cvf::ref<cvf::Part> m_faultGridLines;
cvf::ref<cvf::UByteArray> m_cellVisibility;
cvf::ref<cvf::UByteArray> m_cellVisibility;
//cvf::ref<cvf::Part> m_gridOutlines;
const RimFaultCollection* m_rimFaultCollection;
};

View File

@ -18,25 +18,33 @@
#include "RiaStdInclude.h"
#include "RivReservoirPartMgr.h"
#include "RivGridPartMgr.h"
#include "cvfStructGrid.h"
#include "cvfModelBasicList.h"
#include "RigCaseData.h"
#include "RivGridPartMgr.h"
#include "RivFaultPartMgr.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase)
void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase, const RimFaultCollection* faultCollection)
{
m_allGrids.clear();
m_faults.clear();
if (eclipseCase)
{
std::vector<const RigGridBase*> grids;
eclipseCase->allGrids(&grids);
for (size_t i = 0; i < grids.size() ; ++i)
{
m_allGrids.push_back(new RivGridPartMgr(grids[i], i) );
m_allGrids.push_back(new RivGridPartMgr(grids[i], i, faultCollection));
}
// Faults read from file are present only on main grid
m_faults.push_back(new RivFaultPartMgr(eclipseCase->mainGrid(), 0, faultCollection));
}
}
@ -49,6 +57,11 @@ void RivReservoirPartMgr::setTransform(cvf::Transform* scaleTransform)
{
m_allGrids[i]->setTransform(scaleTransform);
}
for (size_t i = 0; i < m_faults.size() ; ++i)
{
m_faults[i]->setTransform(scaleTransform);
}
}
//--------------------------------------------------------------------------------------------------
@ -58,6 +71,11 @@ void RivReservoirPartMgr::setCellVisibility(size_t gridIndex, cvf::UByteArray* c
{
CVF_ASSERT(gridIndex < m_allGrids.size());
m_allGrids[gridIndex]->setCellVisibility(cellVisibilities);
if (gridIndex < m_faults.size())
{
m_faults[gridIndex]->setCellVisibility(cellVisibilities);
}
}
//--------------------------------------------------------------------------------------------------
@ -78,6 +96,11 @@ void RivReservoirPartMgr::updateCellColor(cvf::Color4f color)
{
m_allGrids[i]->updateCellColor(color);
}
for (size_t i = 0; i < m_faults.size() ; ++i)
{
m_faults[i]->updateCellColor(color);
}
}
//--------------------------------------------------------------------------------------------------
@ -89,6 +112,12 @@ void RivReservoirPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultS
{
m_allGrids[i]->updateCellResultColor(timeStepIndex, cellResultSlot);
}
for (size_t i = 0; i < m_faults.size() ; ++i)
{
m_faults[i]->updateCellResultColor(timeStepIndex, cellResultSlot);
}
}
//--------------------------------------------------------------------------------------------------
@ -100,6 +129,11 @@ void RivReservoirPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimRes
{
m_allGrids[i]->updateCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot);
}
for (size_t i = 0; i < m_faults.size() ; ++i)
{
m_faults[i]->updateCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot);
}
}
//--------------------------------------------------------------------------------------------------
@ -111,6 +145,11 @@ void RivReservoirPartMgr::appendPartsToModel(cvf::ModelBasicList* model)
{
m_allGrids[i]->appendPartsToModel(model);
}
for (size_t i = 0; i < m_faults.size() ; ++i)
{
m_faults[i]->appendPartsToModel(model);
}
}
//--------------------------------------------------------------------------------------------------
@ -124,5 +163,10 @@ void RivReservoirPartMgr::appendPartsToModel(cvf::ModelBasicList* model, const s
{
m_allGrids[gridIndices[i]]->appendPartsToModel(model);
}
if (gridIndices[i] < m_faults.size())
{
m_faults[gridIndices[i]]->appendPartsToModel(model);
}
}
}

View File

@ -21,6 +21,8 @@
#include "cvfArray.h"
#include "cvfCollection.h"
#include "RivFaultPartMgr.h"
namespace cvf
{
class ModelBasicList;
@ -31,7 +33,7 @@ class RimResultSlot;
class RimCellEdgeResultSlot;
class RivGridPartMgr;
class RigCaseData;
class RimFaultCollection;
//==================================================================================================
///
@ -43,7 +45,7 @@ class RigCaseData;
class RivReservoirPartMgr: public cvf::Object
{
public:
void clearAndSetReservoir(const RigCaseData* eclipseCase);
void clearAndSetReservoir(const RigCaseData* eclipseCase, const RimFaultCollection* faultCollection);
void setTransform(cvf::Transform* scaleTransform);
void setCellVisibility(size_t gridIndex, cvf::UByteArray* cellVisibilities );
@ -62,4 +64,5 @@ public:
private:
cvf::Collection<RivGridPartMgr> m_allGrids; // Main grid and all LGR's
cvf::Collection<RivFaultPartMgr> m_faults;
};

View File

@ -151,7 +151,7 @@ void RivReservoirViewPartMgr::clearGeometryCache(ReservoirGeometryCacheType geom
m_propFilteredGeometryFramesNeedsRegen[i] = true;
if (m_propFilteredGeometryFrames[i].notNull())
{
m_propFilteredGeometryFrames[i]->clearAndSetReservoir(eclipseCase);
m_propFilteredGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView->faultCollection());
m_propFilteredGeometryFrames[i]->setTransform(m_scaleTransform.p());
}
}
@ -163,7 +163,7 @@ void RivReservoirViewPartMgr::clearGeometryCache(ReservoirGeometryCacheType geom
m_propFilteredWellGeometryFramesNeedsRegen[i] = true;
if (m_propFilteredWellGeometryFrames[i].notNull())
{
m_propFilteredWellGeometryFrames[i]->clearAndSetReservoir(eclipseCase);
m_propFilteredWellGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView->faultCollection());
m_propFilteredWellGeometryFrames[i]->setTransform(m_scaleTransform.p());
}
}
@ -171,7 +171,7 @@ void RivReservoirViewPartMgr::clearGeometryCache(ReservoirGeometryCacheType geom
else
{
m_geometriesNeedsRegen[geomType] = true;
m_geometries[geomType].clearAndSetReservoir(eclipseCase);
m_geometries[geomType].clearAndSetReservoir(eclipseCase, m_reservoirView->faultCollection());
m_geometries[geomType].setTransform(m_scaleTransform.p());
}
}
@ -238,7 +238,7 @@ void RivReservoirViewPartMgr::appendDynamicGeometryPartsToModel(cvf::ModelBasicL
void RivReservoirViewPartMgr::createGeometry(ReservoirGeometryCacheType geometryType)
{
RigCaseData* res = m_reservoirView->eclipseCase()->reservoirData();
m_geometries[geometryType].clearAndSetReservoir(res);
m_geometries[geometryType].clearAndSetReservoir(res, m_reservoirView->faultCollection());
m_geometries[geometryType].setTransform(m_scaleTransform.p());
std::vector<RigGridBase*> grids;
res->allGrids(&grids);
@ -393,7 +393,7 @@ void RivReservoirViewPartMgr::createPropertyFilteredNoneWellCellGeometry(size_t
if ( m_propFilteredGeometryFrames[frameIndex].isNull()) m_propFilteredGeometryFrames[frameIndex] = new RivReservoirPartMgr;
m_propFilteredGeometryFrames[frameIndex]->clearAndSetReservoir(res);
m_propFilteredGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView->faultCollection());
m_propFilteredGeometryFrames[frameIndex]->setTransform(m_scaleTransform.p());
std::vector<RigGridBase*> grids;
@ -470,7 +470,7 @@ void RivReservoirViewPartMgr::createPropertyFilteredWellGeometry(size_t frameInd
if ( m_propFilteredWellGeometryFrames[frameIndex].isNull()) m_propFilteredWellGeometryFrames[frameIndex] = new RivReservoirPartMgr;
m_propFilteredWellGeometryFrames[frameIndex]->clearAndSetReservoir(res);
m_propFilteredWellGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView->faultCollection());
m_propFilteredWellGeometryFrames[frameIndex]->setTransform(m_scaleTransform.p());
std::vector<RigGridBase*> grids;

View File

@ -44,6 +44,8 @@ ${CEE_CURRENT_LIST_DIR}RimStatisticsCaseEvaluator.h
${CEE_CURRENT_LIST_DIR}RimMimeData.h
${CEE_CURRENT_LIST_DIR}RimCommandObject.h
${CEE_CURRENT_LIST_DIR}RimTools.h
${CEE_CURRENT_LIST_DIR}RimFault.h
${CEE_CURRENT_LIST_DIR}RimFaultCollection.h
)
set (SOURCE_GROUP_SOURCE_FILES
@ -86,6 +88,8 @@ ${CEE_CURRENT_LIST_DIR}RimStatisticsCaseEvaluator.cpp
${CEE_CURRENT_LIST_DIR}RimMimeData.cpp
${CEE_CURRENT_LIST_DIR}RimCommandObject.cpp
${CEE_CURRENT_LIST_DIR}RimTools.cpp
${CEE_CURRENT_LIST_DIR}RimFault.cpp
${CEE_CURRENT_LIST_DIR}RimFaultCollection.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@ -0,0 +1,126 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, 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 "RimFault.h"
#include "RigFault.h"
#include "RimReservoirView.h"
#include "RimResultSlot.h"
#include "RimCellEdgeResultSlot.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimCellPropertyFilterCollection.h"
#include "RimCellRangeFilterCollection.h"
#include "RimWellCollection.h"
CAF_PDM_SOURCE_INIT(RimFault, "Fault");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFault::RimFault()
{
CAF_PDM_InitObject("RimFault", ":/draw_style_faults_24x24.png", "", "");
CAF_PDM_InitFieldNoDefault(&name, "FaultName", "Name", "", "", "");
name.setUiHidden(true);
name.setUiReadOnly(true);
CAF_PDM_InitField(&showFault, "ShowFault", true, "Show fault", "", "", "");
showFault.setUiHidden(true);
CAF_PDM_InitField(&showFaultLabel, "ShowFaultLabel", true, "Show fault label", "", "", "");
CAF_PDM_InitField(&showFaultColor, "ShowFaultColor", true, "Show fault color", "", "", "");
CAF_PDM_InitField(&faultColor, "Color", cvf::Color3f(0.588f, 0.588f, 0.804f), "Fault color", "", "", "");
m_rigFault = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFault::~RimFault()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimFault::userDescriptionField()
{
return &name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFault::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
if (&showFault == changedField)
{
this->updateUiIconFromState(showFault);
RimReservoirView* reservoirView = NULL;
this->firstAncestorOfType(reservoirView);
if (reservoirView)
{
reservoirView->scheduleCreateDisplayModelAndRedraw();
}
}
if (&faultColor == changedField)
{
RimReservoirView* reservoirView = NULL;
this->firstAncestorOfType(reservoirView);
if (reservoirView)
{
reservoirView->scheduleCreateDisplayModelAndRedraw();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimFault::objectToggleField()
{
return &showFault;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFault::setFaultGeometry(const RigFault* faultGeometry)
{
m_rigFault = faultGeometry;
this->name = faultGeometry->name();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigFault* RimFault::faultGeometry() const
{
return m_rigFault;
}

View File

@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, 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 "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
#include "cvfBase.h"
#include "cvfColor3.h"
#include "cafPdmFieldCvfColor.h"
class RigFault;
//==================================================================================================
///
///
//==================================================================================================
class RimFault : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimFault();
virtual ~RimFault();
void setFaultGeometry(const RigFault* faultGeometry);
const RigFault* faultGeometry() const;
virtual caf::PdmFieldHandle* userDescriptionField();
virtual caf::PdmFieldHandle* objectToggleField();
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue);
caf::PdmField<bool> showFault;
caf::PdmField<QString> name;
caf::PdmField<bool> showFaultLabel;
caf::PdmField<bool> showFaultColor;
caf::PdmField<cvf::Color3f> faultColor;
private:
const RigFault* m_rigFault;
};

View File

@ -0,0 +1,165 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, 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 "RimFaultCollection.h"
#include "cafAppEnum.h"
#include "cafPdmFieldCvfColor.h"
#include "cafPdmFieldCvfMat4d.h"
#include "RimReservoirView.h"
#include "RimResultSlot.h"
#include "RimCellRangeFilterCollection.h"
#include "RimCellPropertyFilterCollection.h"
#include "RimWellCollection.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimCellEdgeResultSlot.h"
#include "RiaApplication.h"
#include "RiaPreferences.h"
#include "RimCase.h"
#include "RimReservoirCellResultsCacher.h"
#include "RigCaseData.h"
#include "RivColorTableArray.h"
CAF_PDM_SOURCE_INIT(RimFaultCollection, "Faults");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFaultCollection::RimFaultCollection()
{
CAF_PDM_InitObject("Faults", ":/draw_style_faults_24x24.png", "", "");
CAF_PDM_InitField(&showFaultCollection, "Active", true, "Active", "", "", "");
showFaultCollection.setUiHidden(true);
CAF_PDM_InitField(&showGeometryDetectedFaults, "ShowGeometryDetectedFaults", true, "Show geometry detected faults", "", "", "");
CAF_PDM_InitField(&showFaultLabel, "ShowFaultLabel", true, "Show fault labels", "", "", "");
cvf::Color3f defWellLabelColor = RiaApplication::instance()->preferences()->defaultWellLabelColor();
CAF_PDM_InitField(&faultLabelColor, "FaultLabelColor", defWellLabelColor, "Fault label color", "", "", "");
CAF_PDM_InitFieldNoDefault(&faults, "Faults", "Faults", "", "", "");
m_reservoirView = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFaultCollection::~RimFaultCollection()
{
faults.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFaultCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
if (&showFaultCollection == changedField)
{
this->updateUiIconFromState(showFaultCollection);
if (m_reservoirView)
{
m_reservoirView->scheduleCreateDisplayModelAndRedraw();
}
}
if (&showGeometryDetectedFaults == changedField)
{
if (m_reservoirView)
{
m_reservoirView->scheduleCreateDisplayModelAndRedraw();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFaultCollection::setReservoirView(RimReservoirView* ownerReservoirView)
{
m_reservoirView = ownerReservoirView;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimFaultCollection::objectToggleField()
{
return &showFaultCollection;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFault* RimFaultCollection::findFaultByName(QString name)
{
for (size_t i = 0; i < this->faults().size(); ++i)
{
if (this->faults()[i]->name() == name)
{
return this->faults()[i];
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFaultCollection::syncronizeFaults()
{
if (!(m_reservoirView && m_reservoirView->eclipseCase() && m_reservoirView->eclipseCase()->reservoirData()) ) return;
cvf::ref<cvf::Color3fArray> partColors = RivColorTableArray::colorTableArray();
const cvf::Collection<RigFault> rigFaults = m_reservoirView->eclipseCase()->reservoirData()->mainGrid()->faults();
std::vector<caf::PdmPointer<RimFault> > newFaults;
// Find corresponding fault from data model, or create a new
for (size_t fIdx = 0; fIdx < rigFaults.size(); ++fIdx)
{
RimFault* rimFault = this->findFaultByName(rigFaults[fIdx]->name());
if (!rimFault)
{
rimFault = new RimFault();
rimFault->faultColor = partColors->get(fIdx % partColors->size());
}
rimFault->setFaultGeometry(rigFaults[fIdx].p());
newFaults.push_back(rimFault);
}
this->faults().clear();
this->faults().insert(0, newFaults);
}

View File

@ -0,0 +1,68 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, 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 "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
#include "cafAppEnum.h"
#include <QString>
#include "cvfBase.h"
#include "cvfColor3.h"
#include "RimFault.h"
class RimReservoirView;
//==================================================================================================
///
///
//==================================================================================================
class RimFaultCollection : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimFaultCollection();
virtual ~RimFaultCollection();
void setReservoirView(RimReservoirView* ownerReservoirView);
void syncronizeFaults();
caf::PdmField<bool> showGeometryDetectedFaults;
caf::PdmField<bool> showFaultLabel;
caf::PdmField<cvf::Color3f> faultLabelColor;
caf::PdmField<bool> showFaultCollection;
caf::PdmPointersField<RimFault*> faults;
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue);
virtual caf::PdmFieldHandle* objectToggleField();
private:
RimFault* findFaultByName(QString name);
private:
RimReservoirView* m_reservoirView;
};

View File

@ -262,7 +262,9 @@ void RimInputCase::loadAndSyncronizeInputProperties()
if (isExistingFile)
{
std::vector< RifKeywordAndFilePos > fileKeywords = RifEclipseInputFileTools::findKeywordsOnFile(filenames[i]);
std::vector< RifKeywordAndFilePos > fileKeywords;
RifEclipseInputFileTools::findKeywordsOnFile(filenames[i], fileKeywords);
for_all(fileKeywords, fkIt) fileKeywordSet.insert(fileKeywords[fkIt].keyword);
}

View File

@ -73,6 +73,7 @@
#include <limits.h>
#include "cafCeetronPlusNavigation.h"
#include "RimFaultCollection.h"
namespace caf {
@ -99,11 +100,6 @@ void caf::AppEnum< RimReservoirView::SurfaceModeType >::setUp()
const cvf::uint surfaceBit = 0x00000001;
const cvf::uint meshSurfaceBit = 0x00000002;
const cvf::uint faultBit = 0x00000004;
const cvf::uint meshFaultBit = 0x00000008;
CAF_PDM_SOURCE_INIT(RimReservoirView, "ReservoirView");
//--------------------------------------------------------------------------------------------------
@ -145,6 +141,9 @@ RimReservoirView::RimReservoirView()
CAF_PDM_InitFieldNoDefault(&wellCollection, "WellCollection", "Simulation Wells", "", "", "");
wellCollection = new RimWellCollection;
CAF_PDM_InitFieldNoDefault(&faultCollection, "FaultCollection", "Faults", "", "", "");
faultCollection = new RimFaultCollection;
CAF_PDM_InitFieldNoDefault(&rangeFilterCollection, "RangeFilters", "Range Filters", "", "", "");
rangeFilterCollection = new RimCellRangeFilterCollection();
rangeFilterCollection->setReservoirView(this);
@ -198,6 +197,7 @@ RimReservoirView::~RimReservoirView()
delete rangeFilterCollection();
delete propertyFilterCollection();
delete wellCollection();
delete faultCollection();
if (m_viewer)
{
@ -890,6 +890,9 @@ void RimReservoirView::loadDataAndUpdate()
this->propertyFilterCollection()->loadAndInitializePropertyFilters();
this->faultCollection()->setReservoirView(this);
this->faultCollection()->syncronizeFaults();
m_reservoirGridPartManager->clearGeometryCache();
syncronizeWellsWithResults();
@ -1104,30 +1107,35 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex,
void RimReservoirView::updateDisplayModelVisibility()
{
if (m_viewer.isNull()) return;
const cvf::uint uintSurfaceBit = surfaceBit;
const cvf::uint uintMeshSurfaceBit = meshSurfaceBit;
const cvf::uint uintFaultBit = faultBit;
const cvf::uint uintMeshFaultBit = meshFaultBit;
// Initialize the mask to show everything except the the bits controlled here
unsigned int mask = 0xffffffff & ~surfaceBit & ~faultBit & ~meshSurfaceBit & ~meshFaultBit ;
unsigned int mask = 0xffffffff & ~uintSurfaceBit & ~uintFaultBit & ~uintMeshSurfaceBit & ~uintMeshFaultBit ;
// Then turn the appropriate bits on according to the user settings
if (surfaceMode == SURFACE)
{
mask |= surfaceBit;
mask |= faultBit;
mask |= uintSurfaceBit;
mask |= uintFaultBit;
}
else if (surfaceMode == FAULTS)
{
mask |= faultBit;
mask |= uintFaultBit;
}
if (meshMode == FULL_MESH)
{
mask |= meshSurfaceBit;
mask |= meshFaultBit;
mask |= uintMeshSurfaceBit;
mask |= uintMeshFaultBit;
}
else if (meshMode == FAULTS_MESH)
{
mask |= meshFaultBit;
mask |= uintMeshFaultBit;
}
m_viewer->setEnableMask(mask);

View File

@ -30,6 +30,8 @@
#include <QPointer>
#include <QString>
#include "RimFaultCollection.h"
class RimCase;
class RimResultSlot;
class RimCellEdgeResultSlot;
@ -49,6 +51,7 @@ class RiuViewer;
class RigGridBase;
class RigGridCellFaceVisibilityFilter;
class RimReservoirCellResultsStorage;
namespace cvf
{
class Transform;
@ -56,14 +59,15 @@ namespace cvf
class ModelBasicList;
}
enum ViewState
enum PartRenderMaskEnum
{
GEOMETRY_ONLY,
STATIC_RESULT,
DYNAMIC_RESULT,
CELL_FACE_COMBINED_RESULT
surfaceBit = 0x00000001,
meshSurfaceBit = 0x00000002,
faultBit = 0x00000004,
meshFaultBit = 0x00000008,
};
//==================================================================================================
///
///
@ -99,6 +103,8 @@ public:
caf::PdmField<RimWellCollection*> wellCollection;
caf::PdmField<RimFaultCollection*> faultCollection;
caf::PdmField<Rim3dOverlayInfoConfig*> overlayInfoConfig;
// Visualization setup fields

View File

@ -18,6 +18,7 @@ ${CEE_CURRENT_LIST_DIR}RigCaseCellResultsData.h
${CEE_CURRENT_LIST_DIR}RigSingleWellResultsData.h
${CEE_CURRENT_LIST_DIR}RigStatisticsMath.h
${CEE_CURRENT_LIST_DIR}RigWellPath.h
${CEE_CURRENT_LIST_DIR}RigFault.h
)
set (SOURCE_GROUP_SOURCE_FILES
@ -34,6 +35,7 @@ ${CEE_CURRENT_LIST_DIR}RigCaseCellResultsData.cpp
${CEE_CURRENT_LIST_DIR}RigSingleWellResultsData.cpp
${CEE_CURRENT_LIST_DIR}RigStatisticsMath.cpp
${CEE_CURRENT_LIST_DIR}RigWellPath.cpp
${CEE_CURRENT_LIST_DIR}RigFault.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@ -0,0 +1,66 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, 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 "RigFault.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFault::RigFault()
{
m_cellRangesForFaces.resize(6);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFault::addCellRangeForFace(cvf::StructGridInterface::FaceType face, const cvf::CellRange& cellRange)
{
size_t faceIndex = static_cast<size_t>(face);
CVF_ASSERT(faceIndex < m_cellRangesForFaces.size());
m_cellRangesForFaces[faceIndex].push_back(cellRange);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFault::setName(const QString& name)
{
m_name = name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RigFault::name() const
{
return m_name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<cvf::CellRange>& RigFault::cellRangeForFace(cvf::StructGridInterface::FaceType face) const
{
size_t faceIndex = static_cast<size_t>(face);
CVF_ASSERT(faceIndex < m_cellRangesForFaces.size());
return m_cellRangesForFaces[faceIndex];
}

View File

@ -0,0 +1,50 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA, Ceetron Solutions AS
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfVector3.h"
#include "cvfBoundingBox.h"
#include <vector>
#include <QString>
#include "cvfStructGrid.h"
#include "cvfCellRange.h"
class RigFault : public cvf::Object
{
public:
RigFault();
void setName(const QString& name);
QString name() const;
void addCellRangeForFace(cvf::StructGridInterface::FaceType face, const cvf::CellRange& cellRange);
const std::vector<cvf::CellRange>& cellRangeForFace(cvf::StructGridInterface::FaceType face) const;
private:
QString m_name;
std::vector< std::vector<cvf::CellRange> > m_cellRangesForFaces;
};

View File

@ -538,6 +538,14 @@ cvf::BoundingBox RigGridBase::boundingBox()
return m_boundingBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigGridBase::setFaults(const cvf::Collection<RigFault>& faults)
{
m_faults = faults;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -545,49 +553,51 @@ bool RigGridCellFaceVisibilityFilter::isFaceVisible(size_t i, size_t j, size_t k
{
CVF_TIGHT_ASSERT(m_grid);
if (m_showFaultFaces)
size_t cellIndex = m_grid->cellIndexFromIJK(i, j, k);
if (m_grid->cell(cellIndex).subGrid())
{
size_t cellIndex = m_grid->cellIndexFromIJK(i, j, k);
if (m_grid->cell(cellIndex).isCellFaceFault(face))
{
return true;
}
// Do not show any faces in the place where a LGR is present
return false;
}
if (m_showExternalFaces)
size_t ni, nj, nk;
cvf::StructGridInterface::neighborIJKAtCellFace(i, j, k, face, &ni, &nj, &nk);
// If the cell is on the edge of the grid, Interpret as having an invisible neighbour
if (ni >= m_grid->cellCountI() || nj >= m_grid->cellCountJ() || nk >= m_grid->cellCountK())
{
size_t cellIndex = m_grid->cellIndexFromIJK(i, j, k);
if (m_grid->cell(cellIndex).subGrid())
{
// Do not show any faces in the place where a LGR is present
return false;
}
size_t ni, nj, nk;
cvf::StructGridInterface::neighborIJKAtCellFace(i, j, k, face, &ni, &nj, &nk);
// If the cell is on the edge of the grid, Interpret as having an invisible neighbour
if (ni >= m_grid->cellCountI() || nj >= m_grid->cellCountJ() || nk >= m_grid->cellCountK())
{
return true;
}
return true;
}
size_t neighborCellIndex = m_grid->cellIndexFromIJK(ni, nj, nk);
size_t neighborCellIndex = m_grid->cellIndexFromIJK(ni, nj, nk);
// Do show the faces in the boarder between this grid and a possible LGR. Some of the LGR cells
// might not be visible.
if (m_grid->cell(neighborCellIndex).subGrid())
{
return true;
}
// Do show the faces in the boarder between this grid and a possible LGR. Some of the LGR cells
// might not be visible.
if (m_grid->cell(neighborCellIndex).subGrid())
{
return true;
}
// If the neighbour cell is invisible, we need to draw the face
if ((cellVisibility != NULL) && !(*cellVisibility)[neighborCellIndex])
{
return true;
}
// If the neighbour cell is invisible, we need to draw the face
if ((cellVisibility != NULL) && !(*cellVisibility)[neighborCellIndex])
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigFaultFaceVisibilityFilter::isFaceVisible(size_t i, size_t j, size_t k, cvf::StructGridInterface::FaceType face, const cvf::UByteArray* cellVisibility) const
{
size_t cellIndex = m_grid->cellIndexFromIJK(i, j, k);
if (m_grid->cell(cellIndex).isCellFaceFault(face))
{
return true;
}
return false;
}

View File

@ -22,15 +22,17 @@
#include "cvfVector3.h"
#include "cvfBoundingBox.h"
#include "cvfStructGrid.h"
#include "cvfStructGridGeometryGenerator.h"
#include "cvfStructGridScalarDataAccess.h"
#include "cafFixedArray.h"
#include <vector>
#include <string>
#include "cvfStructGridScalarDataAccess.h"
#include "RifReaderInterface.h"
#include "cafFixedArray.h"
#include "RigFault.h"
class RigMainGrid;
@ -75,6 +77,9 @@ public:
void coarseningBox(size_t coarseningBoxIndex, size_t* i1, size_t* i2, size_t* j1, size_t* j2, size_t* k1, size_t* k2) const;
cvf::BoundingBox boundingBox();
void setFaults(const cvf::Collection<RigFault>& faults);
const cvf::Collection<RigFault>& faults() { return m_faults; }
protected:
friend class RigMainGrid;//::initAllSubGridsParentGridPointer();
@ -116,6 +121,8 @@ private:
cvf::BoundingBox m_boundingBox;
std::vector<caf::SizeTArray6> m_coarseningBoxInfo;
cvf::Collection<RigFault> m_faults;
};
@ -123,17 +130,25 @@ class RigGridCellFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter
{
public:
RigGridCellFaceVisibilityFilter(const RigGridBase* grid)
: m_grid(grid),
m_showFaultFaces(true),
m_showExternalFaces(true)
: m_grid(grid)
{
}
virtual bool isFaceVisible( size_t i, size_t j, size_t k, cvf::StructGridInterface::FaceType face, const cvf::UByteArray* cellVisibility ) const;
private:
const RigGridBase* m_grid;
};
class RigFaultFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter
{
public:
bool m_showFaultFaces;
bool m_showExternalFaces;
RigFaultFaceVisibilityFilter(const RigGridBase* grid)
: m_grid(grid)
{
}
virtual bool isFaceVisible( size_t i, size_t j, size_t k, cvf::StructGridInterface::FaceType face, const cvf::UByteArray* cellVisibility ) const;
private:
const RigGridBase* m_grid;

View File

@ -24,6 +24,8 @@ add_library( ${PROJECT_NAME}
cafUtils.h
cvfStructGrid.cpp
cvfStructGrid.h
cvfCellRange.cpp
cvfCellRange.h
cvfStructGridGeometryGenerator.cpp

View File

@ -0,0 +1,133 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron 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 "cvfCellRange.h"
namespace cvf {
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CellRange::CellRange()
{
m_min = cvf::Vec3st::UNDEFINED;
m_max = cvf::Vec3st::UNDEFINED;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CellRange::CellRange(cvf::Vec3st min, cvf::Vec3st max)
{
setRange(min, max);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CellRange::CellRange(size_t minI, size_t minJ, size_t minK, size_t maxI, size_t maxJ, size_t maxK)
{
setRange(Vec3st(minI, minJ, minK), Vec3st(maxI, maxJ, maxK));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CellRange::setRange(const cvf::Vec3st& min, const cvf::Vec3st& max)
{
m_min = min;
m_max = max;
CVF_ASSERT(normalize());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CellRange::range(cvf::Vec3st& min, cvf::Vec3st& max) const
{
min = m_min;
max = m_max;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool CellRange::normalize()
{
if (m_min == cvf::Vec3st::UNDEFINED || m_max == cvf::Vec3st::UNDEFINED)
{
return false;
}
for (uint i = 0; i < 3; i++)
{
if (m_min[i] > m_max[i])
{
size_t tmp = m_max[i];
m_max[i] = m_min[i];
m_min[i] = tmp;
}
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool CellRange::isInRange(size_t i, size_t j, size_t k) const
{
cvf::Vec3st test(i, j, k);
for (uint idx = 0; idx < 3; idx++)
{
if (test[idx] < m_min[idx] || m_max[idx] <= test[idx])
{
return false;
}
}
return true;
}
} // namespace cvf

View File

@ -0,0 +1,69 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron 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.
//
//##################################################################################################
#pragma once
#include "cvfBase.h"
#include "cvfVector3.h"
namespace cvf {
//==================================================================================================
//
//==================================================================================================
class CellRange
{
public:
CellRange();
CellRange(cvf::Vec3st min, cvf::Vec3st max);
CellRange(size_t minI, size_t minJ, size_t minK, size_t maxI, size_t maxJ, size_t maxK);
void setRange(const cvf::Vec3st& min, const cvf::Vec3st& max);
void range(cvf::Vec3st& min, cvf::Vec3st& max) const;
bool normalize();
bool isInRange(size_t i, size_t j, size_t k) const;
private:
cvf::Vec3st m_min;
cvf::Vec3st m_max;
};
} // End namespace cvf

View File

@ -39,6 +39,20 @@
#include "cvfBase.h"
#include "cvfStructGrid.h"
namespace caf
{
template<>
void cvf::StructGridInterface::FaceEnum::setUp()
{
addItem(cvf::StructGridInterface::POS_I, "X", "");
addItem(cvf::StructGridInterface::NEG_I, "X-", "");
addItem(cvf::StructGridInterface::POS_J, "Y", "");
addItem(cvf::StructGridInterface::NEG_J, "Y-", "");
addItem(cvf::StructGridInterface::POS_K, "Z", "");
addItem(cvf::StructGridInterface::NEG_K, "Z-", "");
}
}
namespace cvf {

View File

@ -40,6 +40,8 @@
#include "cvfObject.h"
#include "cvfVector3.h"
#include "../cafProjectDataModel/cafAppEnum.h"
namespace cvf {
@ -63,6 +65,9 @@ public:
NEG_K
};
typedef caf::AppEnum<StructGridInterface::FaceType> FaceEnum;
public:
StructGridInterface();;

View File

@ -161,7 +161,7 @@ protected:
//==================================================================================================
/// Specialization for pointers, but only applicable to PdmObjectBase derived objects.
/// Specialization for pointers, but only applicable to PdmObject derived objects.
/// The pointer is guarded, meaning that it will be set to NULL if the object pointed to
/// is deleted. The referenced object will be printed in place in the xml-file
//==================================================================================================

View File

@ -10,6 +10,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STRICT_CXX_FLAGS}")
set(CEE_HEADER_FILES
cvfArray.h
cvfArray.inl
cvfArrayWrapperConst.h
cvfArrayWrapperToEdit.h
cvfAssert.h
cvfBase.h
cvfBase64.h

View File

@ -229,6 +229,8 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="cvfArray.h" />
<ClInclude Include="cvfArrayWrapperConst.h" />
<ClInclude Include="cvfArrayWrapperToEdit.h" />
<ClInclude Include="cvfAssert.h" />
<ClInclude Include="cvfBase.h" />
<ClInclude Include="cvfBase64.h" />

View File

@ -42,6 +42,8 @@
<ClInclude Include="cvfLogDestination.h" />
<ClInclude Include="cvfLogDestinationConsole.h" />
<ClInclude Include="cvfLogDestinationFile.h" />
<ClInclude Include="cvfArrayWrapperConst.h" />
<ClInclude Include="cvfArrayWrapperToEdit.h" />
<ClInclude Include="cvfProgramOptions.h" />
</ItemGroup>
<ItemGroup>
@ -89,4 +91,4 @@
<ClCompile Include="cvfLogDestinationFile.cpp" />
<ClCompile Include="cvfProgramOptions.cpp" />
</ItemGroup>
</Project>
</Project>

View File

@ -0,0 +1,153 @@
//##################################################################################################
//
// 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.
//
//##################################################################################################
#pragma once
namespace cvf {
//--------------------------------------------------------------------------------------------------
///
/// \class cvf::ArrayWrapperConst
/// \ingroup Core
///
/// A wrapper class for const access to make it possible to use different array types with
/// different element types in the same algorithms.
///
/// The implementation has a specialization for bare pointer arrays.
/// The reason for the bare pointer specialization is the [] access implementation
/// which is different. (*array)[] vs array[]
///
/// The convenience functions wrapArrayConst() are available to simplify wrapping of your data making it
/// possible to do:
/// myFunction (wrapArrayConst(myNodeArray), wrapArrayConst(myIndexArray), ...);
/// when calling a template function using ArrayWrapperConst's as input.
///
//--------------------------------------------------------------------------------------------------
template < typename ArrayType, typename ElmType >
class ArrayWrapperConst
{
public:
ArrayWrapperConst(const ArrayType* array, size_t size) : m_array(array), m_size(size) { }
inline size_t size() const { return m_size; }
inline const ElmType& operator[] (const size_t index) const { return (*m_array)[index]; }
private:
const ArrayType * m_array;
size_t m_size;
};
//--------------------------------------------------------------------------------------------------
/// Const bare-pointer array wrapper specialization
//--------------------------------------------------------------------------------------------------
template < typename ElmType >
class ArrayWrapperConst <const ElmType*, ElmType>
{
public:
ArrayWrapperConst(const ElmType* array, size_t size) : m_array(array), m_size(size) { }
inline size_t size() const { return m_size; }
inline const ElmType& operator[](const size_t index) const { return m_array[index]; }
private:
const ElmType * m_array;
size_t m_size;
};
#include "cvfArray.h"
#include <vector>
//--------------------------------------------------------------------------------------------------
/// const cvf::Array specialization
//--------------------------------------------------------------------------------------------------
template <typename ElmType>
inline const ArrayWrapperConst< const cvf::Array<ElmType>, ElmType > wrapArrayConst(const cvf::Array<ElmType>* array )
{
const ArrayWrapperConst<const cvf::Array<ElmType>, ElmType> warr(array, array->size());
return warr;
}
template <typename ElmType>
inline const ArrayWrapperConst< const cvf::Array<ElmType>, ElmType > wrapArrayConst( cvf::Array<ElmType>* array )
{
const ArrayWrapperConst<const cvf::Array<ElmType>, ElmType> warr(array, array->size());
return warr;
}
//--------------------------------------------------------------------------------------------------
/// const std::vector specialization
//--------------------------------------------------------------------------------------------------
template <typename ElmType>
inline const ArrayWrapperConst< const std::vector<ElmType>, ElmType > wrapArrayConst( const std::vector<ElmType>* array )
{
const ArrayWrapperConst< const std::vector<ElmType>, ElmType> warr(array, array->size());
return warr;
}
template <typename ElmType>
inline const ArrayWrapperConst< const std::vector<ElmType>, ElmType > wrapArrayConst( std::vector<ElmType>* array )
{
const ArrayWrapperConst< const std::vector<ElmType>, ElmType> warr(array, array->size());
return warr;
}
//--------------------------------------------------------------------------------------------------
/// const Bare-pointer specialization
//--------------------------------------------------------------------------------------------------
template <typename ElmType>
inline const ArrayWrapperConst< const ElmType*, ElmType > wrapArrayConst( const ElmType* array, size_t size )
{
const ArrayWrapperConst<const ElmType*, ElmType> warr(array, size);
return warr;
}
template <typename ElmType>
inline const ArrayWrapperConst< const ElmType*, ElmType > wrapArrayConst( ElmType* array, size_t size )
{
const ArrayWrapperConst<const ElmType*, ElmType> warr(array, size);
return warr;
}
}

View File

@ -0,0 +1,132 @@
//##################################################################################################
//
// 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.
//
//##################################################################################################
#pragma once
namespace cvf {
//--------------------------------------------------------------------------------------------------
///
/// \class cvf::ArrayWrapperToEdit
/// \ingroup Core
///
/// A wrapper class to make it possible to use different array types with
/// different element types in the same algorithms.
///
/// The implementation has a specialization for bare pointer arrays.
/// The reason for the bare pointer specialization is the [] access implementation
/// which is different. (*array)[] vs array[]
///
/// The convenience functions wrapArrayToEdit() are available to simplify wrapping of your data making it
/// possible to do:
/// myFunction (wrapArrayToEdit(myNodeArray), wrapArrayToEdit(myIndexArray), ...);
/// when calling a template function using ArrayWrapperToEdit's as input.
///
//--------------------------------------------------------------------------------------------------
template < typename ArrayType, typename ElmType >
class ArrayWrapperToEdit
{
public:
ArrayWrapperToEdit(ArrayType* array, size_t size) : m_array(array), m_size(size) { }
inline size_t size() const { return m_size; }
inline ElmType& operator[](const size_t index) { return (*m_array)[index]; }
inline const ElmType& operator[](const size_t index) const { return (*m_array)[index]; }
private:
ArrayType * m_array;
size_t m_size;
};
//--------------------------------------------------------------------------------------------------
/// Bare-pointer array wrapper specialization
//--------------------------------------------------------------------------------------------------
template < typename ElmType >
class ArrayWrapperToEdit <ElmType*, ElmType>
{
public:
ArrayWrapperToEdit(ElmType* array, size_t size) : m_array(array), m_size(size) { }
inline size_t size() const { return m_size; }
inline ElmType& operator[](const size_t index) { return m_array[index]; }
inline const ElmType& operator[](const size_t index) const { return m_array[index]; }
private:
ElmType * m_array;
size_t m_size;
};
#include "cvfArray.h"
#include <vector>
//--------------------------------------------------------------------------------------------------
/// cvf::Array specialization
//--------------------------------------------------------------------------------------------------
template <typename ElmType>
inline ArrayWrapperToEdit< cvf::Array<ElmType>, ElmType > wrapArrayToEdit(cvf::Array<ElmType>* array )
{
ArrayWrapperToEdit<cvf::Array<ElmType>, ElmType> warr(array, array->size());
return warr;
}
//--------------------------------------------------------------------------------------------------
/// std::vector specialization
//--------------------------------------------------------------------------------------------------
template <typename ElmType>
inline ArrayWrapperToEdit< std::vector<ElmType>, ElmType > wrapArrayToEdit(std::vector<ElmType>* array )
{
ArrayWrapperToEdit<std::vector<ElmType>, ElmType> warr(array, array->size());
return warr;
}
//--------------------------------------------------------------------------------------------------
/// Bare-pointer specialization
//--------------------------------------------------------------------------------------------------
template <typename ElmType>
inline ArrayWrapperToEdit< ElmType*, ElmType > wrapArrayToEdit(ElmType* array, size_t size )
{
ArrayWrapperToEdit<ElmType*, ElmType> warr(array, size);
return warr;
}
}

View File

@ -13,6 +13,7 @@ include_directories(../LibCore)
set(CEE_HEADER_FILES
cvfArrowGenerator.h
cvfBoundingBox.h
cvfBoundingBoxTree.h
cvfBoxGenerator.h
cvfEdgeKey.h
cvfFrustum.h
@ -34,6 +35,7 @@ cvfVertexWelder.h
set(CEE_SOURCE_FILES
cvfArrowGenerator.cpp
cvfBoundingBox.cpp
cvfBoundingBoxTree.cpp
cvfBoxGenerator.cpp
cvfFrustum.cpp
cvfEdgeKey.cpp

View File

@ -241,6 +241,7 @@
<ItemGroup>
<ClInclude Include="cvfArrowGenerator.h" />
<ClInclude Include="cvfBoundingBox.h" />
<ClInclude Include="cvfBoundingBoxTree.h" />
<ClInclude Include="cvfBoxGenerator.h" />
<ClInclude Include="cvfEdgeKey.h" />
<ClInclude Include="cvfFrustum.h" />
@ -261,6 +262,7 @@
<ItemGroup>
<ClCompile Include="cvfArrowGenerator.cpp" />
<ClCompile Include="cvfBoundingBox.cpp" />
<ClCompile Include="cvfBoundingBoxTree.cpp" />
<ClCompile Include="cvfBoxGenerator.cpp" />
<ClCompile Include="cvfEdgeKey.cpp" />
<ClCompile Include="cvfFrustum.cpp" />

View File

@ -19,6 +19,7 @@
<ClInclude Include="cvfTriangleVertexSplitter.h" />
<ClInclude Include="cvfVertexCompactor.h" />
<ClInclude Include="cvfTriangleMeshEdgeExtractor.h" />
<ClInclude Include="cvfBoundingBoxTree.h" />
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
@ -41,5 +42,6 @@
<ClCompile Include="cvfTriangleVertexSplitter.cpp" />
<ClCompile Include="cvfVertexCompactor.cpp" />
<ClCompile Include="cvfTriangleMeshEdgeExtractor.cpp" />
<ClCompile Include="cvfBoundingBoxTree.cpp" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,977 @@
//##################################################################################################
//
// 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 "cvfBoundingBoxTree.h"
#include "cvfLibCore.h"
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfBoundingBox.h"
#include <cmath>
namespace cvf {
//==================================================================================================
///
/// \class cvf::BoundingBoxTree
/// \ingroup Geometry
///
/// An axis-aligned bounding-box search tree
///
/// This class can be used to quickly do an approximate search for geometry using a bounding box.
/// The geometry entities to search for must be enclosed in bounding boxes which are inserted
/// together with an ID.
///
/// When intersecting, the ID's or the indexes of the intersected boundingboxes are returned,
/// depending on whether explicit id's where supplied.
//==================================================================================================
enum NodeType
{
AB_UNDEFINED,
AB_LEAF,
AB_INTERNAL,
AB_LEAF_GROUP
};
//==================================================================================================
//
//
//
//==================================================================================================
class AABBTreeNode
{
public:
AABBTreeNode();
virtual ~AABBTreeNode() {}
const cvf::BoundingBox& boundingBox() const;
void setBoundingBox(const cvf::BoundingBox bb);
NodeType type() const;
protected:
NodeType m_type;
private:
cvf::BoundingBox m_boundingBox;
};
//=================================================================================================================================
/// Internal node in the AABB tree. It have at least two child nodes, but can have many more (grand-children etc.). Both the Left
/// and right tree node pointes must exist (or else it should be a leaf node).
//=================================================================================================================================
class AABBTreeNodeInternal : public AABBTreeNode
{
public:
AABBTreeNodeInternal();
AABBTreeNodeInternal(AABBTreeNode* left, AABBTreeNode* right);
void setLeft(AABBTreeNode* left);
AABBTreeNode* left();
const AABBTreeNode* left() const;
void setRight(AABBTreeNode* right);
AABBTreeNode* right();
const AABBTreeNode* right() const;
private:
AABBTreeNode* m_pLeft; ///< Left child of this internal node in the binary AABB tree
AABBTreeNode* m_pRight; ///< Right child of this internal node in the binary AABB tree
};
//=================================================================================================================================
/// Standard leaf node in the AABB tree. The leaf node contains only an index, and the interpretation of this index is depending on
/// the type of AABB tree using the node.
//=================================================================================================================================
class AABBTreeNodeLeaf : public AABBTreeNode
{
public:
AABBTreeNodeLeaf(size_t index);
size_t index() const;
private:
size_t m_index; ///< An index of the leaf node. The interpretation of this index is depending on which tree the node is in.
};
//=================================================================================================================================
/// Group leaf node in the AABB tree. The leaf node contains an array with indices, and the interpretation of these are depending on
/// the type of AABB tree using the node.
//=================================================================================================================================
class AABBTreeNodeLeafGroup : public AABBTreeNode
{
public:
AABBTreeNodeLeafGroup();
size_t addIndex(size_t index);
const std::vector<size_t>& indices() const;
void sort();
private:
std::vector<size_t> m_indices; ///< The interpretation of these indices is depending on which tree the node is in.
};
//=================================================================================================================================
//
/// An axis oriented bounding box tree. This is an abstract base class for AABB trees used for searching and intersection testing.
/// All classes deriving from this must implement the CreateLeaves() method. This method creates all the leaf nodes in the AABB
/// tree and is called as a part of the BuildTree() process.
///
/// This base class handles the building of the tree with all the internal nodes. It also handles basic intersection and searching,
/// but the IntersectLeafLeaf() and IntersectBoxLeaf() methods should be implemented in any tree classes used for intersection
/// testing.
///
/// The Find() method only searches for matches in bounding boxes, and must be reimplemented in the decendant classes for
/// accurate testing of leaf nodes when the leaf node properties are known.
//=================================================================================================================================
class AABBTree : public cvf::Object
{
public:
AABBTree();
virtual ~AABBTree();
virtual void free();
bool buildTree();
size_t treeSize() const;
size_t leavesCount() const;
bool boundingBox(cvf::BoundingBox* pBox) const;
cvf::String treeInfo() const;
protected:
virtual bool createLeaves() = 0;
virtual size_t treeNodeSize(const AABBTreeNode* pNode) const;
virtual AABBTreeNodeLeafGroup* createGroupNode(size_t iStartIdx, size_t iEndIdx);
void freeThis();
void deleteInternalNodes(AABBTreeNode* pNode);
size_t treeSize(const AABBTreeNode* pNode) const;
size_t treeHeight(const AABBTreeNode* pNode, size_t iLevel, size_t* piMin, size_t* piMax) const;
void leafBoundingBox(cvf::BoundingBox& pBox, size_t iStartIdx, size_t iEndIdx) const;
bool buildTree(AABBTreeNodeInternal* pNode, size_t iFromIdx, size_t iToIdx);
// Queries
bool intersect(const AABBTreeNode* pA, const AABBTreeNode* pB) const;
protected:
std::vector<AABBTreeNodeLeaf*> m_ppLeaves;
size_t m_iNumLeaves;
AABBTreeNode* m_pRoot;
bool m_bUseGroupNodes;
size_t m_iGroupLimit;
};
class BoundingBoxTreeImpl : public AABBTree
{
BoundingBoxTreeImpl() {}
private:
friend class BoundingBoxTree;
bool createLeaves();
void findIntersections(const cvf::BoundingBox& bb, std::vector<size_t>& bbIds) const;
void findIntersections(const cvf::BoundingBox& bb, const AABBTreeNode* node, std::vector<size_t>& indices) const;
const std::vector<cvf::BoundingBox>* m_boundingBoxes;
const std::vector<size_t>* m_optionalBoundingBoxIds;
};
}
namespace cvf {
using cvf::ref;
int largestComponent(const cvf::Vec3d v)
{
double maxLength = v.x();
int idx = 0;
if (v.y() > maxLength)
{
maxLength = v.y();
idx = 1;
}
if (v.z() > maxLength)
{
maxLength = v.z();
idx = 2;
}
return idx;
}
double largestComponent(const cvf::Vec3d v, cvf::uint* largestIndex)
{
double length = v.x();
cvf::uint idx = 0;
if (v.y() > length)
{
length = v.y();
idx = 1;
}
if (v.z() > length)
{
length = v.z();
idx = 2;
}
if (largestIndex) *largestIndex = idx;
return length;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTreeNode::AABBTreeNode()
{
m_type = AB_UNDEFINED;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const cvf::BoundingBox& AABBTreeNode::boundingBox() const
{
return m_boundingBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
NodeType AABBTreeNode::type() const
{
return m_type;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void AABBTreeNode::setBoundingBox(const cvf::BoundingBox bb)
{
m_boundingBox = bb;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTreeNodeInternal::AABBTreeNodeInternal(AABBTreeNode* left, AABBTreeNode* right)
{
m_type = AB_INTERNAL;
CVF_ASSERT(left);
CVF_ASSERT(right);
m_pLeft = left;
m_pRight = right;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTreeNodeInternal::AABBTreeNodeInternal()
{
m_type = AB_INTERNAL;
m_pLeft = NULL;
m_pRight = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const AABBTreeNode* AABBTreeNodeInternal::left() const
{
return m_pLeft;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTreeNode* AABBTreeNodeInternal::left()
{
return m_pLeft;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const AABBTreeNode* AABBTreeNodeInternal::right() const
{
return m_pRight;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTreeNode* AABBTreeNodeInternal::right()
{
return m_pRight;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void AABBTreeNodeInternal::setLeft(AABBTreeNode* left)
{
CVF_ASSERT(left);
m_pLeft = left;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void AABBTreeNodeInternal::setRight(AABBTreeNode* right)
{
CVF_ASSERT(right);
m_pRight = right;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTreeNodeLeaf::AABBTreeNodeLeaf(size_t index)
{
m_type = AB_LEAF;
m_index = index;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t AABBTreeNodeLeaf::index() const
{
return m_index;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t AABBTreeNodeLeafGroup::addIndex(size_t index)
{
m_indices.push_back(index);
return m_indices.size() - 1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<size_t>& AABBTreeNodeLeafGroup::indices() const
{
return m_indices;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTreeNodeLeafGroup::AABBTreeNodeLeafGroup()
{
m_type = AB_LEAF_GROUP;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void AABBTreeNodeLeafGroup::sort()
{
std::sort(m_indices.begin(), m_indices.end());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTree::AABBTree()
{
m_pRoot = NULL;
m_iNumLeaves = 0;
m_bUseGroupNodes = false;
m_iGroupLimit = 33;
// ResetStatistics();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTree::~AABBTree()
{
freeThis();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void AABBTree::free()
{
freeThis();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool AABBTree::buildTree()
{
// Possibly delete the tree before building it
freeThis();
// First, create all the leaves
if (!createLeaves()) return false;
if (m_iNumLeaves == 0) return true;
// Then find the bounding box of all items in the tree
cvf::BoundingBox box;
leafBoundingBox(box, 0, m_iNumLeaves - 1);
// Create the root
if (m_iNumLeaves == 1)
{
m_pRoot = m_ppLeaves[0];
return true;
}
m_pRoot = new AABBTreeNodeInternal();
m_pRoot->setBoundingBox(box);
bool bRes = buildTree((AABBTreeNodeInternal*)m_pRoot, 0, m_iNumLeaves - 1);
return bRes;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool AABBTree::buildTree(AABBTreeNodeInternal* pNode, size_t iFromIdx, size_t iToIdx)
{
if (!pNode->boundingBox().isValid()) return false;
int iLongestAxis = largestComponent(pNode->boundingBox().extent());
double splitValue = pNode->boundingBox().center()[iLongestAxis];
size_t i = iFromIdx;
size_t iMid = iToIdx;
//=================================================================================================================================
//
// Geometric split tree - best!
//
//=================================================================================================================================
// Order the leaves according to the position of the center of each BB in comparison with longest axis of the BB
while (i < iMid)
{
if (!(m_ppLeaves[i]->boundingBox().isValid()) || m_ppLeaves[i]->boundingBox().center()[iLongestAxis] < splitValue)
{
// Ok, move on
i++;
}
else
{
// Swap, and move iMid back
AABBTreeNodeLeaf* pTemp = m_ppLeaves[i];
m_ppLeaves[i] = m_ppLeaves[iMid];
m_ppLeaves[iMid] = pTemp;
iMid--;
}
}
if ((iMid == iFromIdx) || (iMid == iToIdx))
{
iMid = (iToIdx + iFromIdx)/2;
}
// Create the left tree
if (iMid > iFromIdx)
{
if (m_bUseGroupNodes && ((iMid - iFromIdx + 1) < m_iGroupLimit))
{
pNode->setLeft(createGroupNode(iFromIdx, iMid));
}
else
{
cvf::BoundingBox box;
leafBoundingBox(box, iFromIdx, iMid);
AABBTreeNodeInternal* newNode = new AABBTreeNodeInternal;
newNode->setBoundingBox(box);
pNode->setLeft(newNode);
if (!buildTree((AABBTreeNodeInternal*)pNode->left(), iFromIdx, iMid)) return false;
}
}
else
{
pNode->setLeft(m_ppLeaves[iFromIdx]);
}
// Create the right tree
if (iMid < (iToIdx - 1))
{
if (m_bUseGroupNodes && ((iToIdx - (iMid + 1) + 1) < m_iGroupLimit))
{
pNode->setRight(createGroupNode(iMid + 1, iToIdx));
}
else
{
cvf::BoundingBox box;
leafBoundingBox(box, iMid + 1, iToIdx);
AABBTreeNodeInternal* newNode = new AABBTreeNodeInternal;
newNode->setBoundingBox(box);
pNode->setRight(newNode);
if (!buildTree((AABBTreeNodeInternal*)pNode->right(), iMid + 1, iToIdx)) return false;
}
}
else
{
pNode->setRight(m_ppLeaves[iToIdx]);
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void AABBTree::freeThis()
{
// Delete all the internal nodes
if (m_pRoot)
{
// This also deletes m_pRoot if not a leaf. If it is a leaf, it is deleted below
deleteInternalNodes(m_pRoot);
m_pRoot = NULL;
}
size_t i;
for (i = 0; i < m_iNumLeaves; i++)
{
// Might be NULL if group nodes are used
if (m_ppLeaves[i])
{
delete(m_ppLeaves[i]);
}
}
m_ppLeaves.clear();
m_iNumLeaves = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void AABBTree::deleteInternalNodes(AABBTreeNode* pNode)
{
CVF_ASSERT(pNode);
if (pNode->type() == AB_LEAF) return;
if (pNode->type() == AB_LEAF_GROUP)
{
delete(pNode);
return;
}
AABBTreeNodeInternal* pInt = (AABBTreeNodeInternal*)pNode;
deleteInternalNodes(pInt->left());
deleteInternalNodes(pInt->right());
delete(pNode);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
AABBTreeNodeLeafGroup* AABBTree::createGroupNode(size_t iStartIdx, size_t iEndIdx)
{
size_t iNumItems = iEndIdx - iStartIdx + 1;
CVF_ASSERT(iNumItems > 1);
AABBTreeNodeLeafGroup* pNode = new AABBTreeNodeLeafGroup;
if (!pNode) return NULL;
cvf::BoundingBox bb;
leafBoundingBox(bb, iStartIdx, iEndIdx);
pNode->setBoundingBox(bb);
size_t i;
for (i = iStartIdx; i <= iEndIdx; i++)
{
pNode->addIndex(m_ppLeaves[i]->index());
// Delete the original leaf
delete(m_ppLeaves[i]);
m_ppLeaves[i] = NULL;
}
// Sort the element indices (this is not really required)
// This is done to give then same result as the old implementation that did just a linear search in cases where
// the points are on the element surfaces and thus will give multiple hits.
//
// The performance hit of this seems very small.
pNode->sort();
return pNode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void AABBTree::leafBoundingBox(cvf::BoundingBox& bb, size_t iStartIdx, size_t iEndIdx) const
{
CVF_ASSERT(iStartIdx <= iEndIdx);
bb.reset();
size_t i;
for (i = iStartIdx; i <= iEndIdx; i++)
{
CVF_ASSERT(m_ppLeaves[i]);
bb.add(m_ppLeaves[i]->boundingBox());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t AABBTree::treeSize(const AABBTreeNode* pNode) const
{
CVF_ASSERT(pNode);
if (pNode->type() == AB_LEAF)
{
return treeNodeSize(pNode);
}
if (pNode->type() == AB_LEAF_GROUP)
{
return treeNodeSize(pNode);
}
const AABBTreeNodeInternal* pInt = (const AABBTreeNodeInternal*)pNode;
return treeNodeSize(pInt) + treeSize(pInt->left()) + treeSize(pInt->right());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t AABBTree::treeSize() const
{
if (m_pRoot) return treeSize(m_pRoot);
return 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t AABBTree::treeNodeSize(const AABBTreeNode* pNode) const
{
CVF_ASSERT(pNode);
if (pNode->type() == AB_INTERNAL) return sizeof(AABBTreeNodeInternal);
if (pNode->type() == AB_LEAF) return sizeof(AABBTreeNodeLeaf);
if (pNode->type() == AB_LEAF_GROUP)
{
const AABBTreeNodeLeafGroup* pLeafGroup = (const AABBTreeNodeLeafGroup*)pNode;
return static_cast<size_t>(sizeof(AABBTreeNodeLeafGroup) + static_cast<size_t>(pLeafGroup->indices().size()) * sizeof(cvf::uint));
}
// Should not get here...
CVF_ASSERT(0);
return 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t AABBTree::treeHeight(const AABBTreeNode* pNode, size_t iLevel, size_t* piMin, size_t* piMax) const
{
CVF_ASSERT(pNode);
if ((pNode->type() == AB_LEAF) || (pNode->type() == AB_LEAF_GROUP))
{
if (iLevel < *piMin) *piMin = iLevel;
if (iLevel > *piMax) *piMax = iLevel;
return iLevel;
}
const AABBTreeNodeInternal* pInt = (const AABBTreeNodeInternal*)pNode;
iLevel++;
return treeHeight(pInt->left(), iLevel, piMin, piMax) + treeHeight(pInt->right(), iLevel, piMin, piMax);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::String AABBTree::treeInfo() const
{
cvf::String sInfo;
/*
sInfo = cvf::String("Tree size: %1 \n").arg(static_cast<int>(treeSize()));
sInfo += cvf::String("Num leaves: %1 \n").arg(static_cast<int>(leavesCount()));
size_t iMin = cvf::UNDEFINED_UINT;
size_t iMax = 0;
size_t iSumHeight = treeHeight(m_pRoot, 1, &iMin, &iMax);
size_t iAvgHeigth = 0;
size_t iIdealHeigth = 0;
if (leavesCount() > 0 ) iAvgHeigth = iSumHeight/leavesCount();
sInfo += VTString::MakeForm("Tree height: Min: %d - Max: %d - Avg: %d - Ideal: %d\n", iMin, iMax, iAvgHeigth, (VTint)ceil((log((VTfloat)GetNumLeaves())/log(2.0f))));
iIdealHeigth = (cvf::uint)ceil((log((float)leavesCount())/log(2.0f)));
sInfo = cvf::String("Tree height: Min: %1 - Max: %2 - Avg: %3 - Ideal: %4\n").arg(iMin).arg(iMax).arg(iAvgHeigth).arg(iIdealHeigth);
cvf::BoundingBox bb;
boundingBox(&bb);
sInfo += bb.debugString();
*/
return sInfo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool AABBTree::boundingBox(cvf::BoundingBox* pBox) const
{
CVF_ASSERT(pBox);
if (!m_pRoot) return false;
*pBox = m_pRoot->boundingBox();
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t AABBTree::leavesCount() const
{
return m_iNumLeaves;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool AABBTree::intersect(const AABBTreeNode* pA, const AABBTreeNode* pB) const
{
return pA->boundingBox().intersects(pB->boundingBox());
}
//--------------------------------------------------------------------------------------------------
/// Creates leafs for the supplied valid bounding boxes, keeping the original index
//--------------------------------------------------------------------------------------------------
bool BoundingBoxTreeImpl::createLeaves()
{
size_t i;
for (i = 0; i < m_boundingBoxes->size(); i++)
{
if (!(*m_boundingBoxes)[i].isValid()) continue;
size_t bbId = i;
if (m_optionalBoundingBoxIds) bbId = (*m_optionalBoundingBoxIds)[i];
AABBTreeNodeLeaf* leaf = new AABBTreeNodeLeaf(bbId);
leaf->setBoundingBox((*m_boundingBoxes)[i]);
m_ppLeaves.push_back(leaf);
}
m_iNumLeaves = m_ppLeaves.size();
return true;
}
//--------------------------------------------------------------------------------------------------
/// Find all indices to all bounding boxes intersecting the given bounding box and add them to indices
//--------------------------------------------------------------------------------------------------
void BoundingBoxTreeImpl::findIntersections(const cvf::BoundingBox& bb, std::vector<size_t>& indices) const
{
if (bb.isValid())
{
findIntersections(bb, m_pRoot, indices);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void BoundingBoxTreeImpl::findIntersections(const cvf::BoundingBox& bb, const AABBTreeNode* node, std::vector<size_t>& cvIndices) const
{
CVF_TIGHT_ASSERT(bb.isValid());
if (node && bb.intersects(node->boundingBox()))
{
if (node->type() == AB_LEAF)
{
const AABBTreeNodeLeaf* leaf = static_cast<const AABBTreeNodeLeaf*>(node);
{
cvIndices.push_back(leaf->index());
return;
}
}
else if (node->type() == AB_INTERNAL)
{
const AABBTreeNodeInternal* internalNode = static_cast<const AABBTreeNodeInternal*>(node);
findIntersections(bb, internalNode->left(), cvIndices);
findIntersections(bb, internalNode->right(), cvIndices);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
BoundingBoxTree::BoundingBoxTree()
{
m_implTree = new BoundingBoxTreeImpl;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
BoundingBoxTree::~BoundingBoxTree()
{
delete m_implTree;
}
//--------------------------------------------------------------------------------------------------
/// Build a tree representation of valid bounding boxes. Invalid bounding boxes are ignored
/// The supplied ID array is the ID's returned in the intersection method.
/// If the ID array is omitted, the index of the bounding boxes are returned.
//--------------------------------------------------------------------------------------------------
void BoundingBoxTree::buildTreeFromBoundingBoxes(const std::vector<cvf::BoundingBox>& boundingBoxes,
const std::vector<size_t>* optionalBoundingBoxIds)
{
if (optionalBoundingBoxIds) CVF_ASSERT(boundingBoxes.size() == optionalBoundingBoxIds->size());
m_implTree->m_boundingBoxes = &boundingBoxes;
m_implTree->m_optionalBoundingBoxIds = optionalBoundingBoxIds;
m_implTree->buildTree();
}
//--------------------------------------------------------------------------------------------------
/// Find all indices to all bounding boxes intersecting the given bounding box and add them to indices
//--------------------------------------------------------------------------------------------------
void BoundingBoxTree::findIntersections(const cvf::BoundingBox& bb, std::vector<size_t>* bbIdsOrIndices) const
{
CVF_ASSERT(bbIdsOrIndices);
m_implTree->findIntersections(bb, *bbIdsOrIndices);
}
} // namespace cvf

View File

@ -0,0 +1,69 @@
//##################################################################################################
//
// 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.
//
//##################################################################################################
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfBoundingBox.h"
namespace cvf {
class BoundingBoxTreeImpl;
//==================================================================================================
//
// An axis-aligned bounding-box search tree class
//
//==================================================================================================
class BoundingBoxTree : public cvf::Object
{
public:
BoundingBoxTree();
~BoundingBoxTree();
void buildTreeFromBoundingBoxes(const std::vector<cvf::BoundingBox>& boundingBoxes,
const std::vector<size_t>* optionalBoundingBoxIds);
void findIntersections(const cvf::BoundingBox& inputBB, std::vector<size_t>* bbIdsOrIndexesIntersected) const;
private:
BoundingBoxTreeImpl* m_implTree;
};
} // Namespace cvf

View File

@ -13,6 +13,7 @@ set(CEE_LIBS LibCore)
set(CEE_SOURCE_FILES
cvfArray-Test.cpp
cvfArrayWrapper-Test.cpp
cvfBase-Test.cpp
cvfBase64-Test.cpp
cvfCharArray-Test.cpp

View File

@ -250,6 +250,7 @@
<ItemGroup>
<ClCompile Include="..\..\ThirdParty\gtest\gtest-all.cpp" />
<ClCompile Include="cvfArray-Test.cpp" />
<ClCompile Include="cvfArrayWrapper-Test.cpp" />
<ClCompile Include="cvfBase-Test.cpp" />
<ClCompile Include="cvfBase64-Test.cpp" />
<ClCompile Include="cvfCharArray-Test.cpp" />

View File

@ -32,6 +32,7 @@
<ClCompile Include="cvfLogger-Test.cpp" />
<ClCompile Include="cvfLogEvent-Test.cpp" />
<ClCompile Include="cvfCodeLocation-Test.cpp" />
<ClCompile Include="cvfArrayWrapper-Test.cpp" />
<ClCompile Include="cvfProgramOptions-Test.cpp" />
</ItemGroup>
<ItemGroup>
@ -40,4 +41,4 @@
<ItemGroup>
<CustomBuild Include="TriggerTBBCopy.txt" />
</ItemGroup>
</Project>
</Project>

View File

@ -0,0 +1,189 @@
//##################################################################################################
//
// 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 "cvfBase.h"
#include "cvfArray.h"
#include "cvfArrayWrapperToEdit.h"
#include "cvfArrayWrapperConst.h"
#include "gtest/gtest.h"
#include <iostream>
#include <algorithm>
using namespace cvf;
template <typename ArrayType, typename ElmType>
void arrayWrapperConstTestFunction(const ArrayWrapperConst< ArrayType, ElmType> cinRefArray)
{
ElmType e;
size_t size;
size = cinRefArray.size();
e = cinRefArray[size-1];
CVF_UNUSED(e);
// cinRefArray[size-1] = e;
{
const ElmType& cre = cinRefArray[size-1];
CVF_UNUSED(cre);
//ElmType& re = cinRefArray[size-1];
//re = e;
}
}
template <typename ArrayType, typename ElmType>
void arrayWrapperConstRefTestFunction(const ArrayWrapperConst< ArrayType, ElmType>& cinRefArray)
{
ElmType e;
size_t size;
size = cinRefArray.size();
e = cinRefArray[size-1];
CVF_UNUSED(e);
// cinRefArray[size-1] = e;
{
const ElmType& cre = cinRefArray[size-1];
CVF_UNUSED(cre);
//ElmType& re = cinRefArray[size-1];
//re = e;
}
}
template <typename ArrayType, typename ElmType>
void arrayWrapperTestFunction(ArrayWrapperToEdit< ArrayType, ElmType> cinRefArray)
{
ElmType e, e2;
size_t size;
size = cinRefArray.size();
e = cinRefArray[size-1];
e2 = cinRefArray[0];
cinRefArray[0] = e;
{
const ElmType& cre = cinRefArray[size-1];
CVF_UNUSED(cre);
ElmType& re = cinRefArray[size-1];
re = e2;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST(ArrayWrapperTest, AllSpecializations)
{
std::vector<cvf::Vec3d> vec3dStdVector;
vec3dStdVector.push_back(Vec3d::ZERO);
vec3dStdVector.push_back(Vec3d(1,1,1));
const std::vector<cvf::Vec3d> &cvec3dStdVector = vec3dStdVector;
cvf::Vec3dArray vec3dCvfArray(vec3dStdVector);
const cvf::Vec3dArray& cvec3dCvfArray = vec3dCvfArray;
cvf::Array<size_t> siztCvfArray(2);
siztCvfArray[0] = 0;
siztCvfArray[1] = 1;
cvf::Array<uint> uintCvfArray(2);
uintCvfArray[0] = 0;
uintCvfArray[1] = 1;
const cvf::Array<uint>& cuintCvfArray = uintCvfArray;
size_t siztBarePtrArray[2] = {0, 1};
size_t* siztBarePtr = new size_t[2];
siztBarePtr[0] = 0;
siztBarePtr[1] = 1;
const size_t* csiztBarePtr = siztBarePtr;
cvf::uint* uintBarePtr = new cvf::uint[2];
uintBarePtr[0] = 0;
uintBarePtr[1] = 1;
double* doubleBarePtr = new double[2];
doubleBarePtr[0] = 0;
doubleBarePtr[1] = 1;
const double* cdoubleBarePtr = doubleBarePtr;
arrayWrapperConstTestFunction(wrapArrayConst(&vec3dStdVector));
arrayWrapperConstTestFunction(wrapArrayConst(&cvec3dStdVector));
arrayWrapperConstTestFunction(wrapArrayConst(&vec3dCvfArray));
arrayWrapperConstTestFunction(wrapArrayConst(&cvec3dCvfArray));
arrayWrapperConstTestFunction(wrapArrayConst(&uintCvfArray));
arrayWrapperConstTestFunction(wrapArrayConst(&cuintCvfArray));
arrayWrapperConstTestFunction(wrapArrayConst(siztBarePtrArray, 2));
arrayWrapperConstTestFunction(wrapArrayConst(siztBarePtr, 2));
arrayWrapperConstTestFunction(wrapArrayConst(csiztBarePtr, 2));
arrayWrapperConstTestFunction(wrapArrayConst(doubleBarePtr,2));
arrayWrapperConstTestFunction(wrapArrayConst(cdoubleBarePtr, 2));
arrayWrapperConstRefTestFunction(wrapArrayConst(&vec3dStdVector));
arrayWrapperConstRefTestFunction(wrapArrayConst(&cvec3dStdVector));
arrayWrapperConstRefTestFunction(wrapArrayConst(&vec3dCvfArray));
arrayWrapperConstRefTestFunction(wrapArrayConst(&cvec3dCvfArray));
arrayWrapperConstRefTestFunction(wrapArrayConst(&uintCvfArray));
arrayWrapperConstRefTestFunction(wrapArrayConst(&cuintCvfArray));
arrayWrapperConstRefTestFunction(wrapArrayConst(siztBarePtrArray, 2));
arrayWrapperConstRefTestFunction(wrapArrayConst(siztBarePtr, 2));
arrayWrapperConstRefTestFunction(wrapArrayConst(csiztBarePtr, 2));
arrayWrapperConstRefTestFunction(wrapArrayConst(doubleBarePtr,2));
arrayWrapperConstRefTestFunction(wrapArrayConst(cdoubleBarePtr, 2));
arrayWrapperTestFunction(wrapArrayToEdit(&vec3dStdVector));
//arrayWrapperTestFunction3(wrapArray(&cvec3dStdVector));
EXPECT_EQ(Vec3d::ZERO, vec3dStdVector[1]);
EXPECT_EQ(Vec3d(1,1,1), vec3dStdVector[0]);
arrayWrapperTestFunction(wrapArrayToEdit(&vec3dCvfArray));
EXPECT_EQ(Vec3d::ZERO, vec3dCvfArray[1]);
EXPECT_EQ(Vec3d(1,1,1), vec3dStdVector[0]);
//arrayWrapperTestFunction3(wrapArray(&cvec3dCvfArray));
arrayWrapperTestFunction(wrapArrayToEdit(&uintCvfArray));
//arrayWrapperTestFunction3(wrapArray(&cuintCvfArray));
arrayWrapperTestFunction(wrapArrayToEdit(siztBarePtrArray, 2));
//arrayWrapperTestFunction3(wrapArray(csiztBarePtr, 2));
arrayWrapperTestFunction(wrapArrayToEdit(doubleBarePtr,2));
//arrayWrapperTestFunction3(wrapArray(cdoubleBarePtr, 2));
EXPECT_EQ(0.0, doubleBarePtr[1]);
EXPECT_EQ(1.0, doubleBarePtr[0]);
}

View File

@ -15,6 +15,7 @@ set(CEE_LIBS LibGeometry LibCore)
set(CEE_SOURCE_FILES
cvfArrowGenerator-Test.cpp
cvfBoundingBox-Test.cpp
cvfBoundingBoxTree-Test.cpp
cvfBoxGenerator-Test.cpp
cvfFrustum-Test.cpp
cvfEdgeKey-Test.cpp

View File

@ -251,6 +251,7 @@
<ClCompile Include="..\..\ThirdParty\gtest\gtest-all.cpp" />
<ClCompile Include="cvfArrowGenerator-Test.cpp" />
<ClCompile Include="cvfBoundingBox-Test.cpp" />
<ClCompile Include="cvfBoundingBoxTree-Test.cpp" />
<ClCompile Include="cvfBoxGenerator-Test.cpp" />
<ClCompile Include="cvfEdgeKey-Test.cpp" />
<ClCompile Include="cvfFrustum-Test.cpp" />

View File

@ -20,6 +20,7 @@
<ClCompile Include="cvfTriangleVertexSplitter-Test.cpp" />
<ClCompile Include="cvfVertexCompactor-Test.cpp" />
<ClCompile Include="cvfTriangleMeshEdgeExtractor-Test.cpp" />
<ClCompile Include="cvfBoundingBoxTree-Test.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />

View File

@ -0,0 +1,105 @@
//##################################################################################################
//
// 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 "cvfBoundingBoxTree.h"
#include "gtest/gtest.h"
using namespace cvf;
std::ostream& operator<<(std::ostream& stream, const std::vector<size_t>& array)
{
for (size_t i = 0; i < array.size(); ++i)
{
stream << array[i] << " ";
}
stream << std::endl;
return stream;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST(BoundingBoxTree, Intersection)
{
BoundingBoxTree bbtree;
std::vector<cvf::BoundingBox> bbs;
bbs.push_back(cvf::BoundingBox(Vec3d(0,0,0), Vec3d(1,1,1)));
bbs.push_back(cvf::BoundingBox(Vec3d(1,0,0), Vec3d(2,1,1)));
bbs.push_back(cvf::BoundingBox(Vec3d(2,0,0), Vec3d(3,1,1)));
bbs.push_back(cvf::BoundingBox(Vec3d(3,0,0), Vec3d(4,1,1)));
bbs.push_back(cvf::BoundingBox(Vec3d(4,0,0), Vec3d(5,1,1)));
bbs.push_back(cvf::BoundingBox(Vec3d(0.5,0.5,0), Vec3d(5.5,1.5,1)));
std::vector<size_t> ids;
ids.push_back(10);
ids.push_back(11);
ids.push_back(12);
ids.push_back(13);
ids.push_back(14);
ids.push_back(15);
bbtree.buildTreeFromBoundingBoxes(bbs, &ids);
{
std::vector<size_t> intIds;
bbtree.findIntersections(cvf::BoundingBox(Vec3d(0.25,0.25,0.25), Vec3d(4.5,0.4,0.4)), &intIds);
size_t numBB = intIds.size();
EXPECT_EQ(5, numBB);
EXPECT_EQ(intIds[4], 13);
//std::cout << intIds;
}
{
std::vector<size_t> intIds;
bbtree.findIntersections(cvf::BoundingBox(Vec3d(0.25,0.75,0.25), Vec3d(4.5,0.8,0.4)), &intIds);
size_t numBB = intIds.size();
EXPECT_EQ(6, numBB);
EXPECT_EQ(intIds[5], 15);
//std::cout << intIds;
}
{
std::vector<size_t> intIds;
bbtree.findIntersections(cvf::BoundingBox(Vec3d(2,0,0), Vec3d(3,1,1)), &intIds);
size_t numBB = intIds.size();
EXPECT_EQ(4, numBB);
EXPECT_EQ(intIds[0], 11);
//std::cout << intIds;
}
}

View File

@ -0,0 +1,9 @@
FAULTS
-- NAME IX1 IX2 IY1 IY2 IZ1 IZ2 FACE
'grid_C202' 1 1 1 1 1 3 'X-' /
'grid_C202' 1 1 1 1 1 3 'Z-' /
'grid_C202' 1 2 1 1 1 3 'X-' /
'grid_C202' 1 2 1 1 1 2 'Z-' /
/

View File

@ -0,0 +1,14 @@
INCLUDE
'grid_faults.grdecl' /
FAULTS
-- NAME IX1 IX2 IY1 IY2 IZ1 IZ2 FACE
'mother_grid_C202' 1 1 1 1 1 3 'X-' /
'mother_grid_C202' 1 1 1 1 1 3 'Z-' /
'mother_grid_C202' 1 2 1 1 1 3 'X-' /
'mother_grid_C202' 1 2 1 1 1 2 'Z-' /
/

View File

@ -0,0 +1,12 @@
INCLUDE
'./include/mother_grid_faults.grdecl' /
FAULTS
-- NAME IX1 IX2 IY1 IY2 IZ1 IZ2 FACE
'MAIN' 2 3 1 1 1 3 'X-' /
/
-- More data

View File

@ -0,0 +1,31 @@
-- ==========================================================================
--
-- *************************** GRID SECTION ******************************
--
-- Specification of geometry of computational grid, and of rock
-- properties in each grid block.
--
-- ==========================================================================
GRID
-- GEOMETRY
INCLUDE
'./regular27cell.grdecl' /
-- FAULTS
INCLUDE
'./main_faults.grdecl' /
FAULTS
-- NAME IX1 IX2 IY1 IY2 IZ1 IZ2 FACE
'DATA_FILE_MAIN' 2 3 1 1 1 3 'X-' /
/
EDIT

View File

@ -0,0 +1,88 @@
SPECGRID
3 3 3 1 F /
COORD
0.000 0.000 0.000 0.000 0.000 1.000
0.500 0.000 0.000 0.500 0.000 1.000
1.000 0.000 0.000 1.000 0.000 1.000
1.500 0.000 0.000 1.500 0.000 1.000
0.000 0.500 0.000 0.000 0.500 1.000
0.500 0.500 0.000 0.500 0.500 1.000
1.000 0.500 0.000 1.000 0.500 1.000
1.500 0.500 0.000 1.500 0.500 1.000
0.000 1.000 0.000 0.000 1.000 1.000
0.500 1.000 0.000 0.500 1.000 1.000
1.000 1.000 0.000 1.000 1.000 1.000
1.500 1.000 0.000 1.500 1.000 1.000
0.000 1.500 0.000 0.000 1.500 1.000
0.500 1.500 0.000 0.500 1.500 1.000
1.000 1.500 0.000 1.000 1.500 1.000
1.500 1.500 0.000 1.500 1.500 1.000
/
ZCORN
0.000 0.000 0.000 0.000 0.000 0.000
0.000 0.000 0.000 0.000 0.000 0.000
0.000 0.000 0.000 0.000 0.000 0.000
0.000 0.000 0.000 0.000 0.000 0.000
0.000 0.000 0.000 0.000 0.000 0.000
0.000 0.000 0.000 0.000 0.000 0.000
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
0.500 0.500 0.500 0.500 0.500 0.500
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.000 1.000 1.000 1.000 1.000 1.000
1.500 1.500 1.500 1.500 1.500 1.500
1.500 1.500 1.500 1.500 1.500 1.500
1.500 1.500 1.500 1.500 1.500 1.500
1.500 1.500 1.500 1.500 1.500 1.500
1.500 1.500 1.500 1.500 1.500 1.500
1.500 1.500 1.500 1.500 1.500 1.500
/
ACTNUM
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
/
PERMX
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
/
PORO
0.2 0.2 0.4 0.4 0.6 0.6 0.8 0.8 0.5
0.2 0.2 0.4 0.4 0.6 0.6 0.8 0.8 0.5
0.2 0.2 0.4 0.4 0.6 0.6 0.8 0.8 0.5
/
SATNUM
1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3
/