From e06cb1c39e71b990aa8c521f36ce8db4352a165d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Sep 2023 19:18:49 +0200 Subject: [PATCH] Refactoring --- .../RivAnnotationSourceInfo.cpp | 4 +- .../RivAnnotationSourceInfo.h | 4 +- .../ModelVisualization/RivAnnotationTools.cpp | 252 +++++++++--------- .../ModelVisualization/RivAnnotationTools.h | 9 +- .../Seismic/RivSeismicSectionPartMgr.cpp | 2 +- .../ProjectDataModel/Rim3dView.cpp | 33 +-- .../ProjectDataModel/Rim3dView.h | 1 + 7 files changed, 164 insertions(+), 141 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.cpp b/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.cpp index 677048f905..5f07d32aaa 100644 --- a/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.cpp +++ b/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.cpp @@ -31,7 +31,7 @@ RivAnnotationSourceInfo::RivAnnotationSourceInfo( const std::string m_text, cons //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivAnnotationTools::LabelPositionStrategy RivAnnotationSourceInfo::positionStrategyHint() const +RivAnnotationTools::LabelPositionStrategy RivAnnotationSourceInfo::labelPositionStrategyHint() const { return m_labelPositionHint; } @@ -39,7 +39,7 @@ RivAnnotationTools::LabelPositionStrategy RivAnnotationSourceInfo::positionStrat //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivAnnotationSourceInfo::setPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy strategy ) +void RivAnnotationSourceInfo::setLabelPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy strategy ) { m_labelPositionHint = strategy; } diff --git a/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.h b/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.h index 7749f9ac5e..4de5138e73 100644 --- a/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.h +++ b/ApplicationLibCode/ModelVisualization/RivAnnotationSourceInfo.h @@ -32,8 +32,8 @@ class RivAnnotationSourceInfo : public cvf::Object public: RivAnnotationSourceInfo( const std::string m_text, const std::vector& displayCoords ); - RivAnnotationTools::LabelPositionStrategy positionStrategyHint() const; - void setPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy strategy ); + RivAnnotationTools::LabelPositionStrategy labelPositionStrategyHint() const; + void setLabelPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy strategy ); std::string text() const; std::vector anchorPointsDisplayCoords() const; diff --git a/ApplicationLibCode/ModelVisualization/RivAnnotationTools.cpp b/ApplicationLibCode/ModelVisualization/RivAnnotationTools.cpp index 3a8bcbf7b5..5ac7232f66 100644 --- a/ApplicationLibCode/ModelVisualization/RivAnnotationTools.cpp +++ b/ApplicationLibCode/ModelVisualization/RivAnnotationTools.cpp @@ -26,7 +26,9 @@ #include "RivPartPriority.h" #include "RivPolylineGenerator.h" +#include "cafAppEnum.h" #include "cafEffectGenerator.h" + #include "cvfCamera.h" #include "cvfDrawableGeo.h" #include "cvfDrawableText.h" @@ -35,16 +37,45 @@ #include "cvfViewport.h" #include +#include + +namespace caf +{ + +template <> +void caf::AppEnum::setUp() +{ + addItem( RivAnnotationTools::LabelPositionStrategy::LEFT, "LEFT", "Left" ); + addItem( RivAnnotationTools::LabelPositionStrategy::RIGHT, "RIGHT", "Right" ); + addItem( RivAnnotationTools::LabelPositionStrategy::LEFT_AND_RIGHT, "LEFT_AND_RIGHT", "Left and Right" ); + addItem( RivAnnotationTools::LabelPositionStrategy::COUNT_HINT, "COUNT_HINT", "Count Hint" ); + addItem( RivAnnotationTools::LabelPositionStrategy::ALL, "All", "All" ); + addItem( RivAnnotationTools::LabelPositionStrategy::NONE, "None", "Disabled" ); + // RivAnnotationTools::LabelPositionStrategy::UNKNOWN is not included, as this is enum is not supposed to be displayed in GUI + setDefault( RivAnnotationTools::LabelPositionStrategy::RIGHT ); +} + +} // End namespace caf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivAnnotationTools::RivAnnotationTools( LabelPositionStrategy positionStrategy ) - : m_strategy( positionStrategy ) +RivAnnotationTools::RivAnnotationTools() + : m_strategy( RivAnnotationTools::LabelPositionStrategy::UNDEFINED ) , m_labelCountHint( 0 ) { } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivAnnotationTools::setLabelPositionStrategy( LabelPositionStrategy positionStrategy ) +{ + // By default, each annotation object has a label position strategy. Use this method to override the default. + + m_strategy = positionStrategy; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -86,166 +117,149 @@ struct LabelInfo //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivAnnotationTools::addAnnotationLabels( const cvf::Collection& partCollection, - const cvf::Camera* camera, - cvf::ModelBasicList* model ) +auto computeScalingFactorFromZoom = []( const cvf::Camera* camera ) -> double { - if ( !camera || !model ) return; + double scalingFactor = 1.0; - auto computeScalingFactorFromZoom = []( const cvf::Camera* camera ) -> double + if ( camera ) { - double scalingFactor = 1.0; - - if ( camera ) + auto viewPort = camera->viewport(); + cvf::Vec3d vpCorner1( 0, viewPort->height(), 0 ); + cvf::Vec3d vpCorner2( viewPort->width(), 0, 0 ); + bool unprojOk = true; + cvf::Vec3d corner1Display, corner2Display, e1; + unprojOk &= camera->unproject( vpCorner1, &corner1Display ); + unprojOk &= camera->unproject( vpCorner2, &corner2Display ); + + if ( unprojOk ) { - auto viewPort = camera->viewport(); - cvf::Vec3d vpCorner1( 0, viewPort->height(), 0 ); - cvf::Vec3d vpCorner2( viewPort->width(), 0, 0 ); - bool unprojOk = true; - cvf::Vec3d corner1Display, corner2Display, e1; - unprojOk &= camera->unproject( vpCorner1, &corner1Display ); - unprojOk &= camera->unproject( vpCorner2, &corner2Display ); - - if ( unprojOk ) - { - scalingFactor = 10 * ( corner1Display - corner2Display ).length(); - } + scalingFactor = 10 * ( corner1Display - corner2Display ).length(); } + } - return scalingFactor; - }; - - const double anchorLineScalingFactor = computeScalingFactorFromZoom( camera ); + return scalingFactor; +}; - std::vector labelInfo; +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +auto createLabel = []( const cvf::Camera* camera, + const RivAnnotationSourceInfo* annotationObject, + const double viewportWidth, + const double normalizedXPosition, + const double anchorLineScalingFactor ) -> std::optional +{ + if ( !camera || !annotationObject ) return std::nullopt; - for ( auto p : partCollection ) + cvf::Vec3d anchorPosition; + double smallestDistance = std::numeric_limits::max(); + for ( const auto& displayCoord : annotationObject->anchorPointsDisplayCoords() ) { - auto annotationObject = dynamic_cast( p->sourceInfo() ); - if ( annotationObject ) - { - if ( m_strategy == LabelPositionStrategy::RIGHT || m_strategy == LabelPositionStrategy::LEFT_AND_RIGHT ) - { - cvf::Vec3d lineAnchorPosition; - const auto width = camera->viewport()->width(); - double smallestDistance = 100000; + cvf::Vec3d screenCoord; + camera->project( displayCoord, &screenCoord ); - for ( const auto& v : annotationObject->anchorPointsDisplayCoords() ) - { - cvf::Vec3d screenCoord; - camera->project( v, &screenCoord ); + double horizontalDistance = std::fabs( normalizedXPosition * viewportWidth - screenCoord.x() ); - double candidate = 0.9 * width - screenCoord.x(); - candidate *= candidate; + if ( horizontalDistance < smallestDistance ) + { + smallestDistance = horizontalDistance; + anchorPosition = displayCoord; + } + } - if ( candidate < smallestDistance ) - { - smallestDistance = candidate; - lineAnchorPosition = v; - } - } + if ( smallestDistance == std::numeric_limits::max() ) return std::nullopt; - cvf::Vec3d directionPointToCam = ( camera->position() - lineAnchorPosition ).getNormalized(); + const cvf::Vec3d directionPointToCam = ( camera->position() - anchorPosition ).getNormalized(); - cvf::Vec3d labelPosition = lineAnchorPosition + directionPointToCam * anchorLineScalingFactor; - cvf::Vec3d labelScreenCoord; - camera->project( labelPosition, &labelScreenCoord ); - labelScreenCoord.x() = 0.9 * camera->viewport()->width(); - camera->unproject( labelScreenCoord, &labelPosition ); + cvf::Vec3d labelPosition = anchorPosition + directionPointToCam * anchorLineScalingFactor; - auto labelText = annotationObject->text(); + const double maxScreenSpaceAdjustment = viewportWidth * 0.05; + if ( smallestDistance < maxScreenSpaceAdjustment ) + { + // Establish a fixed horizontal anchor point for the label in screen coordinates. Achieved through conversion to screen coordinates, + // adjusting the x-coordinate, and then reverting to display coordinates. + cvf::Vec3d screenCoord; + camera->project( labelPosition, &screenCoord ); - labelInfo.push_back( { labelText, lineAnchorPosition, labelPosition } ); - } + screenCoord.x() = normalizedXPosition * viewportWidth; + camera->unproject( screenCoord, &labelPosition ); + } - if ( m_strategy == LabelPositionStrategy::LEFT || m_strategy == LabelPositionStrategy::LEFT_AND_RIGHT ) - { - cvf::Vec3d lineAnchorPosition; - const auto width = camera->viewport()->width(); - double smallestDistance = 100000; + return LabelInfo( annotationObject->text(), anchorPosition, labelPosition ); +}; - for ( const auto& v : annotationObject->anchorPointsDisplayCoords() ) - { - cvf::Vec3d screenCoord; - camera->project( v, &screenCoord ); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivAnnotationTools::addAnnotationLabels( const cvf::Collection& partCollection, + const cvf::Camera* camera, + cvf::ModelBasicList* model ) +{ + if ( !camera || !model ) return; - double candidate = 0.1 * width - screenCoord.x(); - candidate *= candidate; + const double anchorLineScalingFactor = computeScalingFactorFromZoom( camera ); - if ( candidate < smallestDistance ) - { - smallestDistance = candidate; - lineAnchorPosition = v; - } - } + std::vector labelInfo; - cvf::Vec3d directionPointToCam = ( camera->position() - lineAnchorPosition ).getNormalized(); + for ( auto p : partCollection ) + { + auto annotationObject = dynamic_cast( p->sourceInfo() ); + if ( annotationObject ) + { + auto strategy = annotationObject->labelPositionStrategyHint(); + if ( m_strategy != LabelPositionStrategy::UNDEFINED ) + { + strategy = m_strategy; + } - cvf::Vec3d labelPosition = lineAnchorPosition + directionPointToCam * anchorLineScalingFactor; - cvf::Vec3d labelScreenCoord; - camera->project( labelPosition, &labelScreenCoord ); - labelScreenCoord.x() = 0.1 * camera->viewport()->width(); - camera->unproject( labelScreenCoord, &labelPosition ); + const auto viewportWidth = camera->viewport()->width(); + const auto viewportHeight = camera->viewport()->height(); - auto labelText = annotationObject->text(); + if ( strategy == LabelPositionStrategy::RIGHT || strategy == LabelPositionStrategy::LEFT_AND_RIGHT ) + { + // Close to the right edge of the visible screen area + const auto normalizedXPosition = 0.9; - labelInfo.push_back( { labelText, lineAnchorPosition, labelPosition } ); + auto labelCandidate = createLabel( camera, annotationObject, viewportWidth, normalizedXPosition, anchorLineScalingFactor ); + if ( labelCandidate.has_value() ) labelInfo.push_back( labelCandidate.value() ); } - if ( m_strategy == LabelPositionStrategy::COUNT_HINT ) + if ( strategy == LabelPositionStrategy::LEFT || strategy == LabelPositionStrategy::LEFT_AND_RIGHT ) { - const auto vpWidth = camera->viewport()->width(); - const auto wpHeight = camera->viewport()->height(); + // 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() ); + } + if ( strategy == LabelPositionStrategy::COUNT_HINT || strategy == LabelPositionStrategy::ALL ) + { std::vector visibleCoords; for ( const auto& v : annotationObject->anchorPointsDisplayCoords() ) { cvf::Vec3d screenCoord; camera->project( v, &screenCoord ); - if ( screenCoord.x() > 0 && screenCoord.x() < vpWidth && screenCoord.y() > 0 && screenCoord.y() < wpHeight ) + if ( screenCoord.x() > 0 && screenCoord.x() < viewportWidth && screenCoord.y() > 0 && screenCoord.y() < viewportHeight ) visibleCoords.push_back( v ); } - size_t stride = std::max( size_t( 1 ), visibleCoords.size() / m_labelCountHint - 1 ); - - for ( size_t i = 0; i < visibleCoords.size(); i += stride ) + size_t stride = 1; + if ( strategy == LabelPositionStrategy::COUNT_HINT ) { - size_t adjustedIndex = std::min( i, visibleCoords.size() - 1 ); - - cvf::Vec3d lineAnchorPosition = visibleCoords[adjustedIndex]; - cvf::Vec3d directionPointToCam = ( camera->position() - lineAnchorPosition ).getNormalized(); - cvf::Vec3d labelPosition = lineAnchorPosition + directionPointToCam * anchorLineScalingFactor; - - auto labelText = annotationObject->text(); - - labelInfo.push_back( { labelText, lineAnchorPosition, labelPosition } ); + stride = std::max( size_t( 1 ), visibleCoords.size() / std::max( 1, m_labelCountHint - 1 ) ); } - } - else if ( m_strategy == LabelPositionStrategy::ALL ) - { - const auto vpWidth = camera->viewport()->width(); - const auto wpHeight = camera->viewport()->height(); - std::vector visibleCoords; - for ( const auto& v : annotationObject->anchorPointsDisplayCoords() ) - { - cvf::Vec3d screenCoord; - camera->project( v, &screenCoord ); - - if ( screenCoord.x() > 0 && screenCoord.x() < vpWidth && screenCoord.y() > 0 && screenCoord.y() < wpHeight ) - visibleCoords.push_back( v ); - } - - for ( size_t i = 0; i < visibleCoords.size(); i++ ) + for ( size_t i = 0; i < visibleCoords.size(); i += stride ) { - cvf::Vec3d lineAnchorPosition = visibleCoords[i]; - cvf::Vec3d directionPointToCam = ( camera->position() - lineAnchorPosition ).getNormalized(); - cvf::Vec3d labelPosition = lineAnchorPosition + directionPointToCam * anchorLineScalingFactor; + size_t adjustedIndex = std::min( i, visibleCoords.size() - 1 ); - auto labelText = annotationObject->text(); + const cvf::Vec3d lineAnchorPosition = visibleCoords[adjustedIndex]; + const cvf::Vec3d directionPointToCam = ( camera->position() - lineAnchorPosition ).getNormalized(); + const cvf::Vec3d labelPosition = lineAnchorPosition + directionPointToCam * anchorLineScalingFactor; - labelInfo.push_back( { labelText, lineAnchorPosition, labelPosition } ); + labelInfo.push_back( { annotationObject->text(), lineAnchorPosition, labelPosition } ); } } } diff --git a/ApplicationLibCode/ModelVisualization/RivAnnotationTools.h b/ApplicationLibCode/ModelVisualization/RivAnnotationTools.h index b9f924d2e7..f394e485b0 100644 --- a/ApplicationLibCode/ModelVisualization/RivAnnotationTools.h +++ b/ApplicationLibCode/ModelVisualization/RivAnnotationTools.h @@ -45,11 +45,16 @@ class RivAnnotationTools LEFT_AND_RIGHT, COUNT_HINT, ALL, - NONE + NONE, + UNDEFINED }; - RivAnnotationTools( LabelPositionStrategy positionStrategy ); + RivAnnotationTools(); + + // By default, each annotation object has a label position strategy. Use this method to override the default. + void setLabelPositionStrategy( LabelPositionStrategy positionStrategy ); void setCountHint( int countHint ); + void addAnnotationLabels( const cvf::Collection& partCollection, const cvf::Camera* camera, cvf::ModelBasicList* model ); static cvf::ref diff --git a/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp b/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp index f86df164a9..e0c4f239eb 100644 --- a/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/Seismic/RivSeismicSectionPartMgr.cpp @@ -267,7 +267,7 @@ 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->setPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy::RIGHT ); + annoObj->setLabelPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy::RIGHT ); firstPart->setSourceInfo( annoObj ); } diff --git a/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp b/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp index 31101f7645..85b2eb35df 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp +++ b/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp @@ -84,18 +84,6 @@ void caf::AppEnum::setUp() setDefault( Rim3dView::SURFACE ); } -template <> -void caf::AppEnum::setUp() -{ - addItem( RivAnnotationTools::LabelPositionStrategy::LEFT, "LEFT", "Left" ); - addItem( RivAnnotationTools::LabelPositionStrategy::RIGHT, "RIGHT", "Right" ); - addItem( RivAnnotationTools::LabelPositionStrategy::LEFT_AND_RIGHT, "LEFT_AND_RIGHT", "Left and Right" ); - addItem( RivAnnotationTools::LabelPositionStrategy::COUNT_HINT, "COUNT_HINT", "Count Hint" ); - addItem( RivAnnotationTools::LabelPositionStrategy::ALL, "All", "All" ); - addItem( RivAnnotationTools::LabelPositionStrategy::NONE, "None", "Disabled" ); - setDefault( RivAnnotationTools::LabelPositionStrategy::RIGHT ); -} - } // End namespace caf CAF_PDM_XML_ABSTRACT_SOURCE_INIT( Rim3dView, "View", "GenericView" ); // Do not use. Abstract class @@ -168,6 +156,11 @@ Rim3dView::Rim3dView() CAF_PDM_InitFieldNoDefault( &m_annotationStrategy, "AnnotationStrategy", "Annotation Strategy" ); CAF_PDM_InitField( &m_annotationCountHint, "AnnotationCountHint", 5, "Annotation Count Hint" ); + CAF_PDM_InitField( &m_forceAnnotationStrategy, + "ForceAnnotationStrategy", + false, + "Use Custom Annotation Strategy", + "Specify the strategy to be applied on all screen space annotations." ); m_seismicVizModel = new cvf::ModelBasicList; m_seismicVizModel->setName( "SeismicSectionModel" ); @@ -526,8 +519,12 @@ void Rim3dView::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOr gridGroup->add( &surfaceMode ); caf::PdmUiGroup* annotationGroup = uiOrdering.addNewGroup( "Annotations" ); + annotationGroup->add( &m_forceAnnotationStrategy ); annotationGroup->add( &m_annotationStrategy ); annotationGroup->add( &m_annotationCountHint ); + m_annotationStrategy.uiCapability()->setUiReadOnly( !m_forceAnnotationStrategy ); + m_annotationCountHint.uiCapability()->setUiReadOnly( + !m_forceAnnotationStrategy || ( m_annotationStrategy() != RivAnnotationTools::LabelPositionStrategy::COUNT_HINT ) ); uiOrdering.skipRemainingFields( true ); } @@ -1054,10 +1051,11 @@ void Rim3dView::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const { createDisplayModelAndRedraw(); } - else if ( changedField == &m_annotationCountHint || changedField == &m_annotationStrategy ) + else if ( changedField == &m_annotationCountHint || changedField == &m_annotationStrategy || changedField == &m_forceAnnotationStrategy ) { if ( m_viewer ) { + updateScreenSpaceModel(); m_viewer->update(); } } @@ -1694,8 +1692,13 @@ void Rim3dView::updateScreenSpaceModel() cvf::Collection partCollection; m_viewer->currentScene()->allParts( &partCollection ); - RivAnnotationTools annoTool( m_annotationStrategy() ); - annoTool.setCountHint( m_annotationCountHint() ); + RivAnnotationTools annoTool; + if ( m_forceAnnotationStrategy ) + { + annoTool.setLabelPositionStrategy( m_annotationStrategy() ); + annoTool.setCountHint( m_annotationCountHint() ); + } + annoTool.addAnnotationLabels( partCollection, m_viewer->mainCamera(), m_screenSpaceModel.p() ); nativeOrOverrideViewer()->addStaticModelOnce( m_screenSpaceModel.p(), isUsingOverrideViewer() ); diff --git a/ApplicationLibCode/ProjectDataModel/Rim3dView.h b/ApplicationLibCode/ProjectDataModel/Rim3dView.h index c7ae421369..ea0fc33f27 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim3dView.h +++ b/ApplicationLibCode/ProjectDataModel/Rim3dView.h @@ -337,6 +337,7 @@ class Rim3dView : public RimViewWindow, public RiuViewerToViewInterface, public caf::PdmField m_showZScaleLabel; caf::PdmPtrField m_comparisonView; + caf::PdmField m_forceAnnotationStrategy; caf::PdmField> m_annotationStrategy; caf::PdmField m_annotationCountHint;