Fix display of intersection lines in 3D view

* 10675 Fix missing intersection line geometry
* Change to list of visible surface intersection lines
* Enable surface intersection band for any intersection
* Show labels for intersection curves in 3D

The polylines are defined in the display coordinate system without Z-scaling. The z-scaling is applied to the visualization parts using Part::setTransform(Transform* transform)
The annotation objects are defined by display coordinates, so apply the Z-scaling to the coordinates.

* Improve naming of surfaces
* Use scaling factor of 1.0 for flat intersection views
This commit is contained in:
Magne Sjaastad authored and GitHub committed 2023-10-03 09:04:46 +02:00
1 parent 21843820e6
commit 10189da362
16 files changed
+130 -64

No files matched your search

@@ -36,17 +36,6 @@
CAF_CMD_SOURCE_INIT( RicCreateSurfaceIntersectionBandFeature, "RicCreateSurfaceIntersectionBandFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicCreateSurfaceIntersectionBandFeature::isCommandEnabled() const
{
auto* surfColl = RimTools::surfaceCollection();
auto surfaces = surfColl->ensembleSurfaces();
return !surfaces.empty();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -64,12 +53,11 @@ void RicCreateSurfaceIntersectionBandFeature::onActionTriggered( bool isChecked
RimSurfaceIntersectionBand* objectToSelect = nullptr;
const double defaultOpacity = 0.6;
const auto colors = RiaColorTables::structuralUncertaintyColors();
if ( firstEnsembleSurface )
{
const double defaultOpacity = 0.6;
auto colors = RiaColorTables::structuralUncertaintyColors();
// Create min/max band
{
auto surf1 = firstEnsembleSurface->findStatisticsSurface( RigSurfaceStatisticsCalculator::StatisticsType::MIN );
@@ -110,6 +98,27 @@ void RicCreateSurfaceIntersectionBandFeature::onActionTriggered( bool isChecked
}
}
}
else
{
auto band = intersection->addIntersectionBand();
auto surfColl = RimTools::surfaceCollection();
auto surfaces = surfColl->surfaces();
if ( surfaces.size() > 1 )
{
band->setSurfaces( surfaces[0], surfaces[1] );
}
auto color = colors.cycledColor3f( 1 );
band->setBandColor( color );
band->setBandOpacity( defaultOpacity );
band->setPolygonOffsetUnit( 0.1 );
band->lineAppearance()->setColor( color );
objectToSelect = band;
}
intersection->rebuildGeometryAndScheduleCreateDisplayModel();
intersection->updateAllRequiredEditors();
@@ -28,7 +28,6 @@ class RicCreateSurfaceIntersectionBandFeature : public caf::CmdFeature
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() const override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};
@@ -51,6 +51,7 @@
#include "RiuGeoMechXfTensorResultAccessor.h"
#include "RivAnnotationSourceInfo.h"
#include "RivExtrudedCurveIntersectionGeometryGenerator.h"
#include "RivExtrudedCurveIntersectionSourceInfo.h"
#include "RivIntersectionHexGridInterface.h"
@@ -231,7 +232,7 @@ void RivIntersectionResultsColoringTools::calculateNodeOrElementNodeBasedGeoMech
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivExtrudedCurveIntersectionPartMgr::generatePartGeometry( cvf::UByteArray* visibleCells )
void RivExtrudedCurveIntersectionPartMgr::generatePartGeometry( cvf::UByteArray* visibleCells, cvf::Transform* scaleTransform )
{
if ( m_intersectionGenerator.isNull() ) return;
@@ -324,7 +325,7 @@ void RivExtrudedCurveIntersectionPartMgr::generatePartGeometry( cvf::UByteArray*
applySingleColorEffect();
createAnnotationSurfaceParts( useBufferObjects );
createAnnotationSurfaceParts( useBufferObjects, scaleTransform );
}
//--------------------------------------------------------------------------------------------------
@@ -601,7 +602,7 @@ void RivExtrudedCurveIntersectionPartMgr::createExtrusionDirParts( bool useBuffe
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivExtrudedCurveIntersectionPartMgr::createAnnotationSurfaceParts( bool useBufferObjects )
void RivExtrudedCurveIntersectionPartMgr::createAnnotationSurfaceParts( bool useBufferObjects, cvf::Transform* scaleTransform )
{
m_annotationParts.clear();
@@ -619,9 +620,10 @@ void RivExtrudedCurveIntersectionPartMgr::createAnnotationSurfaceParts( bool use
auto part = createCurvePart( polylines,
useBufferObjects,
surface->userDescription(),
surface->fullName(),
curve->lineAppearance()->color(),
curve->lineAppearance()->thickness() );
curve->lineAppearance()->thickness(),
scaleTransform );
if ( part.notNull() ) m_annotationParts.push_back( part.p() );
}
@@ -645,18 +647,20 @@ void RivExtrudedCurveIntersectionPartMgr::createAnnotationSurfaceParts( bool use
{
auto part = createCurvePart( polylineA,
useBufferObjects,
surface1->userDescription(),
surface1->fullName(),
band->lineAppearance()->color(),
band->lineAppearance()->thickness() );
band->lineAppearance()->thickness(),
scaleTransform );
if ( part.notNull() ) m_annotationParts.push_back( part.p() );
}
{
auto part = createCurvePart( polylineB,
useBufferObjects,
surface2->userDescription(),
surface2->fullName(),
band->lineAppearance()->color(),
band->lineAppearance()->thickness() );
band->lineAppearance()->thickness(),
scaleTransform );
if ( part.notNull() ) m_annotationParts.push_back( part.p() );
}
@@ -730,7 +734,8 @@ cvf::ref<cvf::Part> RivExtrudedCurveIntersectionPartMgr::createCurvePart( const
bool useBufferObjects,
const QString& description,
const cvf::Color3f& color,
float lineWidth )
float lineWidth,
cvf::Transform* scaleTransform )
{
auto polylineGeo = RivPolylineGenerator::createLineAlongPolylineDrawable( polylines );
if ( polylineGeo.notNull() )
@@ -761,6 +766,31 @@ cvf::ref<cvf::Part> RivExtrudedCurveIntersectionPartMgr::createCurvePart( const
eff->setRenderState( polyOffset.p() );
part->setEffect( eff.p() );
if ( part.notNull() && scaleTransform )
{
// The polylines are defined in the display coordinate system without Z-scaling. The z-scaling is applied to the visualization
// parts using Part::setTransform(Transform* transform)
// The annotation objects are defined by display coordinates, so apply the Z-scaling to the coordinates
std::vector<cvf::Vec3d> displayCoords;
const auto& mat = scaleTransform->worldTransform();
for ( const auto& p : polylines )
{
displayCoords.push_back( p.getTransformedPoint( mat ) );
}
// 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( description.toStdString(), displayCoords );
annoObj->setLabelPositionStrategyHint( RivAnnotationTools::LabelPositionStrategy::RIGHT );
annoObj->setShowColor( true );
annoObj->setColor( color );
part->setSourceInfo( annoObj );
}
return part;
}
@@ -81,19 +81,20 @@ public:
const RivIntersectionGeometryGeneratorInterface* intersectionGeometryGenerator() const;
void generatePartGeometry( cvf::UByteArray* visibleCells );
void generatePartGeometry( cvf::UByteArray* visibleCells, cvf::Transform* scaleTransfor );
private:
void createFaultLabelParts( const std::vector<std::pair<QString, cvf::Vec3d>>& labelAndAnchors );
void createPolyLineParts( bool useBufferObjects );
void createExtrusionDirParts( bool useBufferObjects );
void createAnnotationSurfaceParts( bool useBufferObjects );
void createAnnotationSurfaceParts( bool useBufferObjects, cvf::Transform* scaleTransform );
cvf::ref<cvf::Part> createCurvePart( const std::vector<cvf::Vec3d>& polylines,
bool useBufferObjects,
const QString& description,
const cvf::Color3f& color,
float lineWidth );
float lineWidth,
cvf::Transform* scaleTransform );
private:
caf::PdmPointer<RimExtrudedCurveIntersection> m_rimIntersection;
@@ -242,11 +242,13 @@ auto createMultipleLabels = []( const cvf::Camera* camera,
//--------------------------------------------------------------------------------------------------
void RivAnnotationTools::addAnnotationLabels( const cvf::Collection<cvf::Part>& partCollection,
const cvf::Camera* camera,
cvf::ModelBasicList* model )
cvf::ModelBasicList* model,
bool computeScalingFactor )
{
if ( !camera || !model ) return;
const double anchorLineScalingFactor = computeScalingFactorFromZoom( camera );
// The scaling factor is computed using the camera, and this does not work for the flat intersection view
const double anchorLineScalingFactor = computeScalingFactor ? computeScalingFactorFromZoom( camera ) : 1.0;
for ( auto p : partCollection )
{
@@ -58,7 +58,10 @@ public:
void setCountHint( int countHint );
// Create labels for the given collection of parts. The labels are added to the given model.
void addAnnotationLabels( const cvf::Collection<cvf::Part>& partCollection, const cvf::Camera* camera, cvf::ModelBasicList* model );
void addAnnotationLabels( const cvf::Collection<cvf::Part>& partCollection,
const cvf::Camera* camera,
cvf::ModelBasicList* model,
bool computeScalingFactor );
static cvf::ref<cvf::Part> createPartFromPolyline( const cvf::Color3f& color, const std::vector<cvf::Vec3d>& polyLine );
@@ -248,7 +248,7 @@ void RimIntersectionCollection::appendDynamicPartsToModel( cvf::ModelBasicList*
{
if ( cs->isActive() )
{
cs->intersectionPartMgr()->generatePartGeometry( visibleCells );
cs->intersectionPartMgr()->generatePartGeometry( visibleCells, scaleTransform );
cs->intersectionPartMgr()->appendIntersectionFacesToModel( model, scaleTransform );
cs->intersectionPartMgr()->appendMeshLinePartsToModel( model, scaleTransform );
}
@@ -539,7 +539,7 @@ void Rim2dIntersectionView::onCreateDisplayModel()
m_intersectionVizModel->removeAllParts();
m_flatIntersectionPartMgr->generatePartGeometry( nullptr );
m_flatIntersectionPartMgr->generatePartGeometry( nullptr, scaleTransform() );
m_flatIntersectionPartMgr->appendIntersectionFacesToModel( m_intersectionVizModel.p(), scaleTransform() );
m_flatIntersectionPartMgr->appendMeshLinePartsToModel( m_intersectionVizModel.p(), scaleTransform() );
m_flatIntersectionPartMgr->appendPolylinePartsToModel( *this, m_intersectionVizModel.p(), scaleTransform() );
@@ -1698,7 +1698,9 @@ void Rim3dView::updateScreenSpaceModel()
annoTool.setCountHint( m_annotationCountHint() );
}
annoTool.addAnnotationLabels( partCollection, m_viewer->mainCamera(), m_screenSpaceModel.p() );
// The scaling factor is computed using the camera, and this does not work for the flat intersection view
bool computeScalingFactor = ( viewContent() != RiaDefines::View3dContent::FLAT_INTERSECTION );
annoTool.addAnnotationLabels( partCollection, m_viewer->mainCamera(), m_screenSpaceModel.p(), computeScalingFactor );
nativeOrOverrideViewer()->addStaticModelOnce( m_screenSpaceModel.p(), isUsingOverrideViewer() );
}
@@ -528,19 +528,24 @@ void RimGridView::appendIntersectionsToModel( bool cellFiltersActive, bool prope
if ( m_intersectionCollection->shouldApplyCellFiltersToIntersections() && ( cellFiltersActive || propertyFiltersActive ) )
{
m_intersectionCollection->appendPartsToModel( *this, m_intersectionVizModel.p(), scaleTransform() );
if ( !propertyFiltersActive )
{
cvf::UByteArray visibleCells;
calculateCellVisibility( &visibleCells, { RANGE_FILTERED_WELL_CELLS, RANGE_FILTERED } );
m_intersectionCollection->appendDynamicPartsToModel( m_intersectionVizModel.p(), scaleTransform(), currentTimeStep(), &visibleCells );
}
// NB! Geometry objects are recreated in appendDynamicPartsToModel(), always call
// appendPartsToModel() after appendDynamicPartsToModel()
m_intersectionCollection->appendPartsToModel( *this, m_intersectionVizModel.p(), scaleTransform() );
}
else
{
m_intersectionCollection->appendPartsToModel( *this, m_intersectionVizModel.p(), scaleTransform() );
m_intersectionCollection->appendDynamicPartsToModel( m_intersectionVizModel.p(), scaleTransform(), currentTimeStep() );
// NB! Geometry objects are recreated in appendDynamicPartsToModel(), always call
// appendPartsToModel() after appendDynamicPartsToModel()
m_intersectionCollection->appendPartsToModel( *this, m_intersectionVizModel.p(), scaleTransform() );
}
m_intersectionVizModel->updateBoundingBoxesRecursive();
nativeOrOverrideViewer()->addStaticModelOnce( m_intersectionVizModel.p(), isUsingOverrideViewer() );
@@ -55,8 +55,8 @@ RimSeismicSectionCollection::RimSeismicSectionCollection()
CAF_PDM_InitField( &m_surfaceIntersectionLinesScaleFactor, "SurfaceIntersectionLinesScaleFactor", 5.0, "Line Scale Factor ( >= 1.0 )" );
CAF_PDM_InitFieldNoDefault( &m_hiddenSurfaceLines, "HiddenSurfaceLines", "Hidden Surface Lines" );
m_hiddenSurfaceLines.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_surfacesWithVisibleSurfaceLines, "SurfacesWithVisibleSurfaceLines", "Surface Lines" );
m_surfacesWithVisibleSurfaceLines.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
setName( "Seismic Sections" );
}
@@ -148,7 +148,7 @@ void RimSeismicSectionCollection::defineUiOrdering( QString uiConfigName, caf::P
{
auto grp = uiOrdering.addNewGroup( "Surface Intersection Lines" );
grp->add( &m_surfaceIntersectionLinesScaleFactor );
grp->add( &m_hiddenSurfaceLines );
grp->add( &m_surfacesWithVisibleSurfaceLines );
uiOrdering.skipRemainingFields( true );
}
@@ -171,23 +171,7 @@ void RimSeismicSectionCollection::appendPartsToModel( Rim3dView*
{
if ( !isChecked() ) return;
auto computeVisibleSurface = [&]() -> std::vector<RimSurface*>
{
std::vector<RimSurface*> visibleSurfaces;
auto allSurfaces = RimTools::surfaceCollection()->surfaces();
auto hiddenSurfaces = m_hiddenSurfaceLines.value();
for ( const auto& surf : allSurfaces )
{
if ( std::find( hiddenSurfaces.begin(), hiddenSurfaces.end(), surf ) != hiddenSurfaces.end() ) continue;
visibleSurfaces.push_back( surf );
}
return visibleSurfaces;
};
auto visibleSurfaces = computeVisibleSurface();
auto visibleSurfaces = m_surfacesWithVisibleSurfaceLines().ptrReferencedObjectsByType();
for ( auto& section : m_seismicSections )
{
@@ -275,6 +259,21 @@ void RimSeismicSectionCollection::updateLegendRangesTextAndVisibility( RiuViewer
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSeismicSectionCollection::setSurfacesVisible( const std::vector<RimSurface*>& surfaces )
{
for ( auto surface : surfaces )
{
if ( std::find( m_surfacesWithVisibleSurfaceLines.begin(), m_surfacesWithVisibleSurfaceLines.end(), surface ) ==
m_surfacesWithVisibleSurfaceLines.end() )
{
m_surfacesWithVisibleSurfaceLines.push_back( surface );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -282,8 +281,11 @@ QList<caf::PdmOptionItemInfo> RimSeismicSectionCollection::calculateValueOptions
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_hiddenSurfaceLines )
if ( fieldNeedingOptions == &m_surfacesWithVisibleSurfaceLines )
{
// If a surface is deleted, we need to remove it from the list of surfaces with visible surface lines
m_surfacesWithVisibleSurfaceLines.removePtr( nullptr );
auto surfaceCollection = RimTools::surfaceCollection();
for ( auto surface : surfaceCollection->surfaces() )
{
@@ -72,6 +72,8 @@ public:
std::vector<RimRegularLegendConfig*> legendConfigs();
void updateLegendRangesTextAndVisibility( RiuViewer* nativeOrOverrideViewer, bool isUsingOverrideViewer );
void setSurfacesVisible( const std::vector<RimSurface*>& surfaces );
protected:
caf::PdmFieldHandle* userDescriptionField() override;
@@ -88,5 +90,5 @@ private:
caf::PdmChildArrayField<RimSeismicSection*> m_seismicSections;
caf::PdmField<double> m_surfaceIntersectionLinesScaleFactor;
caf::PdmPtrArrayField<RimSurface*> m_hiddenSurfaceLines;
caf::PdmPtrArrayField<RimSurface*> m_surfacesWithVisibleSurfaceLines;
};
@@ -594,7 +594,8 @@ bool RimGridCaseSurface::exportStructSurfaceFromGridCase( std::vector<cvf::Vec3d
QString RimGridCaseSurface::fullName() const
{
QString retval = RimSurface::fullName();
retval += " - K:";
if ( !retval.isEmpty() ) retval += " - ";
retval += "K:";
retval += QString::number( m_oneBasedSliceIndex );
return retval;
}
@@ -234,7 +234,11 @@ QString RimSurface::fullName() const
{
if ( depthOffset() != 0.0 )
{
return QString( "%1 - Offset:%2" ).arg( m_userDescription, QString::number( depthOffset() ) );
QString name = m_userDescription;
if ( !name.isEmpty() ) name += " - ";
name += QString( "Offset:%1" ).arg( QString::number( depthOffset() ) );
return name;
}
return QString( "%1" ).arg( m_userDescription );
@@ -30,6 +30,7 @@
#include "RimGridView.h"
#include "RimProject.h"
#include "RimRegularLegendConfig.h"
#include "RimSeismicSectionCollection.h"
#include "RimSurface.h"
#include "RimSurfaceInView.h"
#include "RimSurfaceResultDefinition.h"
@@ -241,7 +242,6 @@ RimSurface* RimSurfaceCollection::addGridCaseSurface( RimCase* sourceCase, int o
s->setCase( sourceCase );
s->setOneBasedIndex( oneBasedSliceIndex );
s->setUserDescription( "Surface" );
if ( !s->onLoadData() )
{
@@ -305,6 +305,12 @@ void RimSurfaceCollection::updateViews( const std::vector<RimSurface*>& surfsToR
for ( auto view : views )
{
view->updateSurfacesInViewTreeItems();
if ( auto gridView = dynamic_cast<RimGridView*>( view ) )
{
auto seismicCollection = gridView->seismicSectionCollection();
seismicCollection->setSurfacesVisible( surfsToReload );
}
}
std::set<Rim3dView*> viewsNeedingUpdate;
@@ -147,7 +147,7 @@ std::vector<std::pair<cvf::Vec3d, size_t>>
// Create vector of pairs based on pair of two vectors
std::vector<std::pair<cvf::Vec3d, size_t>> polyLineAndSegment;
for ( size_t i = 0; i < polyLineAndSegment.size(); i++ )
for ( size_t i = 0; i < resampledPolyline.size(); i++ )
{
polyLineAndSegment.push_back( std::make_pair( resampledPolyline[i], segmentIndices[i] ) );
}