From 4c3c01a661b021ebe78e104cba223a176202bf58 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 22 Mar 2019 08:49:39 +0100 Subject: [PATCH] #4210 Fix crash when creating contour map --- .../RivContourMapProjectionPartMgr.cpp | 11 ++++-- .../RimContourMapProjection.cpp | 23 +++++++---- .../RimEclipseContourMapProjection.cpp | 18 ++++++--- .../RimGeoMechContourMapProjection.cpp | 12 +++--- .../RigCellGeometryTools.cpp | 38 +++++++++++++------ .../ReservoirDataModel/RigCellGeometryTools.h | 3 +- .../UnitTests/RigCellGeometryTools-Test.cpp | 19 ++++++---- 7 files changed, 82 insertions(+), 42 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.cpp b/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.cpp index 5b79e91adf..ac72d34dc0 100644 --- a/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.cpp @@ -13,6 +13,7 @@ #include "cafEffectGenerator.h" #include "cafFixedAtlasFont.h" +#include "cafCategoryMapper.h" #include "cvfCamera.h" #include "cvfDrawableText.h" @@ -365,13 +366,17 @@ std::vector> { CVF_ASSERT(camera && displayCoordTransform && labelBBoxes); + std::vector> labelDrawables; + labelBBoxes->clear(); + labelBBoxes->resize(m_contourLinePolygons.size()); + const cvf::ScalarMapper* mapper = m_contourMapProjection->legendConfig()->scalarMapper(); + if (dynamic_cast(mapper) != nullptr) + return labelDrawables; + std::vector tickValues; mapper->majorTickValues(&tickValues); - std::vector> labelDrawables; - labelBBoxes->clear(); - labelBBoxes->resize(m_contourLinePolygons.size()); const RimContourMapProjection::ContourPolygons* previousLevel = nullptr; for (int64_t i = (int64_t)m_contourLinePolygons.size() - 1; i > 0; --i) { diff --git a/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp b/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp index 9799efa95a..0f45b5907a 100644 --- a/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp +++ b/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp @@ -724,14 +724,12 @@ std::pair RimContourMapProjection::minmaxValuesAllTimeSteps() { clearTimeStepRange(); + m_minResultAllTimeSteps = std::min(m_minResultAllTimeSteps, minValue(m_aggregatedResults)); + m_maxResultAllTimeSteps = std::max(m_maxResultAllTimeSteps, maxValue(m_aggregatedResults)); + for (int i = 0; i < (int)baseView()->ownerCase()->timeStepStrings().size() - 1; ++i) { - if (i == m_currentResultTimestep) - { - m_minResultAllTimeSteps = std::min(m_minResultAllTimeSteps, minValue(m_aggregatedResults)); - m_maxResultAllTimeSteps = std::max(m_maxResultAllTimeSteps, maxValue(m_aggregatedResults)); - } - else + if (i != m_currentResultTimestep) { std::vector aggregatedResults = generateResults(i); m_minResultAllTimeSteps = std::min(m_minResultAllTimeSteps, minValue(aggregatedResults)); @@ -1078,8 +1076,6 @@ void RimContourMapProjection::generateContourPolygons() { std::vector contourPolygons; - const double simplifyEpsilon = m_smoothContourLines() ? 5.0e-2 * m_sampleSpacing : 1.0e-3 * m_sampleSpacing; - std::vector contourLevels; if (resultRangeIsValid() && legendConfig()->mappingMode() != RimRegularLegendConfig::CATEGORY_INTEGER) { @@ -1101,6 +1097,17 @@ void RimContourMapProjection::generateContourPolygons() contourLevels.front() *= 0.5; } + double simplifyEpsilon = m_smoothContourLines() ? 5.0e-2 * m_sampleSpacing : 1.0e-3 * m_sampleSpacing; + + if (nContourLevels >= 10) + { + simplifyEpsilon *= 2.0; + } + if (numberOfCells() > 100000) + { + simplifyEpsilon *= 2.0; + } + std::vector unorderedLineSegmentsPerLevel = caf::ContourLines::create(m_aggregatedVertexResults, xVertexPositions(), yVertexPositions(), contourLevels); diff --git a/ApplicationCode/ProjectDataModel/RimEclipseContourMapProjection.cpp b/ApplicationCode/ProjectDataModel/RimEclipseContourMapProjection.cpp index 1152972f8a..52dfee27be 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseContourMapProjection.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseContourMapProjection.cpp @@ -202,7 +202,11 @@ std::vector RimEclipseContourMapProjection::generateResults(int timeStep else { m_currentResultName = cellColors->resultVariable(); - gridResultValues = resultData->cellScalarResults(RigEclipseResultAddress( cellColors->resultType(), cellColors->resultVariable()), timeStep); + RigEclipseResultAddress resAddr(cellColors->resultType(), cellColors->resultVariable()); + if (resAddr.isValid() && resultData->hasResultEntry(resAddr)) + { + gridResultValues = resultData->cellScalarResults(resAddr, timeStep); + } } if (!gridResultValues.empty()) @@ -393,11 +397,13 @@ double RimEclipseContourMapProjection::calculateOverlapVolume(size_t globalCellI localGrid->cellCornerVertices(localCellIdx, hexCorners.data()); cvf::BoundingBox overlapBBox; - std::array overlapCorners = - RigCellGeometryTools::estimateHexOverlapWithBoundingBox(hexCorners, bbox, &overlapBBox); - - double overlapVolume = RigCellGeometryTools::calculateCellVolume(overlapCorners); - return overlapVolume; + std::array overlapCorners; + if (RigCellGeometryTools::estimateHexOverlapWithBoundingBox(hexCorners, bbox, &overlapCorners, &overlapBBox)) + { + double overlapVolume = RigCellGeometryTools::calculateCellVolume(overlapCorners); + return overlapVolume; + } + return 0.0; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechContourMapProjection.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechContourMapProjection.cpp index 0c61038e55..75f558b2b6 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechContourMapProjection.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechContourMapProjection.cpp @@ -427,11 +427,13 @@ double RimGeoMechContourMapProjection::calculateOverlapVolume(size_t m_femPartGrid->cellCornerVertices(globalCellIdx, hexCorners.data()); cvf::BoundingBox overlapBBox; - std::array overlapCorners = - RigCellGeometryTools::estimateHexOverlapWithBoundingBox(hexCorners, bbox, &overlapBBox); - - double overlapVolume = RigCellGeometryTools::calculateCellVolume(overlapCorners); - return overlapVolume; + std::array overlapCorners; + if (RigCellGeometryTools::estimateHexOverlapWithBoundingBox(hexCorners, bbox, &overlapCorners, &overlapBBox)) + { + double overlapVolume = RigCellGeometryTools::calculateCellVolume(overlapCorners); + return overlapVolume; + } + return 0.0; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigCellGeometryTools.cpp b/ApplicationCode/ReservoirDataModel/RigCellGeometryTools.cpp index d7d3d691f0..f8d72346f6 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellGeometryTools.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellGeometryTools.cpp @@ -85,16 +85,30 @@ double RigCellGeometryTools::calculateCellVolume(const std::array } //-------------------------------------------------------------------------------------------------- -/// +/// A reasonable approximation to the overlap volume //-------------------------------------------------------------------------------------------------- -std::array RigCellGeometryTools::estimateHexOverlapWithBoundingBox(const std::array& hexCorners, const cvf::BoundingBox& boundingBox, cvf::BoundingBox* overlapBoundingBox) +bool RigCellGeometryTools::estimateHexOverlapWithBoundingBox(const std::array& hexCorners, const cvf::BoundingBox& boundingBox, std::array* overlapElement, cvf::BoundingBox* overlapBoundingBox) { - CVF_ASSERT(overlapBoundingBox); + CVF_ASSERT(overlapElement && overlapBoundingBox); *overlapBoundingBox = cvf::BoundingBox(); + std::array overlapCorners = hexCorners; - // A reasonable approximation to the overlap volume - cvf::Plane topPlane; topPlane.setFromPoints(hexCorners[0], hexCorners[1], hexCorners[2]); - cvf::Plane bottomPlane; bottomPlane.setFromPoints(hexCorners[4], hexCorners[5], hexCorners[6]); + + std::vector uniqueTopPoints = { hexCorners[0], hexCorners[1], hexCorners[2], hexCorners[3] }; + uniqueTopPoints.erase(std::unique(uniqueTopPoints.begin(), uniqueTopPoints.end()), uniqueTopPoints.end()); + if (uniqueTopPoints.size() < 3) return false; + + cvf::Plane topPlane; + if (!topPlane.setFromPoints(uniqueTopPoints[0], uniqueTopPoints[1], uniqueTopPoints[2])) + return false; + + std::vector uniqueBottomPoints = {hexCorners[4], hexCorners[5], hexCorners[6], hexCorners[7]}; + uniqueBottomPoints.erase(std::unique(uniqueBottomPoints.begin(), uniqueBottomPoints.end()), uniqueBottomPoints.end()); + if (uniqueBottomPoints.size() < 3) return false; + + cvf::Plane bottomPlane; + if (!bottomPlane.setFromPoints(uniqueBottomPoints[0], uniqueBottomPoints[1], uniqueBottomPoints[2])) + return false; for (size_t i = 0; i < 4; ++i) { @@ -104,8 +118,8 @@ std::array RigCellGeometryTools::estimateHexOverlapWithBoundingBo corner.z() = cvf::Math::clamp(corner.z(), boundingBox.min().z(), boundingBox.max().z()); cvf::Vec3d maxZCorner = corner; maxZCorner.z() = boundingBox.max().z(); cvf::Vec3d minZCorner = corner; minZCorner.z() = boundingBox.min().z(); - topPlane.intersect(minZCorner, maxZCorner, &corner); - overlapBoundingBox->add(corner); + if (topPlane.intersect(minZCorner, maxZCorner, &corner)) + overlapBoundingBox->add(corner); } for (size_t i = 4; i < 8; ++i) { @@ -115,10 +129,12 @@ std::array RigCellGeometryTools::estimateHexOverlapWithBoundingBo corner.z() = cvf::Math::clamp(corner.z(), boundingBox.min().z(), boundingBox.max().z()); cvf::Vec3d maxZCorner = corner; maxZCorner.z() = boundingBox.max().z(); cvf::Vec3d minZCorner = corner; minZCorner.z() = boundingBox.min().z(); - bottomPlane.intersect(minZCorner, maxZCorner, &corner); - overlapBoundingBox->add(corner); + if (bottomPlane.intersect(minZCorner, maxZCorner, &corner)) + overlapBoundingBox->add(corner); } - return overlapCorners; + + *overlapElement = overlapCorners; + return true; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigCellGeometryTools.h b/ApplicationCode/ReservoirDataModel/RigCellGeometryTools.h index 49d2f40b8b..e76d114a05 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellGeometryTools.h +++ b/ApplicationCode/ReservoirDataModel/RigCellGeometryTools.h @@ -32,8 +32,9 @@ class RigCellGeometryTools { public: static double calculateCellVolume(const std::array& hexCorners); - static std::array estimateHexOverlapWithBoundingBox(const std::array& hexCorners, + static bool estimateHexOverlapWithBoundingBox(const std::array& hexCorners, const cvf::BoundingBox& boundingBox2dExtrusion, + std::array* overlapCorners, cvf::BoundingBox* overlapBoundingBox); static void createPolygonFromLineSegments(std::list>& intersectionLineSegments, diff --git a/ApplicationCode/UnitTests/RigCellGeometryTools-Test.cpp b/ApplicationCode/UnitTests/RigCellGeometryTools-Test.cpp index 3ec9fbdc24..0ea6a45d7b 100644 --- a/ApplicationCode/UnitTests/RigCellGeometryTools-Test.cpp +++ b/ApplicationCode/UnitTests/RigCellGeometryTools-Test.cpp @@ -46,7 +46,8 @@ TEST(RigCellGeometryTools, calculateCellVolumeTest) // The overlap with the original bounding box should just yield the original bounding box cvf::BoundingBox overlapBoundingBox; - std::array overlapVertices = RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, bbox, &overlapBoundingBox); + std::array overlapVertices; + RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, bbox, &overlapVertices, &overlapBoundingBox); EXPECT_DOUBLE_EQ(bboxVolume, RigCellGeometryTools::calculateCellVolume(overlapVertices)); @@ -64,7 +65,8 @@ TEST(RigCellGeometryTools, calculateCellVolumeTest) corner.x() += 0.5 * bbox.extent().x(); tetrahedronBBox.add(corner); } - overlapVertices = RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, tetrahedronBBox, &overlapBoundingBox); + overlapVertices; + RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, tetrahedronBBox, &overlapVertices, &overlapBoundingBox); EXPECT_DOUBLE_EQ(bboxVolume * 0.5 + extraVolume, RigCellGeometryTools::calculateCellVolume(overlapVertices)); @@ -76,13 +78,13 @@ TEST(RigCellGeometryTools, calculateCellVolumeTest) corner.x() += 0.5 * bbox.extent().x(); tetrahedronBBox.add(corner); } - overlapVertices = RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, tetrahedronBBox, &overlapBoundingBox); + RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, tetrahedronBBox, &overlapVertices, &overlapBoundingBox); EXPECT_DOUBLE_EQ(extraVolume, RigCellGeometryTools::calculateCellVolume(overlapVertices)); // Expand original bounding box to be much larger than the hex bbox.expand(2000); - overlapVertices = RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, bbox, &overlapBoundingBox); + RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, bbox, &overlapVertices, &overlapBoundingBox); EXPECT_DOUBLE_EQ(bboxVolume + extraVolume, RigCellGeometryTools::calculateCellVolume(overlapVertices)); } @@ -105,20 +107,21 @@ TEST(RigCellGeometryTools, calculateCellVolumeTest2) double expectedOverlap = 50 * 50 * 25 + 0.5 * 50 * 50 * 50; cvf::BoundingBox overlapBoundingBox; - std::array overlapVertices = RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, innerBBox, &overlapBoundingBox); + std::array overlapVertices; + RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, innerBBox, &overlapVertices, &overlapBoundingBox); EXPECT_DOUBLE_EQ(expectedOverlap, RigCellGeometryTools::calculateCellVolume(overlapVertices)); cvf::BoundingBox smallerInnerBBox(cvf::Vec3d(25.0, 25.0, -10.0), cvf::Vec3d(75.0, 75.0, 25.0)); - overlapVertices = RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, smallerInnerBBox, &overlapBoundingBox); + RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, smallerInnerBBox, &overlapVertices, &overlapBoundingBox); EXPECT_DOUBLE_EQ(50 * 50 * 25, RigCellGeometryTools::calculateCellVolume(overlapVertices)); cvf::BoundingBox smallerBBox(cvf::Vec3d(50.0, 50.0, 0.0), cvf::Vec3d(100.0, 100.0, 100.0)); - overlapVertices = RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, smallerBBox, &overlapBoundingBox); + RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, smallerBBox, &overlapVertices, &overlapBoundingBox); double tipVolume = 50 * 50 * 50 * 0.5; EXPECT_DOUBLE_EQ(tipVolume, RigCellGeometryTools::calculateCellVolume(overlapVertices)); cvf::BoundingBox smallerBBox2(cvf::Vec3d(0.0, 0.0, 0.0), cvf::Vec3d(50.0, 50.0, 100.0)); - overlapVertices = RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, smallerBBox2, &overlapBoundingBox); + RigCellGeometryTools::estimateHexOverlapWithBoundingBox(cornerVertices, smallerBBox2, &overlapVertices, &overlapBoundingBox); double expectedVolume = (totalCellVolume - 2*tipVolume) * 0.5; EXPECT_DOUBLE_EQ(expectedVolume, RigCellGeometryTools::calculateCellVolume(overlapVertices)); }