diff --git a/ApplicationLibCode/ModelVisualization/Riv3dWellLogDrawSurfaceGenerator.cpp b/ApplicationLibCode/ModelVisualization/Riv3dWellLogDrawSurfaceGenerator.cpp index 3a32f84a825..9605d3675b6 100644 --- a/ApplicationLibCode/ModelVisualization/Riv3dWellLogDrawSurfaceGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Riv3dWellLogDrawSurfaceGenerator.cpp @@ -86,14 +86,16 @@ bool Riv3dWellLogDrawSurfaceGenerator::createDrawSurface( const caf::DisplayCoor size_t indexToFirstVisibleSegment = 0u; if ( wellPathCollection->wellPathClip ) { - double clipZDistance = wellPathCollection->wellPathClipZDistance; - cvf::Vec3d clipLocation = wellPathClipBoundingBox.max() + clipZDistance * cvf::Vec3d( 0, 0, 1 ); - clipLocation = displayCoordTransform->transformToDisplayCoord( clipLocation ); - double horizontalLengthAlongWellToClipPoint; + double clipZDistance = wellPathCollection->wellPathClipZDistance; + cvf::Vec3d clipLocation = wellPathClipBoundingBox.max() + clipZDistance * cvf::Vec3d( 0, 0, 1 ); + clipLocation = displayCoordTransform->transformToDisplayCoord( clipLocation ); + double horizontalLengthAlongWellToClipPoint = 0.0; + double measuredDepthAtFirstClipPoint = 0.0; wellPathDisplayCoords = RigWellPath::clipPolylineStartAboveZ( wellPathDisplayCoords, clipLocation.z(), &horizontalLengthAlongWellToClipPoint, + &measuredDepthAtFirstClipPoint, &indexToFirstVisibleSegment ); } diff --git a/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.cpp b/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.cpp index c15ed4d5cf0..65a2936eaca 100644 --- a/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.cpp +++ b/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.cpp @@ -25,8 +25,21 @@ RivAnnotationSourceInfo::RivAnnotationSourceInfo( const std::string m_text, cons : m_text( m_text ) , m_showColor( false ) , m_color( cvf::Color3f( cvf::Color3f::BLACK ) ) - , m_anchorPointsDisplayCoord( displayCoords ) , m_labelPositionHint( RivAnnotationTools::LabelPositionStrategy::RIGHT ) + , m_anchorPointsDisplayCoord( displayCoords ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivAnnotationSourceInfo::RivAnnotationSourceInfo( const std::vector& texts, const std::vector& displayCoords ) + : m_text( m_text ) + , m_showColor( false ) + , m_color( cvf::Color3f( cvf::Color3f::BLACK ) ) + , m_labelPositionHint( RivAnnotationTools::LabelPositionStrategy::COUNT_HINT ) + , m_anchorPointsDisplayCoord( displayCoords ) + , m_texts( texts ) { } @@ -54,6 +67,14 @@ std::string RivAnnotationSourceInfo::text() const return m_text; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RivAnnotationSourceInfo::texts() const +{ + return m_texts; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.h b/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.h index d8c3cf82fe0..8eb843c74a0 100644 --- a/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.h +++ b/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.h @@ -31,12 +31,14 @@ class RivAnnotationSourceInfo : public cvf::Object { public: RivAnnotationSourceInfo( const std::string m_text, const std::vector& displayCoords ); + RivAnnotationSourceInfo( const std::vector& texts, const std::vector& displayCoords ); RivAnnotationTools::LabelPositionStrategy labelPositionStrategyHint() const; void setLabelPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy strategy ); - std::string text() const; - std::vector anchorPointsDisplayCoords() const; + std::string text() const; + std::vector texts() const; + std::vector anchorPointsDisplayCoords() const; bool showColor() const; void setShowColor( bool showColor ); @@ -50,4 +52,5 @@ class RivAnnotationSourceInfo : public cvf::Object cvf::Color3f m_color; RivAnnotationTools::LabelPositionStrategy m_labelPositionHint; std::vector m_anchorPointsDisplayCoord; + std::vector m_texts; }; diff --git a/ApplicationLibCode/ModelVisualization/RivAnnotationTools.cpp b/ApplicationLibCode/ModelVisualization/RivAnnotationTools.cpp index ff29be5fd9b..8280c4fe173 100644 --- a/ApplicationLibCode/ModelVisualization/RivAnnotationTools.cpp +++ b/ApplicationLibCode/ModelVisualization/RivAnnotationTools.cpp @@ -63,7 +63,7 @@ void caf::AppEnum::setUp() //-------------------------------------------------------------------------------------------------- RivAnnotationTools::RivAnnotationTools() : m_strategy( RivAnnotationTools::LabelPositionStrategy::UNDEFINED ) - , m_labelCountHint( 0 ) + , m_labelCountHint( 5 ) { } @@ -190,6 +190,55 @@ auto createLabel = []( const cvf::Camera* camera, return info; }; +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +auto createLabelsFromAnnotationObjectTexts = []( const cvf::Camera* camera, + const RivAnnotationSourceInfo* annotationObject, + const double viewportWidth, + const double viewportHeight, + const double anchorLineScalingFactor ) -> std::vector +{ + if ( !annotationObject || annotationObject->texts().empty() ) return {}; + + std::vector labelInfo; + + std::vector labelCoords; + std::vector labelTexts; + + const auto candidateCoords = annotationObject->anchorPointsDisplayCoords(); + const auto candidateLabels = annotationObject->texts(); + + if ( candidateCoords.size() == candidateLabels.size() ) + { + for ( size_t i = 0; i < annotationObject->anchorPointsDisplayCoords().size(); i++ ) + { + const auto& displayCoord = candidateCoords[i]; + + cvf::Vec3d screenCoord; + camera->project( displayCoord, &screenCoord ); + + if ( screenCoord.x() > 0 && screenCoord.x() < viewportWidth && screenCoord.y() > 0 && screenCoord.y() < viewportHeight ) + { + const auto& text = candidateLabels[i]; + labelCoords.push_back( displayCoord ); + labelTexts.push_back( text ); + } + } + + for ( size_t i = 0; i < labelCoords.size(); i++ ) + { + const cvf::Vec3d lineAnchorPosition = labelCoords[i]; + const cvf::Vec3d directionPointToCam = ( camera->position() - lineAnchorPosition ).getNormalized(); + const cvf::Vec3d labelPosition = lineAnchorPosition + directionPointToCam * anchorLineScalingFactor; + + labelInfo.push_back( { labelTexts[i], lineAnchorPosition, labelPosition } ); + } + } + + return labelInfo; +}; + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -208,67 +257,77 @@ void RivAnnotationTools::addAnnotationLabels( const cvf::Collection& { std::vector labelInfo; - auto strategy = annotationObject->labelPositionStrategyHint(); - if ( m_strategy != LabelPositionStrategy::UNDEFINED ) - { - strategy = m_strategy; - } - const auto viewportWidth = camera->viewport()->width(); const auto viewportHeight = camera->viewport()->height(); - if ( strategy == LabelPositionStrategy::RIGHT || strategy == LabelPositionStrategy::LEFT_AND_RIGHT ) + if ( !annotationObject->texts().empty() ) { - // Close to the right edge of the visible screen area - const auto normalizedXPosition = 0.9; - - auto labelCandidate = createLabel( camera, annotationObject, viewportWidth, normalizedXPosition, anchorLineScalingFactor ); - if ( labelCandidate.has_value() ) labelInfo.push_back( labelCandidate.value() ); + labelInfo = + createLabelsFromAnnotationObjectTexts( camera, annotationObject, viewportWidth, viewportHeight, anchorLineScalingFactor ); } - - if ( strategy == LabelPositionStrategy::LEFT || strategy == LabelPositionStrategy::LEFT_AND_RIGHT ) + else { - // Close to the left edge of the visible screen area - const auto normalizedXPosition = 0.1; - - auto labelCandidate = createLabel( camera, annotationObject, viewportWidth, normalizedXPosition, anchorLineScalingFactor ); - if ( labelCandidate.has_value() ) labelInfo.push_back( labelCandidate.value() ); - } + auto strategy = annotationObject->labelPositionStrategyHint(); + if ( m_strategy != LabelPositionStrategy::UNDEFINED ) + { + // Can override annotation object strategy defined in Rim3dView::updateScreenSpaceModel() + strategy = m_strategy; + } - if ( strategy == LabelPositionStrategy::COUNT_HINT || strategy == LabelPositionStrategy::ALL ) - { - std::vector visibleCoords; - for ( const auto& v : annotationObject->anchorPointsDisplayCoords() ) + if ( strategy == LabelPositionStrategy::RIGHT || strategy == LabelPositionStrategy::LEFT_AND_RIGHT ) { - cvf::Vec3d screenCoord; - camera->project( v, &screenCoord ); + // Close to the right edge of the visible screen area + const auto normalizedXPosition = 0.9; - if ( screenCoord.x() > 0 && screenCoord.x() < viewportWidth && screenCoord.y() > 0 && screenCoord.y() < viewportHeight ) - visibleCoords.push_back( v ); + auto labelCandidate = createLabel( camera, annotationObject, viewportWidth, normalizedXPosition, anchorLineScalingFactor ); + if ( labelCandidate.has_value() ) labelInfo.push_back( labelCandidate.value() ); } - size_t stride = 1; - if ( strategy == LabelPositionStrategy::COUNT_HINT ) + if ( strategy == LabelPositionStrategy::LEFT || strategy == LabelPositionStrategy::LEFT_AND_RIGHT ) { - stride = std::max( size_t( 1 ), visibleCoords.size() / std::max( 1, m_labelCountHint - 1 ) ); + // Close to the left edge of the visible screen area + const auto normalizedXPosition = 0.1; + + auto labelCandidate = createLabel( camera, annotationObject, viewportWidth, normalizedXPosition, anchorLineScalingFactor ); + if ( labelCandidate.has_value() ) labelInfo.push_back( labelCandidate.value() ); } - for ( size_t i = 0; i < visibleCoords.size(); i += stride ) + if ( strategy == LabelPositionStrategy::COUNT_HINT || strategy == LabelPositionStrategy::ALL ) { - size_t adjustedIndex = std::min( i, visibleCoords.size() - 1 ); + std::vector visibleCoords; + for ( const auto& v : annotationObject->anchorPointsDisplayCoords() ) + { + cvf::Vec3d screenCoord; + camera->project( v, &screenCoord ); + + if ( screenCoord.x() > 0 && screenCoord.x() < viewportWidth && screenCoord.y() > 0 && screenCoord.y() < viewportHeight ) + visibleCoords.push_back( v ); + } - const cvf::Vec3d lineAnchorPosition = visibleCoords[adjustedIndex]; - const cvf::Vec3d directionPointToCam = ( camera->position() - lineAnchorPosition ).getNormalized(); - const cvf::Vec3d labelPosition = lineAnchorPosition + directionPointToCam * anchorLineScalingFactor; + size_t stride = 1; + if ( strategy == LabelPositionStrategy::COUNT_HINT ) + { + stride = std::max( size_t( 1 ), visibleCoords.size() / std::max( 1, m_labelCountHint - 1 ) ); + } - labelInfo.push_back( { annotationObject->text(), lineAnchorPosition, labelPosition } ); + for ( size_t i = 0; i < visibleCoords.size(); i += stride ) + { + size_t adjustedIndex = std::min( i, visibleCoords.size() - 1 ); + + const cvf::Vec3d lineAnchorPosition = visibleCoords[adjustedIndex]; + const cvf::Vec3d directionPointToCam = ( camera->position() - lineAnchorPosition ).getNormalized(); + const cvf::Vec3d labelPosition = lineAnchorPosition + directionPointToCam * anchorLineScalingFactor; + + labelInfo.push_back( { annotationObject->text(), lineAnchorPosition, labelPosition } ); + } } } for ( const auto& [labelText, lineAnchorPosition, labelPosition] : labelInfo ) { - // Line part { + // Line part + std::vector points = { lineAnchorPosition, labelPosition }; auto anchorLineColor = cvf::Color3f::BLACK; @@ -279,8 +338,9 @@ void RivAnnotationTools::addAnnotationLabels( const cvf::Collection& } } - // Text part { + // Text part + auto backgroundColor = annotationObject->showColor() ? annotationObject->color() : cvf::Color3f::LIGHT_GRAY; auto textColor = RiaColorTools::contrastColor( backgroundColor ); auto fontSize = 10; diff --git a/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.cpp index 63d80713108..9047b896c17 100644 --- a/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -55,6 +55,7 @@ #include "RimWellPathValve.h" #include "Riv3dWellLogPlanePartMgr.h" +#include "RivAnnotationSourceInfo.h" #include "RivBoxGeometryGenerator.h" #include "RivDrawableSpheres.h" #include "RivFishbonesSubsPartMgr.h" @@ -620,6 +621,7 @@ void RivWellPathPartMgr::buildWellPathParts( const caf::DisplayCoordTransform* d m_pipeGeomGenerator->setCrossSectionVertexCount( wellPathCollection->wellPathCrossSectionVertexCount() ); double horizontalLengthAlongWellToClipPoint = 0.0; + double measuredDepthAtFirstClipPoint = 0.0; size_t idxToFirstVisibleSegment = 0; if ( wellPathCollection->wellPathClip ) { @@ -627,6 +629,7 @@ void RivWellPathPartMgr::buildWellPathParts( const caf::DisplayCoordTransform* d clippedWellPathCenterLine = RigWellPath::clipPolylineStartAboveZ( wellpathCenterLine, maxZClipHeight, &horizontalLengthAlongWellToClipPoint, + &measuredDepthAtFirstClipPoint, &idxToFirstVisibleSegment ); } else @@ -694,6 +697,31 @@ void RivWellPathPartMgr::buildWellPathParts( const caf::DisplayCoordTransform* d cvf::ref eff = gen.generateCachedEffect(); m_centerLinePart->setEffect( eff.p() ); + + if ( m_rimWellPath->measuredDepthLabelInterval().has_value() && clippedWellPathCenterLine.size() > 2 ) + { + const double distanceBetweenLabels = m_rimWellPath->measuredDepthLabelInterval().value(); + + // Create a round number as start for measured depth label + const double startMeasuredDepth = ( int( measuredDepthAtFirstClipPoint / distanceBetweenLabels ) + 1 ) * distanceBetweenLabels; + + std::vector labelTexts; + std::vector labelDisplayCoords; + + double measuredDepth = startMeasuredDepth; + while ( measuredDepth < wellPathGeometry->measuredDepths().back() ) + { + labelTexts.push_back( std::to_string( static_cast( measuredDepth ) ) ); + auto domainCoord = wellPathGeometry->interpolatedPointAlongWellPath( measuredDepth ); + + auto displayCoord = displayCoordTransform->transformToDisplayCoord( domainCoord ); + labelDisplayCoords.push_back( displayCoord ); + + measuredDepth += distanceBetweenLabels; + } + + m_centerLinePart->setSourceInfo( new RivAnnotationSourceInfo( labelTexts, labelDisplayCoords ) ); + } } // Generate label with well-path name at a position that is slightly offset towards the end of the well path diff --git a/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp b/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp index e1673d4739e..e3f104621dd 100644 --- a/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp @@ -264,13 +264,16 @@ void RivSeismicSectionPartMgr::appendSurfaceIntersectionLines( cvf::ModelBasicLi } } - // Add annotation info to be used to display label in Rim3dView::onViewNavigationChanged() - // Set the source info once, as this data is only used for display of labels - auto annoObj = new RivAnnotationSourceInfo( surface->fullName().toStdString(), completePolyLine ); - annoObj->setLabelPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy::RIGHT ); - annoObj->setShowColor( true ); - annoObj->setColor( surface->color() ); - - firstPart->setSourceInfo( annoObj ); + if ( firstPart ) + { + // Add annotation info to be used to display label in Rim3dView::onViewNavigationChanged() + // Set the source info on one part only, as this data is only used for display of labels + auto annoObj = new RivAnnotationSourceInfo( surface->fullName().toStdString(), completePolyLine ); + annoObj->setLabelPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy::RIGHT ); + annoObj->setShowColor( true ); + annoObj->setColor( surface->color() ); + + firstPart->setSourceInfo( annoObj ); + } } } diff --git a/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.cpp b/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.cpp index c3983e2d587..26fa03be3cd 100644 --- a/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.cpp @@ -761,9 +761,11 @@ std::vector> RimExtrudedCurveIntersection::polyLines( cv if ( ownerCase && ownerCase->activeCellsBoundingBox().isValid() ) { size_t dummy; + double dummyDouble; lines[0] = RigWellPath::clipPolylineStartAboveZ( lines[0], ownerCase->activeCellsBoundingBox().max().z(), &horizontalProjectedLengthAlongWellPathToClipPoint, + &dummyDouble, &dummy ); } } diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.cpp b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.cpp index 0edd1e4b060..47db2984e57 100644 --- a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.cpp @@ -114,6 +114,10 @@ RimWellPath::RimWellPath() CAF_PDM_InitField( &m_branchIndex, "SimBranchIndex", 0, "Branch" ); CAF_PDM_InitField( &m_showWellPathLabel, "ShowWellPathLabel", true, "Show Well Path Label" ); + CAF_PDM_InitField( &m_measuredDepthLabelInterval, + "MeasuredDepthLabelInterval", + std::make_pair( false, 50.0 ), + "Enable Labels at Measured Depth Intervals" ); CAF_PDM_InitField( &m_showWellPath, "ShowWellPath", true, "Show Well Path" ); m_showWellPath.uiCapability()->setUiHidden( true ); @@ -647,6 +651,16 @@ void RimWellPath::setShowWellPath( bool showWellPath ) m_showWellPath = showWellPath; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::optional RimWellPath::measuredDepthLabelInterval() const +{ + if ( m_measuredDepthLabelInterval().first ) return m_measuredDepthLabelInterval().second; + + return std::nullopt; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -699,6 +713,7 @@ void RimWellPath::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& ui appGroup->add( &m_showWellPathLabel ); appGroup->add( &m_wellPathColor ); appGroup->add( &m_wellPathRadiusScaleFactor ); + appGroup->add( &m_measuredDepthLabelInterval ); caf::PdmUiGroup* simWellGroup = uiOrdering.addNewGroup( "Simulation Well" ); simWellGroup->add( &m_simWellName ); diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.h b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.h index 44483db095e..60d47638dc4 100644 --- a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.h +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPath.h @@ -141,6 +141,8 @@ class RimWellPath : public caf::PdmObject, public RimWellPathComponentInterface bool showWellPath() const; void setShowWellPath( bool showWellPath ); + std::optional measuredDepthLabelInterval() const; + cvf::Color3f wellPathColor() const; void setWellPathColor( const cvf::Color3f& color ); @@ -199,8 +201,9 @@ class RimWellPath : public caf::PdmObject, public RimWellPathComponentInterface caf::PdmField m_wellPathFormationFilePath; caf::PdmField m_formationKeyInFile; - caf::PdmField m_showWellPath; - caf::PdmField m_showWellPathLabel; + caf::PdmField m_showWellPath; + caf::PdmField m_showWellPathLabel; + caf::PdmField> m_measuredDepthLabelInterval; caf::PdmField m_wellPathRadiusScaleFactor; caf::PdmField m_wellPathColor; diff --git a/ApplicationLibCode/ReservoirDataModel/RigWellPath.cpp b/ApplicationLibCode/ReservoirDataModel/RigWellPath.cpp index 5e75e0f55f7..62adcd06490 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigWellPath.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigWellPath.cpp @@ -586,6 +586,7 @@ bool RigWellPath::isAnyPointInsideBoundingBox( const std::vector& po std::vector RigWellPath::clipPolylineStartAboveZ( const std::vector& polyLine, double maxZ, double* horizontalLengthAlongWellToClipPoint, + double* measuredDepthAtFirstClipPoint, size_t* indexToFirstVisibleSegment ) { CVF_ASSERT( horizontalLengthAlongWellToClipPoint ); @@ -605,7 +606,12 @@ std::vector RigWellPath::clipPolylineStartAboveZ( const std::vector< if ( vxIdx > 0 ) { cvf::Vec3d segment = polyLine[vxIdx] - polyLine[vxIdx - 1]; - segment[2] = 0.0; + if ( measuredDepthAtFirstClipPoint ) + { + *measuredDepthAtFirstClipPoint += segment.length(); + } + + segment[2] = 0.0; *horizontalLengthAlongWellToClipPoint += segment.length(); } } diff --git a/ApplicationLibCode/ReservoirDataModel/RigWellPath.h b/ApplicationLibCode/ReservoirDataModel/RigWellPath.h index eeb2f2d1c67..16cbb0b4831 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigWellPath.h +++ b/ApplicationLibCode/ReservoirDataModel/RigWellPath.h @@ -88,6 +88,7 @@ class RigWellPath : public cvf::Object, public caf::SignalEmitter static std::vector clipPolylineStartAboveZ( const std::vector& polyLine, double maxZ, double* horizontalLengthAlongWellToClipPoint, + double* measuredDepthAtFirstClipPoint, size_t* indexToFirstVisibleSegment ); private: