diff --git a/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.cpp b/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.cpp index 151ea37150..2ecf80b497 100644 --- a/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.cpp @@ -1,5 +1,7 @@ #include "RivContourMapProjectionPartMgr.h" +#include "RiaColorTools.h" +#include "RiaFontCache.h" #include "RiaWeightedMeanCalculator.h" #include "RivMeshLinesSourceInfo.h" #include "RivScalarMapperUtils.h" @@ -9,11 +11,13 @@ #include "cafEffectGenerator.h" +#include "cvfDrawableText.h" #include "cvfGeometryBuilderFaceList.h" #include "cvfGeometryUtils.h" #include "cvfMeshEdgeExtractor.h" #include "cvfPart.h" #include "cvfPrimitiveSetIndexedUInt.h" +#include "cvfScalarMapper.h" #include @@ -48,8 +52,8 @@ void RivContourMapProjectionPartMgr::appendProjectionToModel(cvf::ModelBasicList if (m_contourMapProjection->showContourLines()) { - std::vector> contourDrawables = createContourPolygons(displayCoordTransform); - for (cvf::ref contourDrawable : contourDrawables) + std::vector> contourDrawables = createContourPolygons(displayCoordTransform); + for (cvf::ref contourDrawable : contourDrawables) { if (contourDrawable.notNull() && contourDrawable->boundingBox().isValid()) { @@ -148,6 +152,27 @@ cvf::ref RivContourMapProjectionPartMgr::createTextureCoords() return textureCoords; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivContourMapProjectionPartMgr::createTextLabel(const cvf::Color3f& backgroundColor) +{ + auto font = RiaFontCache::getFont(RiaFontCache::FONT_SIZE_8); + + cvf::ref labelDrawable = new cvf::DrawableText(); + labelDrawable->setFont(font.p()); + labelDrawable->setCheckPosVisible(true); + labelDrawable->setUseDepthBuffer(false); + labelDrawable->setDrawBorder(true); + labelDrawable->setDrawBackground(true); + labelDrawable->setBackgroundColor(backgroundColor); + labelDrawable->setVerticalAlignment(cvf::TextDrawer::BASELINE); + cvf::Color3f textColor = RiaColorTools::constrastColor(backgroundColor); + labelDrawable->setTextColor(textColor); + + return labelDrawable; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -181,23 +206,55 @@ cvf::ref RivContourMapProjectionPartMgr::createProjectionMapDr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector> RivContourMapProjectionPartMgr::createContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform) const +std::vector> RivContourMapProjectionPartMgr::createContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform) const { m_contourMapProjection->generateContourPolygons(); const std::vector& contourPolygons = m_contourMapProjection->contourPolygons(); - std::vector> contourDrawables; - for (size_t i = 0; i < contourPolygons.size(); ++i) + const cvf::ScalarMapper* mapper = m_contourMapProjection->legendConfig()->scalarMapper(); + std::vector tickValues; + mapper->majorTickValues(&tickValues); + + std::vector> contourDrawables; + std::vector> labelDrawables; + for (int64_t i = (int64_t) contourPolygons.size() - 1; i > 0; --i) { + cvf::Color3f backgroundColor(mapper->mapToColor(tickValues[i])); + for (size_t j = 0; j < contourPolygons[i].size(); ++j) { - if (contourPolygons[i][j].empty()) continue; + if (contourPolygons[i][j].vertices.empty()) continue; - cvf::ref vertexArray = new cvf::Vec3fArray(contourPolygons[i][j].size()); - for (size_t v = 0; v < contourPolygons[i][j].size(); ++v) + size_t nVertices = contourPolygons[i][j].vertices.size(); + size_t nLabels = m_contourMapProjection->showContourLabels() ? std::max((size_t)1, nVertices / 150u) : 0u; + for (size_t l = 0; l < nLabels; ++l) { - cvf::Vec3f displayVertex(displayCoordTransform->transformToDisplayCoord(contourPolygons[i][j][v])); - (*vertexArray)[v] = displayVertex; + cvf::ref label = createTextLabel(backgroundColor); + cvf::Vec3f labelVertex(displayCoordTransform->transformToDisplayCoord(contourPolygons[i][j].vertices[(nVertices * l) / nLabels])); + labelVertex.z() += 3.0f; + label->addText(contourPolygons[i][j].label, labelVertex); + bool overlaps = false; + cvf::BoundingBox bbox = label->boundingBox(); + for (cvf::ref existingLabel : labelDrawables) + { + if (existingLabel->boundingBox().intersects(bbox)) + { + overlaps = true; + break; + } + } + if (!overlaps) + { + labelDrawables.push_back(label); + } + } + cvf::ref vertexArray = new cvf::Vec3fArray(nVertices); + for (size_t v = 0; v < nVertices; v += 2) + { + cvf::Vec3d displayVertex1 = displayCoordTransform->transformToDisplayCoord(contourPolygons[i][j].vertices[v]); + cvf::Vec3d displayVertex2 = displayCoordTransform->transformToDisplayCoord(contourPolygons[i][j].vertices[v + 1]); + (*vertexArray)[v] = cvf::Vec3f(displayVertex1); + (*vertexArray)[v + 1] = cvf::Vec3f(displayVertex2); } std::vector indices; @@ -218,6 +275,11 @@ std::vector> RivContourMapProjectionPartMgr::createCo contourDrawables.push_back(geo); } } + for (cvf::ref labelDrawable : labelDrawables) + { + contourDrawables.push_back(labelDrawable); + } + return contourDrawables; } diff --git a/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.h b/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.h index af580e391f..2fe43cd5be 100644 --- a/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivContourMapProjectionPartMgr.h @@ -23,6 +23,7 @@ #include "cvfBase.h" #include "cvfDrawableGeo.h" +#include "cvfDrawableText.h" #include "cvfModelBasicList.h" #include "cvfObject.h" @@ -42,11 +43,12 @@ public: cvf::ref createTextureCoords() const; private: + static cvf::ref createTextLabel(const cvf::Color3f& backgroundColor); cvf::ref createProjectionMapDrawable(const caf::DisplayCoordTransform* displayCoordTransform) const; - std::vector> createContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform) const; + std::vector> createContourPolygons(const caf::DisplayCoordTransform* displayCoordTransform) const; cvf::ref createPickPointVisDrawable(const caf::DisplayCoordTransform* displayCoordTransform) const; private: - caf::PdmPointer m_contourMapProjection; - caf::PdmPointer m_parentContourMap; + caf::PdmPointer m_contourMapProjection; + caf::PdmPointer m_parentContourMap; }; diff --git a/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp b/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp index c8906f1c75..b96d6dd8b8 100644 --- a/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp +++ b/ApplicationCode/ProjectDataModel/RimContourMapProjection.cpp @@ -78,6 +78,7 @@ RimContourMapProjection::RimContourMapProjection() CAF_PDM_InitFieldNoDefault(&m_resultAggregation, "ResultAggregation", "Result Aggregation", "", "", ""); CAF_PDM_InitField(&m_showContourLines, "ContourLines", true, "Show Contour Lines", "", "", ""); + CAF_PDM_InitField(&m_showContourLabels, "ContourLabels", false, "Show Contour Labels", "", "", ""); CAF_PDM_InitField(&m_weightByParameter, "WeightByParameter", false, "Weight by Result Parameter", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_weightingResult, "WeightingResult", "", "", "", ""); @@ -144,26 +145,29 @@ void RimContourMapProjection::generateContourPolygons() int nContourLevels = static_cast(contourLevels.size()); if (nContourLevels > 2) { + std::vector fudgedContourLevels = contourLevels; if (legendConfig()->mappingMode() == RimRegularLegendConfig::LINEAR_CONTINUOUS || legendConfig()->mappingMode() == RimRegularLegendConfig::LINEAR_DISCRETE) { // Slight fudge to avoid very jagged contour lines at the very edge // Shift the contour levels inwards. - contourLevels[0] += (contourLevels[1] - contourLevels[0]) * 0.1; - contourLevels[nContourLevels - 1] -= (contourLevels[nContourLevels - 1] - contourLevels[nContourLevels - 2]) * 0.1; + fudgedContourLevels[0] += (contourLevels[1] - contourLevels[0]) * 0.1; + fudgedContourLevels[nContourLevels - 1] -= (contourLevels[nContourLevels - 1] - contourLevels[nContourLevels - 2]) * 0.1; } std::vector closedContourLines = - caf::ContourLines::create(m_aggregatedVertexResults, xVertexPositions(), yVertexPositions(), contourLevels); + caf::ContourLines::create(m_aggregatedVertexResults, xVertexPositions(), yVertexPositions(), fudgedContourLevels); contourPolygons.resize(closedContourLines.size()); for (size_t i = 0; i < closedContourLines.size(); ++i) { for (size_t j = 0; j < closedContourLines[i].size(); ++j) { - ContourPolygon contourPolygon; contourPolygon.reserve(closedContourLines[i][j].size()); + ContourPolygon contourPolygon; + contourPolygon.label = cvf::String(contourLevels[i]); + contourPolygon.vertices.reserve(closedContourLines[i][j].size()); for (size_t k = 0; k < closedContourLines[i][j].size(); ++k) { cvf::Vec3d contourPoint3d = cvf::Vec3d(closedContourLines[i][j][k], m_fullBoundingBox.min().z()); - contourPolygon.push_back(contourPoint3d); + contourPolygon.vertices.push_back(contourPoint3d); } contourPolygons[i].push_back(contourPolygon); } @@ -318,6 +322,14 @@ bool RimContourMapProjection::showContourLines() const return m_showContourLines(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimContourMapProjection::showContourLabels() const +{ + return m_showContourLines() && m_showContourLabels(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -660,6 +672,8 @@ void RimContourMapProjection::defineUiOrdering(QString uiConfigName, caf::PdmUiO caf::PdmUiGroup* mainGroup = uiOrdering.addNewGroup("Projection Settings"); mainGroup->add(&m_relativeSampleSpacing); mainGroup->add(&m_showContourLines); + mainGroup->add(&m_showContourLabels); + m_showContourLabels.uiCapability()->setUiReadOnly(!m_showContourLines()); mainGroup->add(&m_resultAggregation); caf::PdmUiGroup* weightingGroup = uiOrdering.addNewGroup("Mean Weighting Options"); diff --git a/ApplicationCode/ProjectDataModel/RimContourMapProjection.h b/ApplicationCode/ProjectDataModel/RimContourMapProjection.h index 7e76c51c8d..2289c4f6a9 100644 --- a/ApplicationCode/ProjectDataModel/RimContourMapProjection.h +++ b/ApplicationCode/ProjectDataModel/RimContourMapProjection.h @@ -29,6 +29,7 @@ #include "cvfBoundingBox.h" #include "cvfGeometryBuilderFaceList.h" +#include "cvfString.h" #include "cvfVector2.h" class RigMainGrid; @@ -45,6 +46,12 @@ class RimContourMapProjection : public RimCheckableNamedObject { CAF_PDM_HEADER_INIT; public: + struct ContourPolygon + { + std::vector vertices; + cvf::String label; + }; + enum ResultAggregationEnum { RESULTS_TOP_VALUE, @@ -60,7 +67,6 @@ public: RESULTS_HC_COLUMN }; typedef caf::AppEnum ResultAggregation; - typedef std::vector ContourPolygon; typedef std::vector ContourPolygons; RimContourMapProjection(); @@ -77,6 +83,7 @@ public: double sampleSpacing() const; double sampleSpacingFactor() const; bool showContourLines() const; + bool showContourLabels() const; QString resultAggregationText() const; QString resultDescriptionText() const; @@ -162,6 +169,7 @@ protected: caf::PdmField m_relativeSampleSpacing; caf::PdmField m_resultAggregation; caf::PdmField m_showContourLines; + caf::PdmField m_showContourLabels; caf::PdmField m_weightByParameter; caf::PdmChildField m_weightingResult;