(#540) Range filter mapping now works fem->ecl and opposite.

We need to test more, but now it is getting there.
This commit is contained in:
Jacob Støren 2015-10-21 10:04:00 +02:00
parent 53826f4966
commit 00b56b7440
2 changed files with 158 additions and 112 deletions

View File

@ -70,23 +70,31 @@ struct RigRangeEndPoints
///
//--------------------------------------------------------------------------------------------------
void RigCaseToCaseRangeFilterMapper::convertRangeFilter(RimCellRangeFilter* srcFilter, RimCellRangeFilter* dstFilter,
const RigMainGrid* eclGrid, const RigFemPart* femPart,
void RigCaseToCaseRangeFilterMapper::convertRangeFilter(const RimCellRangeFilter* srcFilter,
RimCellRangeFilter* dstFilter,
const RigMainGrid* eclGrid,
const RigFemPart* femPart,
bool femIsDestination)
{
CVF_ASSERT(srcFilter && eclGrid && dstFilter && femPart);
CVF_ASSERT(srcFilter->gridIndex() == 0); // LGR not supported yet
RigRangeEndPoints src;
src.StartI = srcFilter->startIndexI() - 1;
src.StartJ = srcFilter->startIndexJ() - 1;
src.StartK = srcFilter->startIndexK() - 1;
// Convert the (start, count) range filter vars to end point cell ijk
{
src.StartI = srcFilter->startIndexI() - 1;
src.StartJ = srcFilter->startIndexJ() - 1;
src.StartK = srcFilter->startIndexK() - 1;
// Needs to subtract one more to have the end idx beeing the last cell in the selection, not the first outside
src.EndI = src.StartI + srcFilter->cellCountI() - 1;
src.EndJ = src.StartJ + srcFilter->cellCountJ() - 1;
src.EndK = src.StartK + srcFilter->cellCountK() - 1;
// Needs to subtract one more to have the end idx beeing
// the last cell in the selection, not the first outside
src.EndI = src.StartI + srcFilter->cellCountI() - 1;
src.EndJ = src.StartJ + srcFilter->cellCountJ() - 1;
src.EndK = src.StartK + srcFilter->cellCountK() - 1;
}
// Clamp the src end points to be inside the src model
{
size_t maxIIndex;
size_t maxJIndex;
@ -101,11 +109,6 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilter(RimCellRangeFilter* srcF
}
else
{
// When using femPart as source we need to clamp the fem srcRange filter
// to the extents of the ecl grid within the fem part before
// doing the mapping. If not, the range filter corners will most likely be outside
// the ecl grid, resulting in an undefined conversion.
maxIIndex = femPart->structGrid()->cellCountI()- 1;
maxJIndex = femPart->structGrid()->cellCountJ()- 1;
maxKIndex = femPart->structGrid()->cellCountK()- 1;
@ -116,104 +119,35 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilter(RimCellRangeFilter* srcF
src.EndK = CVF_MIN(src.EndK, maxKIndex);
}
// When using femPart as source we need to clamp the fem srcRange filter
// to the extents of the ecl grid within the fem part before
// doing the mapping. If not, the range filter corners will most likely be outside
// the ecl grid, resulting in an undefined conversion.
if (!femIsDestination)
{
RigRangeEndPoints eclMaxMin;
eclMaxMin.StartI = 0;
eclMaxMin.StartJ = 0;
eclMaxMin.StartK = 0;
eclMaxMin.EndI = eclGrid->cellCountI() - 1;
eclMaxMin.EndJ = eclGrid->cellCountJ() - 1;
eclMaxMin.EndK = eclGrid->cellCountK() - 1;
RigRangeEndPoints eclExtInFem;
convertRangeFilterEndPoints(eclMaxMin, eclExtInFem, eclGrid, femPart, true);
src.StartI = CVF_MAX(src.StartI, eclExtInFem.StartI);
src.StartJ = CVF_MAX(src.StartJ, eclExtInFem.StartJ);
src.StartK = CVF_MAX(src.StartK, eclExtInFem.StartK);
src.EndI = CVF_MIN(src.EndI , eclExtInFem.EndI);
src.EndJ = CVF_MIN(src.EndJ , eclExtInFem.EndJ);
src.EndK = CVF_MIN(src.EndK , eclExtInFem.EndK);
}
RigRangeEndPoints dst;
{
struct RangeFilterCorner { RangeFilterCorner() : isExactMatch(false){} cvf::Vec3st ijk; bool isExactMatch; };
convertRangeFilterEndPoints(src, dst, eclGrid, femPart, femIsDestination);
RangeFilterCorner rangeFilterMatches[8];
cvf::Vec3st srcRangeCube[8];
srcRangeCube[0] = cvf::Vec3st(src.StartI, src.StartJ, src.StartK);
srcRangeCube[1] = cvf::Vec3st(src.EndI, src.StartJ, src.StartK);
srcRangeCube[2] = cvf::Vec3st(src.EndI, src.EndJ, src.StartK);
srcRangeCube[3] = cvf::Vec3st(src.StartI, src.EndJ, src.StartK);
srcRangeCube[4] = cvf::Vec3st(src.StartI, src.StartJ, src.EndK);
srcRangeCube[5] = cvf::Vec3st(src.EndI, src.StartJ, src.EndK);
srcRangeCube[6] = cvf::Vec3st(src.EndI, src.EndJ, src.EndK);
srcRangeCube[7] = cvf::Vec3st(src.StartI, src.EndJ, src.EndK);
bool foundExactMatch = false;
int cornerIdx = 0;
int diagIdx = 6;// Index to diagonal corner
for (cornerIdx = 0; cornerIdx < 4; ++cornerIdx)
{
diagIdx = (cornerIdx < 2) ? cornerIdx + 6 : cornerIdx + 2;
if (femIsDestination)
{
rangeFilterMatches[cornerIdx].isExactMatch = findBestFemCellFromEclCell(eclGrid,
srcRangeCube[cornerIdx][0],
srcRangeCube[cornerIdx][1],
srcRangeCube[cornerIdx][2],
femPart,
&(rangeFilterMatches[cornerIdx].ijk[0]),
&(rangeFilterMatches[cornerIdx].ijk[1]),
&(rangeFilterMatches[cornerIdx].ijk[2]));
rangeFilterMatches[diagIdx].isExactMatch = findBestFemCellFromEclCell(eclGrid,
srcRangeCube[diagIdx][0],
srcRangeCube[diagIdx][1],
srcRangeCube[diagIdx][2],
femPart,
&(rangeFilterMatches[diagIdx].ijk[0]),
&(rangeFilterMatches[diagIdx].ijk[1]),
&(rangeFilterMatches[diagIdx].ijk[2]));
}
else
{
rangeFilterMatches[cornerIdx].isExactMatch = findBestEclCellFromFemCell(femPart,
srcRangeCube[cornerIdx][0],
srcRangeCube[cornerIdx][1],
srcRangeCube[cornerIdx][2],
eclGrid,
&(rangeFilterMatches[cornerIdx].ijk[0]),
&(rangeFilterMatches[cornerIdx].ijk[1]),
&(rangeFilterMatches[cornerIdx].ijk[2]));
rangeFilterMatches[diagIdx].isExactMatch = findBestEclCellFromFemCell(femPart,
srcRangeCube[diagIdx][0],
srcRangeCube[diagIdx][1],
srcRangeCube[diagIdx][2],
eclGrid,
&(rangeFilterMatches[diagIdx].ijk[0]),
&(rangeFilterMatches[diagIdx].ijk[1]),
&(rangeFilterMatches[diagIdx].ijk[2]));
}
if (rangeFilterMatches[cornerIdx].isExactMatch && rangeFilterMatches[diagIdx].isExactMatch)
{
foundExactMatch = true;
break;
}
}
// Get the start and end IJK from the matched corners
if (foundExactMatch)
{
// Populate dst range filter from the diagonal that matches exact
dst.StartI = CVF_MIN(rangeFilterMatches[cornerIdx].ijk[0], rangeFilterMatches[diagIdx].ijk[0]);
dst.StartJ = CVF_MIN(rangeFilterMatches[cornerIdx].ijk[1], rangeFilterMatches[diagIdx].ijk[1]);
dst.StartK = CVF_MIN(rangeFilterMatches[cornerIdx].ijk[2], rangeFilterMatches[diagIdx].ijk[2]);
dst.EndI = CVF_MAX(rangeFilterMatches[cornerIdx].ijk[0], rangeFilterMatches[diagIdx].ijk[0]);
dst.EndJ = CVF_MAX(rangeFilterMatches[cornerIdx].ijk[1], rangeFilterMatches[diagIdx].ijk[1]);
dst.EndK = CVF_MAX(rangeFilterMatches[cornerIdx].ijk[2], rangeFilterMatches[diagIdx].ijk[2]);
}
else
{
// Todo: be even smarter, and use possible matching corners to add up an as best solution as possible.
// For now we just take the first diagonal.
dst.StartI = rangeFilterMatches[0].ijk[0];
dst.StartJ = rangeFilterMatches[0].ijk[1];
dst.StartK = rangeFilterMatches[0].ijk[2];
dst.EndI = rangeFilterMatches[6].ijk[0];
dst.EndJ = rangeFilterMatches[6].ijk[1];
dst.EndK = rangeFilterMatches[6].ijk[2];
}
}
// Populate the dst range filter with new data
if ( dst.StartI != cvf::UNDEFINED_SIZE_T
@ -243,6 +177,112 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilter(RimCellRangeFilter* srcF
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeEndPoints &src,
RigRangeEndPoints &dst,
const RigMainGrid* eclGrid,
const RigFemPart* femPart,
bool femIsDestination)
{
{
struct RangeFilterCorner { RangeFilterCorner() : isExactMatch(false){} cvf::Vec3st ijk; bool isExactMatch; };
RangeFilterCorner rangeFilterMatches[8];
cvf::Vec3st srcRangeCube[8];
srcRangeCube[0] = cvf::Vec3st(src.StartI, src.StartJ, src.StartK);
srcRangeCube[1] = cvf::Vec3st(src.EndI , src.StartJ, src.StartK);
srcRangeCube[2] = cvf::Vec3st(src.EndI , src.EndJ , src.StartK);
srcRangeCube[3] = cvf::Vec3st(src.StartI, src.EndJ , src.StartK);
srcRangeCube[4] = cvf::Vec3st(src.StartI, src.StartJ, src.EndK);
srcRangeCube[5] = cvf::Vec3st(src.EndI , src.StartJ, src.EndK);
srcRangeCube[6] = cvf::Vec3st(src.EndI , src.EndJ , src.EndK);
srcRangeCube[7] = cvf::Vec3st(src.StartI, src.EndJ , src.EndK);
bool foundExactMatch = false;
int cornerIdx = 0;
int diagIdx = 6;// Index to diagonal corner
for (cornerIdx = 0; cornerIdx < 4; ++cornerIdx)
{
diagIdx = (cornerIdx < 2) ? cornerIdx + 6 : cornerIdx + 2;
if (femIsDestination)
{
rangeFilterMatches[cornerIdx].isExactMatch = findBestFemCellFromEclCell(eclGrid,
srcRangeCube[cornerIdx][0],
srcRangeCube[cornerIdx][1],
srcRangeCube[cornerIdx][2],
femPart,
&(rangeFilterMatches[cornerIdx].ijk[0]),
&(rangeFilterMatches[cornerIdx].ijk[1]),
&(rangeFilterMatches[cornerIdx].ijk[2]));
rangeFilterMatches[diagIdx].isExactMatch = findBestFemCellFromEclCell(eclGrid,
srcRangeCube[diagIdx][0],
srcRangeCube[diagIdx][1],
srcRangeCube[diagIdx][2],
femPart,
&(rangeFilterMatches[diagIdx].ijk[0]),
&(rangeFilterMatches[diagIdx].ijk[1]),
&(rangeFilterMatches[diagIdx].ijk[2]));
}
else
{
rangeFilterMatches[cornerIdx].isExactMatch = findBestEclCellFromFemCell(femPart,
srcRangeCube[cornerIdx][0],
srcRangeCube[cornerIdx][1],
srcRangeCube[cornerIdx][2],
eclGrid,
&(rangeFilterMatches[cornerIdx].ijk[0]),
&(rangeFilterMatches[cornerIdx].ijk[1]),
&(rangeFilterMatches[cornerIdx].ijk[2]));
rangeFilterMatches[diagIdx].isExactMatch = findBestEclCellFromFemCell(femPart,
srcRangeCube[diagIdx][0],
srcRangeCube[diagIdx][1],
srcRangeCube[diagIdx][2],
eclGrid,
&(rangeFilterMatches[diagIdx].ijk[0]),
&(rangeFilterMatches[diagIdx].ijk[1]),
&(rangeFilterMatches[diagIdx].ijk[2]));
}
if (rangeFilterMatches[cornerIdx].isExactMatch && rangeFilterMatches[diagIdx].isExactMatch)
{
foundExactMatch = true;
break;
}
}
// Get the start and end IJK from the matched corners
if (foundExactMatch)
{
// Populate dst range filter from the diagonal that matches exact
dst.StartI = CVF_MIN(rangeFilterMatches[cornerIdx].ijk[0], rangeFilterMatches[diagIdx].ijk[0]);
dst.StartJ = CVF_MIN(rangeFilterMatches[cornerIdx].ijk[1], rangeFilterMatches[diagIdx].ijk[1]);
dst.StartK = CVF_MIN(rangeFilterMatches[cornerIdx].ijk[2], rangeFilterMatches[diagIdx].ijk[2]);
dst.EndI = CVF_MAX(rangeFilterMatches[cornerIdx].ijk[0], rangeFilterMatches[diagIdx].ijk[0]);
dst.EndJ = CVF_MAX(rangeFilterMatches[cornerIdx].ijk[1], rangeFilterMatches[diagIdx].ijk[1]);
dst.EndK = CVF_MAX(rangeFilterMatches[cornerIdx].ijk[2], rangeFilterMatches[diagIdx].ijk[2]);
}
else
{
// Todo: be even smarter, and use possible matching corners to add up an as best solution as possible.
// For now we just take the first diagonal.
dst.StartI = rangeFilterMatches[0].ijk[0];
dst.StartJ = rangeFilterMatches[0].ijk[1];
dst.StartK = rangeFilterMatches[0].ijk[2];
dst.EndI = rangeFilterMatches[6].ijk[0];
dst.EndJ = rangeFilterMatches[6].ijk[1];
dst.EndK = rangeFilterMatches[6].ijk[2];
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -387,4 +427,3 @@ bool RigCaseToCaseRangeFilterMapper::findBestEclCellFromFemCell(const RigFemPart
return foundExactMatch;
}

View File

@ -23,6 +23,7 @@
class RimCellRangeFilter;
class RigMainGrid;
class RigFemPart;
struct RigRangeEndPoints;
class RigCaseToCaseRangeFilterMapper
{
@ -34,10 +35,16 @@ public:
private:
static void convertRangeFilter(RimCellRangeFilter* srcFilter, RimCellRangeFilter* dstFilter,
static void convertRangeFilter(const RimCellRangeFilter* srcFilter, RimCellRangeFilter* dstFilter,
const RigMainGrid* eclGrid, const RigFemPart* femPart,
bool femIsDestination);
static void convertRangeFilterEndPoints(const RigRangeEndPoints &src,
RigRangeEndPoints &dst,
const RigMainGrid* eclGrid,
const RigFemPart* femPart,
bool femIsDestination);
static bool findBestFemCellFromEclCell(const RigMainGrid* masterEclGrid, size_t ei, size_t ej, size_t ek,
const RigFemPart* dependentFemPart, size_t* fi, size_t * fj, size_t* fk);