//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- String ProgramOptions::usageText(int maxWidth, int maxOptionWidth) const { if (maxWidth <= 1) maxWidth = 2; if (maxOptionWidth <= 0) maxOptionWidth = maxWidth/2; const String prefixStr = prefixString(); std::vector<String> optAndValArr; std::vector<String> descrArr; int optAndValMaxLen = 0; const size_t numOpts = m_optionSpecs.size(); for (size_t i = 0; i < numOpts; i++) { const OptionSpec* spec = m_optionSpecs.at(i); String optAndVal = prefixStr + spec->m_name + String(" ") + spec->m_valueSyntax; optAndValMaxLen = CVF_MAX(optAndValMaxLen, static_cast<int>(optAndVal.size())); optAndValArr.push_back(optAndVal); descrArr.push_back(spec->m_descr); } const int firstColWidth = static_cast<int>(CVF_MIN(optAndValMaxLen + 1, maxOptionWidth)); const String firstColBlanks = String("%1").arg("", firstColWidth); String retStr; for (size_t iopt = 0; iopt < numOpts; iopt++) { const String optAndVal = optAndValArr[iopt]; const int maxDescrWidth = CVF_MAX((maxWidth - firstColWidth), 1); std::vector<String> descrLines = breakStringIntoLines(descrArr[iopt], static_cast<size_t>(maxDescrWidth)); String s = String("%1 ").arg(optAndValArr[iopt], -(firstColWidth - 1)); if (s.size() > static_cast<size_t>(firstColWidth) && descrLines.size() > 0) { s += "\n" + firstColBlanks; } for (size_t i = 0; i < descrLines.size(); i++) { if (i > 0) { s += "\n" + firstColBlanks; } s += descrLines[i]; } retStr += s + String("\n"); } return retStr; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimCellEdgeColors::minMaxCellEdgeValues(double& min, double& max) { double globalMin, globalMax; globalMin = HUGE_VAL; globalMax = -HUGE_VAL; size_t resultIndices[6]; this->gridScalarIndices(resultIndices); size_t idx; for (idx = 0; idx < 6; idx++) { if (resultIndices[idx] == cvf::UNDEFINED_SIZE_T) continue; { double cMin, cMax; m_reservoirView->currentGridCellResults()->cellResults()->minMaxCellScalarValues(resultIndices[idx], cMin, cMax); globalMin = CVF_MIN(globalMin, cMin); globalMax = CVF_MAX(globalMax, cMax); } } min = globalMin; max = globalMax; }
//-------------------------------------------------------------------------------------------------- /// Get the extent (width and height) of the given text with this font in pixels //-------------------------------------------------------------------------------------------------- cvf::Vec2ui Font::textExtent(const String& text) { std::vector<cvf::String> lines = text.split("\n"); float maxLineWidth = 0; uint textHeight = 0; uint lineSpacing = static_cast<uint>(this->lineSpacing()); for (size_t lineIdx = 0; lineIdx < lines.size(); ++lineIdx) { String line = lines[lineIdx]; size_t numCharacters = line.size(); float lineWidth = 0; for (size_t j = 0; j < numCharacters; ++j) { wchar_t character = line[j]; // Jump to the next character in the string, if any if (j < (numCharacters - 1)) { float advance = static_cast<float>(this->advance(character, text[j + 1])); lineWidth += advance; } else { ref<Glyph> glyph = getGlyph(character); lineWidth += static_cast<float>(glyph->width()) + static_cast<float>(glyph->horizontalBearingX()); } } maxLineWidth = CVF_MAX(lineWidth, maxLineWidth); if (lineIdx == 0) { ref<Glyph> glyph = getGlyph(L'A'); textHeight += glyph->height(); } else { textHeight += lineSpacing; } } return Vec2ui(static_cast<uint>(maxLineWidth), textHeight); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimLegendConfig::updateLegend() { double adjustedMin = cvf::UNDEFINED_DOUBLE; double adjustedMax = cvf::UNDEFINED_DOUBLE; double posClosestToZero = cvf::UNDEFINED_DOUBLE; double negClosestToZero = cvf::UNDEFINED_DOUBLE; if (m_rangeMode == AUTOMATIC_ALLTIMESTEPS) { adjustedMin = roundToNumSignificantDigits(m_globalAutoMin, m_precision); adjustedMax = roundToNumSignificantDigits(m_globalAutoMax, m_precision); posClosestToZero = m_globalAutoPosClosestToZero; negClosestToZero = m_globalAutoNegClosestToZero; } else if (m_rangeMode == AUTOMATIC_CURRENT_TIMESTEP) { adjustedMin = roundToNumSignificantDigits(m_localAutoMin, m_precision); adjustedMax = roundToNumSignificantDigits(m_localAutoMax, m_precision); posClosestToZero = m_localAutoPosClosestToZero; negClosestToZero = m_localAutoNegClosestToZero; } else { adjustedMin = roundToNumSignificantDigits(m_userDefinedMinValue, m_precision); adjustedMax = roundToNumSignificantDigits(m_userDefinedMaxValue, m_precision); posClosestToZero = m_globalAutoPosClosestToZero; negClosestToZero = m_globalAutoNegClosestToZero; } m_linDiscreteScalarMapper->setRange(adjustedMin, adjustedMax); m_linSmoothScalarMapper->setRange(adjustedMin, adjustedMax); if (m_mappingMode == LOG10_CONTINUOUS || m_mappingMode == LOG10_DISCRETE) { if (adjustedMin != adjustedMax) { if (adjustedMin == 0) { if (adjustedMax > adjustedMin) { adjustedMin = posClosestToZero; } else { adjustedMin = negClosestToZero; } } else if (adjustedMax == 0) { if (adjustedMin > adjustedMax) { adjustedMax = posClosestToZero; } else { adjustedMax = negClosestToZero; } } else if (adjustedMin < 0 && adjustedMax > 0) { adjustedMin = posClosestToZero; } else if (adjustedMax < 0 && adjustedMin > 0) { adjustedMin = negClosestToZero; } } } m_logDiscreteScalarMapper->setRange(adjustedMin, adjustedMax); m_logSmoothScalarMapper->setRange(adjustedMin, adjustedMax); cvf::Color3ubArray legendColors; switch (m_colorRangeMode()) { case NORMAL: { legendColors.reserve(7); legendColors.add(cvf::Color3ub( 0, 0, 255)); legendColors.add(cvf::Color3ub( 0, 127, 255)); legendColors.add(cvf::Color3ub( 0, 255, 255)); legendColors.add(cvf::Color3ub( 0, 255, 0)); legendColors.add(cvf::Color3ub(255, 255, 0)); legendColors.add(cvf::Color3ub(255, 127, 0)); legendColors.add(cvf::Color3ub(255, 0, 0)); } break; case OPPOSITE_NORMAL: { legendColors.reserve(7); legendColors.add(cvf::Color3ub(255, 0, 0)); legendColors.add(cvf::Color3ub(255, 127, 0)); legendColors.add(cvf::Color3ub(255, 255, 0)); legendColors.add(cvf::Color3ub( 0, 255, 0)); legendColors.add(cvf::Color3ub( 0, 255, 255)); legendColors.add(cvf::Color3ub( 0, 127, 255)); legendColors.add(cvf::Color3ub( 0, 0, 255)); } break; case BLACK_WHITE: case WHITE_BLACK: { legendColors.reserve(2); if (m_colorRangeMode() == BLACK_WHITE) { legendColors.add(cvf::Color3ub::BLACK); legendColors.add(cvf::Color3ub::WHITE); } else { legendColors.add(cvf::Color3ub::WHITE); legendColors.add(cvf::Color3ub::BLACK); } } break; case PINK_WHITE: case WHITE_PINK: { legendColors.reserve(2); if (m_colorRangeMode() == PINK_WHITE) { legendColors.add(cvf::Color3ub::DEEP_PINK); legendColors.add(cvf::Color3ub::WHITE); } else { legendColors.add(cvf::Color3ub::WHITE); legendColors.add(cvf::Color3ub::DEEP_PINK); } } break; case BLUE_WHITE_RED: case RED_WHITE_BLUE: { legendColors.reserve(3); if (m_colorRangeMode() == BLUE_WHITE_RED) { legendColors.add(cvf::Color3ub::BLUE); legendColors.add(cvf::Color3ub::WHITE); legendColors.add(cvf::Color3ub::RED); } else { legendColors.add(cvf::Color3ub::RED); legendColors.add(cvf::Color3ub::WHITE); legendColors.add(cvf::Color3ub::BLUE); } } break; } m_linDiscreteScalarMapper->setColors(legendColors); m_logDiscreteScalarMapper->setColors(legendColors); m_logSmoothScalarMapper->setColors(legendColors); m_linSmoothScalarMapper->setColors(legendColors); m_linDiscreteScalarMapper->setLevelCount(m_numLevels, true); m_logDiscreteScalarMapper->setLevelCount(m_numLevels, true); m_logSmoothScalarMapper->setLevelCount(m_numLevels, true); m_linSmoothScalarMapper->setLevelCount(m_numLevels, true); switch(m_mappingMode()) { case LINEAR_DISCRETE: m_currentScalarMapper = m_linDiscreteScalarMapper.p(); break; case LINEAR_CONTINUOUS: m_currentScalarMapper = m_linSmoothScalarMapper.p(); break; case LOG10_CONTINUOUS: m_currentScalarMapper = m_logSmoothScalarMapper.p(); break; case LOG10_DISCRETE: m_currentScalarMapper = m_logDiscreteScalarMapper.p(); break; default: break; } m_legend->setScalarMapper(m_currentScalarMapper.p()); double decadesInRange = 0; if (m_mappingMode == LOG10_CONTINUOUS || m_mappingMode == LOG10_DISCRETE) { // For log mapping, use the min value as reference for num valid digits decadesInRange = cvf::Math::abs(adjustedMin) < cvf::Math::abs(adjustedMax) ? cvf::Math::abs(adjustedMin) : cvf::Math::abs(adjustedMax); decadesInRange = log10(decadesInRange); } else { // For linear mapping, use the max value as reference for num valid digits double absRange = CVF_MAX(cvf::Math::abs(adjustedMax), cvf::Math::abs(adjustedMin)); decadesInRange = log10(absRange); } decadesInRange = cvf::Math::ceil(decadesInRange); // Using Fixed format NumberFormatType nft = m_tickNumberFormat(); m_legend->setTickFormat((cvf::OverlayScalarMapperLegend::NumberFormat)nft); // Set the fixed number of digits after the decimal point to the number needed to show all the significant digits. int numDecimalDigits = m_precision(); if (nft != SCIENTIFIC) { numDecimalDigits -= static_cast<int>(decadesInRange); } m_legend->setTickPrecision(cvf::Math::clamp(numDecimalDigits, 0, 20)); if (m_globalAutoMax != cvf::UNDEFINED_DOUBLE ) { m_userDefinedMaxValue.setUiName(QString("Max ") + "(" + QString::number(m_globalAutoMax, 'g', m_precision) + ")"); } else { m_userDefinedMaxValue.setUiName(QString()); } if (m_globalAutoMin != cvf::UNDEFINED_DOUBLE ) { m_userDefinedMinValue.setUiName(QString("Min ") + "(" + QString::number(m_globalAutoMin, 'g', m_precision) + ")"); } else { m_userDefinedMinValue.setUiName(QString()); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigCaseCellResultsData::minMaxCellScalarValues(size_t scalarResultIndex, size_t timeStepIndex, double& min, double& max) { min = HUGE_VAL; max = -HUGE_VAL; CVF_ASSERT(scalarResultIndex < resultCount()); if (timeStepIndex >= m_cellScalarResults[scalarResultIndex].size()) { return; } if (scalarResultIndex >= m_maxMinValuesPrTs.size()) { m_maxMinValuesPrTs.resize(scalarResultIndex+1); } if (timeStepIndex >= m_maxMinValuesPrTs[scalarResultIndex].size()) { m_maxMinValuesPrTs[scalarResultIndex].resize(timeStepIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL)); } if (m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first != HUGE_VAL) { min = m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first; max = m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].second; return; } if (scalarResultIndex == m_combinedTransmissibilityResultIndex) { size_t tranX, tranY, tranZ; if (!findTransmissibilityResults(tranX, tranY, tranZ)) return; double tranMin; double tranMax; minMaxCellScalarValues(tranX, timeStepIndex, tranMin, tranMax); min = CVF_MIN(tranMin, min); max = CVF_MAX(tranMax, max); minMaxCellScalarValues(tranY, timeStepIndex, tranMin, tranMax); min = CVF_MIN(tranMin, min); max = CVF_MAX(tranMax, max); minMaxCellScalarValues(tranZ, timeStepIndex, tranMin, tranMax); min = CVF_MIN(tranMin, min); max = CVF_MAX(tranMax, max); return; } std::vector<double>& values = m_cellScalarResults[scalarResultIndex][timeStepIndex]; size_t i; for (i = 0; i < values.size(); i++) { if (values[i] == HUGE_VAL) { continue; } if (values[i] < min) { min = values[i]; } if (values[i] > max) { max = values[i]; } } m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first = min; m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].second= max; }
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; // 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; } // Clamp the src end points to be inside the src model { size_t maxIIndex; size_t maxJIndex; size_t maxKIndex; // Clamp end if (femIsDestination) { maxIIndex = eclGrid->cellCountI()- 1; maxJIndex = eclGrid->cellCountJ()- 1; maxKIndex = eclGrid->cellCountK()- 1; } else { maxIIndex = femPart->structGrid()->cellCountI()- 1; maxJIndex = femPart->structGrid()->cellCountJ()- 1; maxKIndex = femPart->structGrid()->cellCountK()- 1; } src.EndI = CVF_MIN(src.EndI, maxIIndex); src.EndJ = CVF_MIN(src.EndJ, maxJIndex); 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; convertRangeFilterEndPoints(src, dst, eclGrid, femPart, femIsDestination); // Populate the dst range filter with new data if ( dst.StartI != cvf::UNDEFINED_SIZE_T && dst.StartJ != cvf::UNDEFINED_SIZE_T && dst.StartK != cvf::UNDEFINED_SIZE_T && dst.EndI != cvf::UNDEFINED_SIZE_T && dst.EndJ != cvf::UNDEFINED_SIZE_T && dst.EndK != cvf::UNDEFINED_SIZE_T) { dstFilter->startIndexI = static_cast<int>(dst.StartI + 1); dstFilter->startIndexJ = static_cast<int>(dst.StartJ + 1); dstFilter->startIndexK = static_cast<int>(dst.StartK + 1); dstFilter->cellCountI = static_cast<int>(dst.EndI - (dst.StartI-1)); dstFilter->cellCountJ = static_cast<int>(dst.EndJ - (dst.StartJ-1)); dstFilter->cellCountK = static_cast<int>(dst.EndK - (dst.StartK-1)); } else { dstFilter->startIndexI = 1; dstFilter->startIndexJ = 1; dstFilter->startIndexK = 1; dstFilter->cellCountI = 0; dstFilter->cellCountJ = 0; dstFilter->cellCountK = 0; } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeEndPoints &src, RigRangeEndPoints &dst, const RigMainGrid* eclGrid, const RigFemPart* femPart, bool femIsDestination) { { struct RangeFilterCorner { RangeFilterCorner() : cellMatchType(APPROX_ON_COLLAPSED){} cvf::Vec3st ijk; CellMatchType cellMatchType; }; 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].cellMatchType = 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].cellMatchType = 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].cellMatchType = 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].cellMatchType = 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].cellMatchType == EXACT && rangeFilterMatches[diagIdx].cellMatchType == EXACT) { 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 { // Look at the matches for each "face" of the range filter cube, // and use first exact match to determine the position of that "face" size_t faceIJKs[6] = {cvf::UNDEFINED_SIZE_T, cvf::UNDEFINED_SIZE_T,cvf::UNDEFINED_SIZE_T,cvf::UNDEFINED_SIZE_T,cvf::UNDEFINED_SIZE_T,cvf::UNDEFINED_SIZE_T}; for (int faceIdx = 0; faceIdx < 6; ++faceIdx) { int ijOrk = 0; if (faceIdx == cvf::StructGridInterface::POS_I || faceIdx == cvf::StructGridInterface::NEG_I) ijOrk = 0; if (faceIdx == cvf::StructGridInterface::POS_J || faceIdx == cvf::StructGridInterface::NEG_J) ijOrk = 1; if (faceIdx == cvf::StructGridInterface::POS_K || faceIdx == cvf::StructGridInterface::NEG_K) ijOrk = 2; cvf::ubyte surfCorners[4]; cvf::StructGridInterface::cellFaceVertexIndices((cvf::StructGridInterface::FaceType) faceIdx , surfCorners); bool foundAcceptedMatch = false; for (int cIdx = 0; cIdx < 4; ++cIdx) { if (rangeFilterMatches[surfCorners[cIdx]].cellMatchType == EXACT) { foundAcceptedMatch = true; faceIJKs[faceIdx] = rangeFilterMatches[surfCorners[cIdx]].ijk[ijOrk]; break; } } if (!foundAcceptedMatch) { // Take first match that is not related to a collapsed eclipse cell for (int cIdx = 0; cIdx < 4; ++cIdx) { if (rangeFilterMatches[surfCorners[cIdx]].cellMatchType == APPROX) { foundAcceptedMatch = true; faceIJKs[faceIdx] = rangeFilterMatches[surfCorners[cIdx]].ijk[ijOrk]; break; } } if (!foundAcceptedMatch) { // Only collapsed cell hits in this "face" // Todo: then use opposite face - range filter thickness // For now, just select the first faceIJKs[faceIdx] = rangeFilterMatches[surfCorners[0]].ijk[ijOrk]; } } } #ifdef DEBUG for (int faceIdx = 0; faceIdx <6; ++faceIdx) {CVF_TIGHT_ASSERT(faceIJKs[faceIdx] != cvf::UNDEFINED_SIZE_T);} #endif dst.EndI = faceIJKs[cvf::StructGridInterface::POS_I]; dst.StartI = faceIJKs[cvf::StructGridInterface::NEG_I]; dst.EndJ = faceIJKs[cvf::StructGridInterface::POS_J]; dst.StartJ = faceIJKs[cvf::StructGridInterface::NEG_J]; dst.EndK = faceIJKs[cvf::StructGridInterface::POS_K]; dst.StartK = faceIJKs[cvf::StructGridInterface::NEG_K]; } } }
//-------------------------------------------------------------------------------------------------- /// Generate surface representation of the specified cut plane /// /// \note Will compute normals before returning geometry //-------------------------------------------------------------------------------------------------- void StructGridCutPlane::computeCutPlane() { DebugTimer tim("StructGridCutPlane::computeCutPlane", DebugTimer::DISABLED); bool doMapScalar = false; if (m_mapScalarSetIndex != UNDEFINED_UINT && m_scalarMapper.notNull()) { doMapScalar = true; } uint cellCountI = m_grid->cellCountI(); uint cellCountJ = m_grid->cellCountJ(); uint cellCountK = m_grid->cellCountK(); // Clear any current data m_vertices.clear(); m_vertexScalars.clear(); m_triangleIndices.clear(); m_meshLineIndices.clear(); // The indexing conventions for vertices and // edges used in the algorithm: // edg verts // 4-------------5 *------4------* 0 0 - 1 // /| /| /| /| 1 1 - 2 // / | / | 7/ | 5/ | 2 2 - 3 // / | / | |z / 8 / 9 3 3 - 0 // 7-------------6 | | /y *------6------* | 4 4 - 5 // | | | | |/ | | | | 5 5 - 6 // | 0---------|---1 *---x | *------0--|---* 6 6 - 7 // | / | / 11 / 10 / 7 7 - 4 // | / | / | /3 | /1 8 0 - 4 // |/ |/ |/ |/ 9 1 - 5 // 3-------------2 *------2------* 10 2 - 6 // vertex indices edge indices 11 3 - 7 // uint k; for (k = 0; k < cellCountK; k++) { uint j; for (j = 0; j < cellCountJ; j++) { uint i; for (i = 0; i < cellCountI; i++) { size_t cellIndex = m_grid->cellIndexFromIJK(i, j, k); Vec3d minCoord; Vec3d maxCoord; m_grid->cellMinMaxCordinates(cellIndex, &minCoord, &maxCoord); // Early reject for cells outside clipping box if (m_clippingBoundingBox.isValid()) { BoundingBox cellBB(minCoord, maxCoord); if (!m_clippingBoundingBox.intersects(cellBB)) { continue; } } // Check if plane intersects this cell and skip if it doesn't if (!isCellIntersectedByPlane(m_plane, minCoord, maxCoord)) { continue; } GridCell cell; bool isClipped = false; if (m_clippingBoundingBox.isValid()) { if (!m_clippingBoundingBox.contains(minCoord) || !m_clippingBoundingBox.contains(maxCoord)) { isClipped = true; minCoord.x() = CVF_MAX(minCoord.x(), m_clippingBoundingBox.min().x()); minCoord.y() = CVF_MAX(minCoord.y(), m_clippingBoundingBox.min().y()); minCoord.z() = CVF_MAX(minCoord.z(), m_clippingBoundingBox.min().z()); maxCoord.x() = CVF_MIN(maxCoord.x(), m_clippingBoundingBox.max().x()); maxCoord.y() = CVF_MIN(maxCoord.y(), m_clippingBoundingBox.max().y()); maxCoord.z() = CVF_MIN(maxCoord.z(), m_clippingBoundingBox.max().z()); } } cell.p[0].set(minCoord.x(), maxCoord.y(), minCoord.z()); cell.p[1].set(maxCoord.x(), maxCoord.y(), minCoord.z()); cell.p[2].set(maxCoord.x(), minCoord.y(), minCoord.z()); cell.p[3].set(minCoord.x(), minCoord.y(), minCoord.z()); cell.p[4].set(minCoord.x(), maxCoord.y(), maxCoord.z()); cell.p[5].set(maxCoord.x(), maxCoord.y(), maxCoord.z()); cell.p[6].set(maxCoord.x(), minCoord.y(), maxCoord.z()); cell.p[7].set(minCoord.x(), minCoord.y(), maxCoord.z()); // Fetch scalar values double cellScalarValue = 0; if (doMapScalar) { cellScalarValue = m_grid->cellScalar(m_mapScalarSetIndex, i, j, k); // If we're doing node averaging we must populate grid cell with scalar values interpolated to the grid points if (m_mapNodeAveragedScalars) { if (isClipped) { double scalarVal; if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[0], &scalarVal)) cell.s[0] = scalarVal; if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[1], &scalarVal)) cell.s[1] = scalarVal; if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[2], &scalarVal)) cell.s[2] = scalarVal; if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[3], &scalarVal)) cell.s[3] = scalarVal; if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[4], &scalarVal)) cell.s[4] = scalarVal; if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[5], &scalarVal)) cell.s[5] = scalarVal; if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[6], &scalarVal)) cell.s[6] = scalarVal; if (m_grid->pointScalar(m_mapScalarSetIndex, cell.p[7], &scalarVal)) cell.s[7] = scalarVal; } else { cell.s[0] = m_grid->gridPointScalar(m_mapScalarSetIndex, i, j + 1, k); cell.s[1] = m_grid->gridPointScalar(m_mapScalarSetIndex, i + 1, j + 1, k); cell.s[2] = m_grid->gridPointScalar(m_mapScalarSetIndex, i + 1, j, k); cell.s[3] = m_grid->gridPointScalar(m_mapScalarSetIndex, i, j, k); cell.s[4] = m_grid->gridPointScalar(m_mapScalarSetIndex, i, j + 1, k + 1); cell.s[5] = m_grid->gridPointScalar(m_mapScalarSetIndex, i + 1, j + 1, k + 1); cell.s[6] = m_grid->gridPointScalar(m_mapScalarSetIndex, i + 1, j, k + 1); cell.s[7] = m_grid->gridPointScalar(m_mapScalarSetIndex, i, j, k + 1); } } } Triangles triangles; uint numTriangles = polygonise(m_plane, cell, &triangles); if (numTriangles > 0) { // Add all the referenced vertices // At the same time registering their index in the 'global' vertex list uint globalVertexIndices[12]; int iv; for (iv = 0; iv < 12; iv++) { if (triangles.usedVertices[iv]) { globalVertexIndices[iv] = static_cast<uint>(m_vertices.size()); m_vertices.push_back(Vec3f(triangles.vertices[iv])); if (doMapScalar) { if (m_mapNodeAveragedScalars) { m_vertexScalars.push_back(triangles.scalars[iv]); } else { m_vertexScalars.push_back(cellScalarValue); } } } else { globalVertexIndices[iv] = UNDEFINED_UINT; } } // Build triangles from the cell const size_t prevNumTriangleIndices = m_triangleIndices.size(); uint t; for (t = 0; t < numTriangles; t++) { m_triangleIndices.push_back(globalVertexIndices[triangles.triangleIndices[3*t]]); m_triangleIndices.push_back(globalVertexIndices[triangles.triangleIndices[3*t + 1]]); m_triangleIndices.push_back(globalVertexIndices[triangles.triangleIndices[3*t + 2]]); } // Add mesh line indices addMeshLineIndices(&m_triangleIndices[prevNumTriangleIndices], numTriangles); } } } } //Trace::show("Vertices:%d TriConns:%d Tris:%d", m_vertices.size(), m_triangleIndices.size(), m_triangleIndices.size()/3); tim.reportTimeMS(); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseOutput::readWellCells(RigReservoir* reservoir) { CVF_ASSERT(reservoir); if (m_dynamicResultsAccess.isNull()) return; well_info_type* ert_well_info = well_info_alloc(NULL); if (!ert_well_info) return; m_dynamicResultsAccess->readWellData(ert_well_info); RigMainGrid* mainGrid = reservoir->mainGrid(); std::vector<RigGridBase*> grids; reservoir->allGrids(&grids); cvf::Collection<RigWellResults> wells; caf::ProgressInfo progress(well_info_get_num_wells(ert_well_info), ""); int wellIdx; for (wellIdx = 0; wellIdx < well_info_get_num_wells(ert_well_info); wellIdx++) { const char* wellName = well_info_iget_well_name(ert_well_info, wellIdx); CVF_ASSERT(wellName); cvf::ref<RigWellResults> wellResults = new RigWellResults; wellResults->m_wellName = wellName; well_ts_type* ert_well_time_series = well_info_get_ts(ert_well_info , wellName); int timeStepCount = well_ts_get_size(ert_well_time_series); wellResults->m_wellCellsTimeSteps.resize(timeStepCount); int timeIdx; for (timeIdx = 0; timeIdx < timeStepCount; timeIdx++) { well_state_type* ert_well_state = well_ts_iget_state(ert_well_time_series, timeIdx); RigWellResultFrame& wellResFrame = wellResults->m_wellCellsTimeSteps[timeIdx]; // Build timestamp for well // Also see RifEclipseOutputFileAccess::timeStepsText for accessing time_t structures { time_t stepTime = well_state_get_sim_time(ert_well_state); wellResFrame.m_timestamp = QDateTime::fromTime_t(stepTime); } // Production type well_type_enum ert_well_type = well_state_get_type(ert_well_state); if (ert_well_type == PRODUCER) { wellResFrame.m_productionType = RigWellResultFrame::PRODUCER; } else if (ert_well_type == WATER_INJECTOR) { wellResFrame.m_productionType = RigWellResultFrame::WATER_INJECTOR; } else if (ert_well_type == GAS_INJECTOR) { wellResFrame.m_productionType = RigWellResultFrame::GAS_INJECTOR; } else if (ert_well_type == OIL_INJECTOR) { wellResFrame.m_productionType = RigWellResultFrame::OIL_INJECTOR; } else { wellResFrame.m_productionType = RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE; } wellResFrame.m_isOpen = well_state_is_open( ert_well_state ); // Loop over all the grids in the model. If we have connections in one, we will discard // the maingrid connections as they are "duplicates" bool hasWellConnectionsInLGR = false; for (size_t gridNr = 1; gridNr < grids.size(); ++gridNr) { int branchCount = well_state_iget_lgr_num_branches(ert_well_state, static_cast<int>(gridNr)); if (branchCount > 0) { hasWellConnectionsInLGR = true; break; } } size_t gridNr = hasWellConnectionsInLGR ? 1 : 0; for (; gridNr < grids.size(); ++gridNr) { // Wellhead. If several grids have a wellhead definition for this well, we use tha last one. (Possibly the innermost LGR) const well_conn_type* ert_wellhead = well_state_iget_wellhead(ert_well_state, static_cast<int>(gridNr)); if (ert_wellhead) { int cellI = well_conn_get_i( ert_wellhead ); int cellJ = well_conn_get_j( ert_wellhead ); int cellK = CVF_MAX(0, well_conn_get_k(ert_wellhead)); // Why this ? // If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1 // Adjust K so index is always in valid grid region if (cellK >= grids[gridNr]->cellCountK()) { cellK -= static_cast<int>(grids[gridNr]->cellCountK()); } wellResFrame.m_wellHead.m_gridCellIndex = grids[gridNr]->cellIndexFromIJK(cellI, cellJ, cellK); wellResFrame.m_wellHead.m_gridIndex = gridNr; } int branchCount = well_state_iget_lgr_num_branches(ert_well_state, static_cast<int>(gridNr)); if (branchCount > 0) { if (static_cast<int>(wellResFrame.m_wellResultBranches.size()) < branchCount) wellResFrame.m_wellResultBranches.resize(branchCount); for (int branchIdx = 0; branchIdx < branchCount; ++branchIdx ) { // Connections int connectionCount = well_state_iget_num_lgr_connections(ert_well_state, static_cast<int>(gridNr), branchIdx); if (connectionCount > 0) { RigWellResultBranch& wellSegment = wellResFrame.m_wellResultBranches[branchIdx]; // Is this completely right? Is the branch index actually the same between lgrs ? wellSegment.m_branchNumber = branchIdx; size_t existingConnCount = wellSegment.m_wellCells.size(); wellSegment.m_wellCells.resize(existingConnCount + connectionCount); int connIdx; for (connIdx = 0; connIdx < connectionCount; connIdx++) { const well_conn_type* ert_connection = well_state_iget_lgr_connections( ert_well_state, static_cast<int>(gridNr), branchIdx)[connIdx]; CVF_ASSERT(ert_connection); RigWellResultCell& data = wellSegment.m_wellCells[existingConnCount + connIdx]; data.m_gridIndex = gridNr; { int cellI = well_conn_get_i( ert_connection ); int cellJ = well_conn_get_j( ert_connection ); int cellK = well_conn_get_k( ert_connection ); bool open = well_conn_open( ert_connection ); int branch = well_conn_get_branch( ert_connection ); int segment = well_conn_get_segment( ert_connection ); // If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1 // Adjust K so index is always in valid grid region if (cellK >= grids[gridNr]->cellCountK()) { cellK -= static_cast<int>(grids[gridNr]->cellCountK()); } data.m_gridCellIndex = grids[gridNr]->cellIndexFromIJK(cellI , cellJ , cellK); data.m_isOpen = open; data.m_branchId = branch; data.m_segmentId = segment; } } } } } } } wellResults->computeMappingFromResultTimeIndicesToWellTimeIndices(m_timeSteps); wells.push_back(wellResults.p()); progress.incrementProgress(); } well_info_free(ert_well_info); reservoir->setWellResults(wells); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimLegendConfig::updateLegend() { double adjustedMin = cvf::UNDEFINED_DOUBLE; double adjustedMax = cvf::UNDEFINED_DOUBLE; double posClosestToZero = cvf::UNDEFINED_DOUBLE; double negClosestToZero = cvf::UNDEFINED_DOUBLE; if (m_rangeMode == AUTOMATIC_ALLTIMESTEPS) { adjustedMin = roundToNumSignificantDigits(m_globalAutoMin, m_precision); adjustedMax = roundToNumSignificantDigits(m_globalAutoMax, m_precision); posClosestToZero = m_globalAutoPosClosestToZero; negClosestToZero = m_globalAutoNegClosestToZero; } else if (m_rangeMode == AUTOMATIC_CURRENT_TIMESTEP) { adjustedMin = roundToNumSignificantDigits(m_localAutoMin, m_precision); adjustedMax = roundToNumSignificantDigits(m_localAutoMax, m_precision); posClosestToZero = m_localAutoPosClosestToZero; negClosestToZero = m_localAutoNegClosestToZero; } else { adjustedMin = roundToNumSignificantDigits(m_userDefinedMinValue, m_precision); adjustedMax = roundToNumSignificantDigits(m_userDefinedMaxValue, m_precision); posClosestToZero = m_globalAutoPosClosestToZero; negClosestToZero = m_globalAutoNegClosestToZero; } m_linDiscreteScalarMapper->setRange(adjustedMin, adjustedMax); m_linSmoothScalarMapper->setRange(adjustedMin, adjustedMax); if (m_mappingMode == LOG10_CONTINUOUS || m_mappingMode == LOG10_DISCRETE) { if (adjustedMin != adjustedMax) { if (adjustedMin == 0) { if (adjustedMax > adjustedMin) { adjustedMin = posClosestToZero; } else { adjustedMin = negClosestToZero; } } else if (adjustedMax == 0) { if (adjustedMin > adjustedMax) { adjustedMax = posClosestToZero; } else { adjustedMax = negClosestToZero; } } else if (adjustedMin < 0 && adjustedMax > 0) { adjustedMin = posClosestToZero; } else if (adjustedMax < 0 && adjustedMin > 0) { adjustedMin = negClosestToZero; } } } m_logDiscreteScalarMapper->setRange(adjustedMin, adjustedMax); m_logSmoothScalarMapper->setRange(adjustedMin, adjustedMax); cvf::Color3ubArray legendColors; switch (m_colorRangeMode()) { case NORMAL: { legendColors.reserve(7); legendColors.add(cvf::Color3ub( 0, 0, 255)); legendColors.add(cvf::Color3ub( 0, 127, 255)); legendColors.add(cvf::Color3ub( 0, 255, 255)); legendColors.add(cvf::Color3ub( 0, 255, 0)); legendColors.add(cvf::Color3ub(255, 255, 0)); legendColors.add(cvf::Color3ub(255, 127, 0)); legendColors.add(cvf::Color3ub(255, 0, 0)); } break; case OPPOSITE_NORMAL: { legendColors.reserve(7); legendColors.add(cvf::Color3ub(255, 0, 0)); legendColors.add(cvf::Color3ub(255, 127, 0)); legendColors.add(cvf::Color3ub(255, 255, 0)); legendColors.add(cvf::Color3ub( 0, 255, 0)); legendColors.add(cvf::Color3ub( 0, 255, 255)); legendColors.add(cvf::Color3ub( 0, 127, 255)); legendColors.add(cvf::Color3ub( 0, 0, 255)); } break; case BLACK_WHITE: case WHITE_BLACK: { legendColors.reserve(2); if (m_colorRangeMode() == BLACK_WHITE) { legendColors.add(cvf::Color3ub::BLACK); legendColors.add(cvf::Color3ub::WHITE); } else { legendColors.add(cvf::Color3ub::WHITE); legendColors.add(cvf::Color3ub::BLACK); } } break; case PINK_WHITE: case WHITE_PINK: { legendColors.reserve(2); if (m_colorRangeMode() == PINK_WHITE) { legendColors.add(cvf::Color3ub::DEEP_PINK); legendColors.add(cvf::Color3ub::WHITE); } else { legendColors.add(cvf::Color3ub::WHITE); legendColors.add(cvf::Color3ub::DEEP_PINK); } } break; case BLUE_WHITE_RED: case RED_WHITE_BLUE: { legendColors.reserve(3); if (m_colorRangeMode() == BLUE_WHITE_RED) { legendColors.add(cvf::Color3ub::BLUE); legendColors.add(cvf::Color3ub::WHITE); legendColors.add(cvf::Color3ub::RED); } else { legendColors.add(cvf::Color3ub::RED); legendColors.add(cvf::Color3ub::WHITE); legendColors.add(cvf::Color3ub::BLUE); } } break; case CATEGORY: { // Based on http://stackoverflow.com/questions/470690/how-to-automatically-generate-n-distinct-colors // and Kelly Colors and sorted by hue // See also http://www.w3schools.com/colors/ for palettes etc. legendColors.reserve(20); legendColors.add(cvf::Color3ub(128, 62, 117)); // hwb(310, 24%, 50%) strong_purple legendColors.add(cvf::Color3ub(212, 28, 132)); // hwb(326, 11%, 17%) strong_purplish_red legendColors.add(cvf::Color3ub(246, 118, 142)); // hwb(349, 46%, 4%) strong_purplish_pink legendColors.add(cvf::Color3ub(193, 0, 32)); // hwb(350, 0%, 24%) vivid_red legendColors.add(cvf::Color3ub(127, 24, 13)); // hwb( 6, 5%, 50%) strong_reddish_brown legendColors.add(cvf::Color3ub(241, 58, 19)); // hwb( 11, 7%, 5%) vivid_reddish_orange legendColors.add(cvf::Color3ub(255, 122, 92)); // hwb( 11, 36%, 0%) strong_yellowish_pink legendColors.add(cvf::Color3ub(129, 112, 102)); // hwb( 22, 40%, 49%) medium_gray legendColors.add(cvf::Color3ub(255, 104, 0)); // hwb( 24, 0%, 0%) vivid_orange legendColors.add(cvf::Color3ub( 89, 51, 21)); // hwb( 26, 8%, 65%) deep_yellowish_brown legendColors.add(cvf::Color3ub(255, 142, 0)); // hwb( 33, 0%, 0%) vivid_orange_yellow legendColors.add(cvf::Color3ub(206, 162, 98)); // hwb( 36, 38%, 19%) grayish_yellow legendColors.add(cvf::Color3ub(244, 200, 0)); // hwb( 49, 0%, 4%) vivid_greenish_yellow legendColors.add(cvf::Color3ub(147, 170, 0)); // hwb( 68, 0%, 33%) vivid_yellowish_green legendColors.add(cvf::Color3ub( 59, 84, 23)); // hwb( 85, 9%, 67%) dark_olive_green legendColors.add(cvf::Color3ub( 0, 125, 52)); // hwb(145, 0%, 51%) vivid_green legendColors.add(cvf::Color3ub( 54, 125, 123)); // hwb(178, 21%, 51%) vivid_blueish_green legendColors.add(cvf::Color3ub( 0, 83, 138)); // hwb(204, 0%, 46%) strong_blue legendColors.add(cvf::Color3ub(166, 189, 215)); // hwb(212, 65%, 16%) very_light_blue legendColors.add(cvf::Color3ub( 46, 76, 224)); // hwb(230, 18%, 12%) medium_blue } break; case ANGULAR: { legendColors.reserve(9); legendColors.add(cvf::Color3ub(255, 0, 255)); legendColors.add(cvf::Color3ub(0, 0, 255)); legendColors.add(cvf::Color3ub(0, 127, 255)); legendColors.add(cvf::Color3ub(0, 255, 255)); legendColors.add(cvf::Color3ub(0, 255, 0)); legendColors.add(cvf::Color3ub(255, 255, 0)); legendColors.add(cvf::Color3ub(255, 127, 0)); legendColors.add(cvf::Color3ub(255, 0, 0)); legendColors.add(cvf::Color3ub(255, 0, 255)); } break; } m_linDiscreteScalarMapper->setColors(legendColors); m_logDiscreteScalarMapper->setColors(legendColors); m_logSmoothScalarMapper->setColors(legendColors); m_linSmoothScalarMapper->setColors(legendColors); m_linDiscreteScalarMapper->setLevelCount(m_numLevels, true); m_logDiscreteScalarMapper->setLevelCount(m_numLevels, true); m_logSmoothScalarMapper->setLevelCount(m_numLevels, true); m_linSmoothScalarMapper->setLevelCount(m_numLevels, true); switch(m_mappingMode()) { case LINEAR_DISCRETE: m_currentScalarMapper = m_linDiscreteScalarMapper.p(); break; case LINEAR_CONTINUOUS: m_currentScalarMapper = m_linSmoothScalarMapper.p(); break; case LOG10_CONTINUOUS: m_currentScalarMapper = m_logSmoothScalarMapper.p(); break; case LOG10_DISCRETE: m_currentScalarMapper = m_logDiscreteScalarMapper.p(); break; case CATEGORY_INTEGER: m_categoryMapper->setCategoriesWithNames(m_categories, m_categoryNames); m_categoryMapper->setInterpolateColors(legendColors); m_currentScalarMapper = m_categoryMapper.p(); break; default: break; } if (m_currentScalarMapper != m_categoryMapper.p()) { m_scalarMapperLegend->setScalarMapper(m_currentScalarMapper.p()); } double decadesInRange = 0; if (m_mappingMode == LOG10_CONTINUOUS || m_mappingMode == LOG10_DISCRETE) { // For log mapping, use the min value as reference for num valid digits decadesInRange = cvf::Math::abs(adjustedMin) < cvf::Math::abs(adjustedMax) ? cvf::Math::abs(adjustedMin) : cvf::Math::abs(adjustedMax); decadesInRange = log10(decadesInRange); } else { // For linear mapping, use the max value as reference for num valid digits double absRange = CVF_MAX(cvf::Math::abs(adjustedMax), cvf::Math::abs(adjustedMin)); decadesInRange = log10(absRange); } decadesInRange = cvf::Math::ceil(decadesInRange); // Using Fixed format NumberFormatType nft = m_tickNumberFormat(); m_scalarMapperLegend->setTickFormat((cvf::OverlayScalarMapperLegend::NumberFormat)nft); // Set the fixed number of digits after the decimal point to the number needed to show all the significant digits. int numDecimalDigits = m_precision(); if (nft != SCIENTIFIC) { numDecimalDigits -= static_cast<int>(decadesInRange); } m_scalarMapperLegend->setTickPrecision(cvf::Math::clamp(numDecimalDigits, 0, 20)); if (m_globalAutoMax != cvf::UNDEFINED_DOUBLE ) { m_userDefinedMaxValue.uiCapability()->setUiName(QString("Max ") + "(" + QString::number(m_globalAutoMax, 'g', m_precision) + ")"); } else { m_userDefinedMaxValue.uiCapability()->setUiName(QString()); } if (m_globalAutoMin != cvf::UNDEFINED_DOUBLE ) { m_userDefinedMinValue.uiCapability()->setUiName(QString("Min ") + "(" + QString::number(m_globalAutoMin, 'g', m_precision) + ")"); } else { m_userDefinedMinValue.uiCapability()->setUiName(QString()); } }
//-------------------------------------------------------------------------------------------------- /// 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 = nullptr; 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", " "); // Remove character ' used to mark start and end of fault name, possibly also around face definition; 'I+' line.remove("'"); QStringList entries = line.split(" ", QString::SkipEmptyParts); if (entries.size() < 8) { continue; } QString name = entries[0]; 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]; cvf::StructGridInterface::FaceEnum cellFaceEnum = RifEclipseInputFileTools::faceEnumFromText(faceString); // Adjust from 1-based to 0-based cell indices // Guard against invalid cell ranges by limiting lowest possible range value to zero cvf::CellRange cellrange(CVF_MAX(i1 - 1, 0), CVF_MAX(j1 - 1, 0), CVF_MAX(k1 - 1, 0), CVF_MAX(i2 - 1, 0), CVF_MAX(j2 - 1, 0), CVF_MAX(k2 - 1, 0)); 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()); }