You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make contour maps available inside normal 3D views. A new in-view mirror collection on RimGridView lists every contour map in the project; a per-view wrapper object points at an existing contour map view and renders its geometry in the 3D scene at a controllable elevation, with an option to drape the contour lines onto the visible grid geometry.
Why
Contour maps today can only be seen in their own dedicated 2D view. RimEclipseContourMapView derives from RimEclipseView but locks the camera top-down (sm_defaultViewMatrix, navigation rotation disabled, orthographic projection), and the projection geometry is generated in a flat local coordinate space with z = 0 that the part manager lifts to RigContourMapGrid::origin3d() — the minimum z of the expanded bounding box, i.e. below the reservoir.
The result is that a contour map cannot be correlated visually with the 3D model it was computed from. Users want to overlay a contour map (including ensemble statistics maps) on a normal 3D view: see the aggregated values as a coloured plane above the grid, see the contour lines, and optionally drape those lines onto the visible grid geometry so they read as isolines on the reservoir surface.
How
Mirror, don't duplicate.RimContourMapInView holds a caf::PdmPtrField<RimEclipseContourMapView*> and renders that view's already-computed trianglesWithVertexValues(), contourPolygons() and legendConfig(). No second projection, no second result computation, no duplicated result/aggregation/resolution UI. The wrapper owns only presentation state: where the map sits in z, whether the surface and lines are drawn, and whether lines are draped.
This follows the established in-view collection pattern used by RimSurfaceInViewCollection and RimPolygonInViewCollection: project-level master data under RimOilField, a caf::PdmChildField mirror on the view, thin wrapper objects with a PdmPtrField back to the master item, and a sync routine that orphan-sweeps, find-or-creates and reorders.
Scope
Eclipse contour maps and ensemble statistics contour maps. RimStatisticsContourMapView derives from RimEclipseContourMapView, so a single pointer type covers both.
GeoMech contour maps are deliberately out of scope: their collection lives per-case on RimGeoMechCase rather than on RimOilField, and there is no common view base type across the two families.
Key design decisions
Decision
Choice
Rationale
What the wrapper holds
Pointer to an existing contour map view
Reuses the computed projection, triangles, contour polygons and legend. RimContourMapProjection::baseView() already assumes a contour-map-view ancestor, so owning an independent projection would require reworking that.
Vertical placement
MapPosition enum (Top of case / Bottom of case / User defined depth) + Depth Offset
Default TOP_OF_CASE puts the map above the reservoir instead of underneath it. TOP_OF_CASE uses expandedBoundingBox().max().z(), the same value RicCreateContourMapPolygonTools uses for contour-map-derived polygons.
Which maps are mirrored
All of them, unchecked by default
A 3D view of one realization may legitimately want to overlay an ensemble statistics map whose primary case is a different one. Filtering by case would exclude exactly that.
Scene model
Per-frame named cvf::ModelBasicList, not a static viz model
Contour map data is time-step dependent. Follows the pattern already in RimEclipseContourMapView::appendContourMapProjectionToModel.
Contour labels
Not drawn in 3D for this iteration
Label placement is camera-dependent; the 2D view only keeps them correct via onViewNavigationChanged().
Prerequisites
None. All work is inside ApplicationLibCode; no external resources or configuration changes are needed.
Steps
1. Elevation control in the part manager
Every consumer of contour map geometry repeats the same conversion in four places — createProjectionMapPart (~line 245), createContourPolygons (~line 304), createContourLabels, and createPickPointVisDrawable (~line 552):
Introduce an elevation provider so the z component can be replaced without touching geometry generation.
Add ApplicationLibCode/ModelVisualization/RivContourMapElevationProvider.{h,cpp} with an abstract provider and two implementations:
classRivContourMapElevationProvider
{
public:virtual~RivContourMapElevationProvider();
// localPos2d is relative to RigContourMapGrid::origin2d().// Returns the domain z to use, or nullopt where no elevation is defined.virtual std::optional<double> domainElevation( const cvf::Vec2d& localPos2d ) const = 0;
};
classRivContourMapFlatElevation : publicRivContourMapElevationProvider { /* constant z */ };
classRivContourMapTopographyElevation : publicRivContourMapElevationProvider { /* backed by RigContourMapTopography */ };
Centralise the coordinate conversion in RivContourMapProjectionPartMgr behind a private helper:
With elevationProvider == nullptr it must return exactly today's value (+ origin3d()) and never nullopt, so existing 2D contour map views are byte-for-byte unchanged.
Add a trailing const RivContourMapElevationProvider* elevationProvider = nullptr parameter to appendProjectionToModel and appendContourLinesToModel. Existing call sites in RimEclipseContourMapView.cpp and RimGeoMechContourMapView.cpp need no edit.
Handle gaps in createContourPolygons: when toDisplayCoord returns nullopt for either end of a segment, skip that segment. Dropping segments naturally splits a draped polyline wherever the grid is not visible below it — the same gap handling RivSeismicSectionPartMgr::projectPolyLineOntoSurface uses.
Fix the discarded polygon offset. At RivContourMapProjectionPartMgr.cpp:174 (and :92) the return value of caf::MeshEffectGenerator::createAndConfigurePolygonOffsetRenderState( caf::PO_1 ) is discarded and never assigned to the effect, so contour lines get no polygon offset at all. In the 2D view the lines are coplanar with the map so nothing shows; draped onto grid geometry they will z-fight badly. Assign the render state to an un-cached effect (generateUnCachedEffect(), otherwise the shared cached effect is polluted), using the recipe already established in RivSurfaceIntersectionCurveTools::createCurvePart (factor = -5, units = -1000). This is required for the feature, not a drive-by cleanup.
2. Top-elevation lookup over the contour map grid
Nothing in the repo does "drape onto grid topography" today (grep -i drape returns nothing), and RigMainGrid has no topZAtXY()-style helper. Rather than ray-casting per polygon vertex, precompute a raster once over the contour map grid's vertices and bilinearly interpolate — the same shape as RigContourMapProjection::interpolateValue. The vertex count is the same order as the map itself (a 100×100 map is ~10k rays, computed once per display model rebuild).
Implement the per-vertex ray drop using the idiom already present at RigContourMapCalculator.cpp:450: build a thin vertical cvf::BoundingBox at the vertex x/y spanning the grid's z range → RigMainGrid::findIntersectingCells( bbox ) → for each cell set in cellVisibility, RigHexIntersectionTools::lineHexCellIntersection with a vertical segment top→bottom → keep the maximum hit z. Use #pragma omp parallel for over vertices, matching the surrounding contour map code.
Implement bilinear interpolation in elevationAtLocalPos, returning nullopt when any contributing vertex is undefined.
cellVisibility is the host view's RimGridView::currentTotalCellVisibility(), so the drape follows the 3D view's cell filters and property filters — this is what "project onto the visible geometry" means.
3. The in-view wrapper
Add ApplicationLibCode/ProjectDataModel/ContourMap/RimContourMapInView.{h,cpp}, deriving from RimCheckableNamedObject:
using SourceItemT = RimEclipseContourMapView; // matches the in-view wrapper convention
RimEclipseContourMapView* sourceItem() const;
enumclassMapPosition { TOP_OF_CASE, BOTTOM_OF_CASE, USER_DEFINED_DEPTH };
Non-PDM members: cvf::ref<RivContourMapProjectionPartMgr> m_partMgr (lazily created, exactly as RimSurfaceInView::surfacePartMgr() does) and a cached std::shared_ptr<RigContourMapTopography> cleared by clearGeometry().
Implement appendPartsToModel( cvf::ModelBasicList*, const caf::DisplayCoordTransform*, const cvf::Camera*, int hostTimeStep ):
Guard: source view non-null, its case has loaded data, isChecked().
auto* proj = m_contourMapView->contourMapProjection(); then proj->generateResultsIfNecessary( timeStep ); proj->generateGeometryIfNecessary(); — clamp timeStep to the source case's time step count, since the host view and the contour map's case need not have the same number of steps.
Build a RivContourMapFlatElevation from mapElevation() and call appendProjectionToModel(...) when m_showMapSurface.
Build either the flat provider or a RivContourMapTopographyElevation and call appendContourLinesToModel(..., showContourLines = m_showContourLines, showContourLabels = false, ...). Passing showContourLabels = false already short-circuits createContourLabels (RivContourMapProjectionPartMgr.cpp:149).
Implement legend forwarding: legendConfig() returns m_contourMapView->contourMapProjection()->legendConfig(), and updateLegendRangesTextAndVisibility( RiuViewer*, bool ) calls the source projection's updateLegend() (which sets ranges and title) then addColorLegendToBottomLeftCorner( legendConfig()->titledOverlayFrame(), ... ), mirroring RimSurfaceInView::updateLegendRangesTextAndVisibility (RimSurfaceInView.cpp:269).
Implement fieldChangedByUi: clearGeometry() for m_projectLinesOnGeometry (invalidates the topography cache), then firstAncestorOfType<Rim3dView>()->scheduleCreateDisplayModelAndRedraw().
4. The in-view collection
The master collection RimEclipseContourMapViewCollection is a flatcaf::PdmObjectCollection<RimEclipseContourMapView>, not a caf::PdmNestedCollection, so the CRTP template RimNestedMirrorCollectionInView (used by RimPolygonInViewCollection) does not apply. Model the sync on the flat half of RimSurfaceInViewCollection::syncSurfacesWithView().
Add ApplicationLibCode/ProjectDataModel/ContourMap/RimContourMapInViewCollection.{h,cpp}, deriving from RimCheckableNamedObject:
Implement the sync in updateFromContourMapCollection(): orphan-sweep children whose PdmPtrField has been auto-nulled by PDM, find-or-create a wrapper per source view, then clearWithoutDelete() and push back in source order. Every new wrapper starts unchecked.
5. Wiring into the views
Extend the bitmask at ApplicationLibCode/Application/RiaDefines.h:269:
RimGridView.{h,cpp}: add caf::PdmChildField<RimContourMapInViewCollection*> m_contourMapInViewCollection plus accessor, created eagerly in the constructor next to m_polygonInViewCollection (RimGridView.cpp:106). Handle ItemIn3dView::CONTOUR_MAP in updateViewTreeItems (RimGridView.cpp:533) by calling updateFromContourMapCollection().
RimEclipseView.cpp — scene assembly in onUpdateDisplayModelForCurrentTimeStep(), using the per-frame named-model pattern from RimEclipseContourMapView.cpp:333 (not a static viz model, because the data is time-step dependent):
RimEclipseView.cpp — tree and legends: uiTreeOrdering.add( contourMapInViewCollection() ) in defineUiTreeOrdering (~line 2141); append the collection's legend configs in legendConfigs() (~line 2536); call updateLegendRangesTextAndVisibility(...) in onUpdateLegends() (~line 1674) when checked.
RimEclipseContourMapView.cpp: suppress the collection inside contour map views themselves (they derive from RimEclipseView), the same way surfaceInViewCollection() returns nullptr there (RimEclipseContourMapView.cpp:641) — don't add it to the tree and skip the append. Otherwise every contour map view would offer to render every other contour map.
6. Change notification
RimEclipseContourMapViewCollection.cpp: after addView, removeChild and in onChildDeleted, broadcast to all views, following RimPolygonCollection::updateViewTreeItems() (RimPolygonCollection.cpp:203):
for ( auto view : RimProject::current()->allViews() )
{
view->updateViewTreeItems( RiaDefines::ItemIn3dView::CONTOUR_MAP );
view->scheduleCreateDisplayModelAndRedraw();
}
RicNewContourMapViewFeature.cpp: trigger the same broadcast after creating a map, so it appears in already-open 3D views without a reload.
7. Build files
Headers are not listed in this project's cmake fragments — only .cpp files.
Regression check on the 2D view: create a contour map (New Contour Map from a 3D view) and confirm the 2D view is visually unchanged. This validates the toDisplayCoord refactor and the polygon offset fix.
Basic overlay: open a normal 3D view. Contour Maps appears in the tree with the map listed and unchecked. Check it — the coloured plane renders above the grid (TOP_OF_CASE) with contour lines, and its legend appears in the bottom-left corner.
Placement: switch Map Position through Bottom of Case and User Defined Depth, and vary Depth Offset. The plane moves accordingly.
Visibility toggles: toggle Show Map Surface and Show Contour Lines independently.
Draping: enable Project Lines on Geometry. Lines follow the grid topography and are cut where no cell is visible. Apply a cell filter or property filter in the 3D view and confirm the drape follows the new visibility and does not z-fight.
Time steps: step through time steps in the 3D view and confirm the map updates.
Ensemble: create an ensemble statistics contour map and confirm it also appears and renders.
Deletion: delete the contour map view and confirm the wrapper disappears from every 3D view without a crash.
Project round-trip: save the project, reopen it, and confirm check state, map position, offset and drape flag all persist.
ModelVisualization/RivContourMapProjectionPartMgr.{h,cpp}, ProjectDataModel/RimGridView.{h,cpp}, ProjectDataModel/RimEclipseView.cpp, ProjectDataModel/ContourMap/RimEclipseContourMapView.cpp, ProjectDataModel/ContourMap/RimEclipseContourMapViewCollection.cpp, Commands/RicNewContourMapViewFeature.cpp, Application/RiaDefines.h, plus 3 CMakeLists_files.cmake.
Known limitations (documented, not fixed here)
Contour labels are not drawn in the 3D view. They are camera-dependent and would need an onViewNavigationChanged() hook in RimEclipseView to stay correct while rotating.
The map surface is always flat; only the contour lines can be draped.
If both the 2D contour map view and a 3D view showing it are open on different time steps, the shared projection cache (m_currentResultTimestep) will recompute on each redraw. Correct, but it costs time; worth revisiting if it proves annoying.
RivContourMapProjectionPartMgr.h — already decoupled from the projection object; takes vertices, grid, background colour and scalar mapper as arguments
Implementation plan for #1043.
Description
What
Make contour maps available inside normal 3D views. A new in-view mirror collection on
RimGridViewlists every contour map in the project; a per-view wrapper object points at an existing contour map view and renders its geometry in the 3D scene at a controllable elevation, with an option to drape the contour lines onto the visible grid geometry.Why
Contour maps today can only be seen in their own dedicated 2D view.
RimEclipseContourMapViewderives fromRimEclipseViewbut locks the camera top-down (sm_defaultViewMatrix, navigation rotation disabled, orthographic projection), and the projection geometry is generated in a flat local coordinate space withz = 0that the part manager lifts toRigContourMapGrid::origin3d()— the minimum z of the expanded bounding box, i.e. below the reservoir.The result is that a contour map cannot be correlated visually with the 3D model it was computed from. Users want to overlay a contour map (including ensemble statistics maps) on a normal 3D view: see the aggregated values as a coloured plane above the grid, see the contour lines, and optionally drape those lines onto the visible grid geometry so they read as isolines on the reservoir surface.
How
Mirror, don't duplicate.
RimContourMapInViewholds acaf::PdmPtrField<RimEclipseContourMapView*>and renders that view's already-computedtrianglesWithVertexValues(),contourPolygons()andlegendConfig(). No second projection, no second result computation, no duplicated result/aggregation/resolution UI. The wrapper owns only presentation state: where the map sits in z, whether the surface and lines are drawn, and whether lines are draped.This follows the established in-view collection pattern used by
RimSurfaceInViewCollectionandRimPolygonInViewCollection: project-level master data underRimOilField, acaf::PdmChildFieldmirror on the view, thin wrapper objects with aPdmPtrFieldback to the master item, and a sync routine that orphan-sweeps, find-or-creates and reorders.Scope
Eclipse contour maps and ensemble statistics contour maps.
RimStatisticsContourMapViewderives fromRimEclipseContourMapView, so a single pointer type covers both.GeoMech contour maps are deliberately out of scope: their collection lives per-case on
RimGeoMechCaserather than onRimOilField, and there is no common view base type across the two families.Key design decisions
RimContourMapProjection::baseView()already assumes a contour-map-view ancestor, so owning an independent projection would require reworking that.MapPositionenum (Top of case / Bottom of case / User defined depth) +Depth OffsetTOP_OF_CASEputs the map above the reservoir instead of underneath it.TOP_OF_CASEusesexpandedBoundingBox().max().z(), the same valueRicCreateContourMapPolygonToolsuses for contour-map-derived polygons.cvf::ModelBasicList, not a static viz modelRimEclipseContourMapView::appendContourMapProjectionToModel.onViewNavigationChanged().Prerequisites
None. All work is inside
ApplicationLibCode; no external resources or configuration changes are needed.Steps
1. Elevation control in the part manager
Every consumer of contour map geometry repeats the same conversion in four places —
createProjectionMapPart(~line 245),createContourPolygons(~line 304),createContourLabels, andcreatePickPointVisDrawable(~line 552):cvf::Vec3d globalVertex = localVertex + contourMapGrid.origin3d(); cvf::Vec3d displayVertex = displayCoordTransform->transformToDisplayCoord( globalVertex );Introduce an elevation provider so the z component can be replaced without touching geometry generation.
ApplicationLibCode/ModelVisualization/RivContourMapElevationProvider.{h,cpp}with an abstract provider and two implementations:RivContourMapProjectionPartMgrbehind a private helper:elevationProvider == nullptrit must return exactly today's value (+ origin3d()) and nevernullopt, so existing 2D contour map views are byte-for-byte unchanged.const RivContourMapElevationProvider* elevationProvider = nullptrparameter toappendProjectionToModelandappendContourLinesToModel. Existing call sites inRimEclipseContourMapView.cppandRimGeoMechContourMapView.cppneed no edit.createContourPolygons: whentoDisplayCoordreturnsnulloptfor either end of a segment, skip that segment. Dropping segments naturally splits a draped polyline wherever the grid is not visible below it — the same gap handlingRivSeismicSectionPartMgr::projectPolyLineOntoSurfaceuses.RivContourMapProjectionPartMgr.cpp:174(and:92) the return value ofcaf::MeshEffectGenerator::createAndConfigurePolygonOffsetRenderState( caf::PO_1 )is discarded and never assigned to the effect, so contour lines get no polygon offset at all. In the 2D view the lines are coplanar with the map so nothing shows; draped onto grid geometry they will z-fight badly. Assign the render state to an un-cached effect (generateUnCachedEffect(), otherwise the shared cached effect is polluted), using the recipe already established inRivSurfaceIntersectionCurveTools::createCurvePart(factor = -5,units = -1000). This is required for the feature, not a drive-by cleanup.2. Top-elevation lookup over the contour map grid
Nothing in the repo does "drape onto grid topography" today (
grep -i drapereturns nothing), andRigMainGridhas notopZAtXY()-style helper. Rather than ray-casting per polygon vertex, precompute a raster once over the contour map grid's vertices and bilinearly interpolate — the same shape asRigContourMapProjection::interpolateValue. The vertex count is the same order as the map itself (a 100×100 map is ~10k rays, computed once per display model rebuild).ApplicationLibCode/ReservoirDataModel/ContourMap/RigContourMapTopography.{h,cpp}:RigContourMapCalculator.cpp:450: build a thin verticalcvf::BoundingBoxat the vertex x/y spanning the grid's z range →RigMainGrid::findIntersectingCells( bbox )→ for each cell set incellVisibility,RigHexIntersectionTools::lineHexCellIntersectionwith a vertical segment top→bottom → keep the maximum hit z. Use#pragma omp parallel forover vertices, matching the surrounding contour map code.elevationAtLocalPos, returningnulloptwhen any contributing vertex is undefined.cellVisibilityis the host view'sRimGridView::currentTotalCellVisibility(), so the drape follows the 3D view's cell filters and property filters — this is what "project onto the visible geometry" means.3. The in-view wrapper
Add
ApplicationLibCode/ProjectDataModel/ContourMap/RimContourMapInView.{h,cpp}, deriving fromRimCheckableNamedObject:caf::PdmPtrField<RimEclipseContourMapView*> m_contourMapViewcaf::PdmProxyValueField<QString> m_nameProxynameField()uiHiddencaf::PdmField<caf::AppEnum<MapPosition>> m_mapPositionTOP_OF_CASEcaf::PdmField<double> m_depthOffsetcaf::PdmField<double> m_userDefinedDepthz = -depth), asRimPolygonAppearancedoes withm_polygonPlaneDepthcaf::PdmField<bool> m_showMapSurfacecaf::PdmField<bool> m_showContourLinescaf::PdmField<bool> m_projectLinesOnGeometryNon-PDM members:
cvf::ref<RivContourMapProjectionPartMgr> m_partMgr(lazily created, exactly asRimSurfaceInView::surfacePartMgr()does) and a cachedstd::shared_ptr<RigContourMapTopography>cleared byclearGeometry().Implement
appendPartsToModel( cvf::ModelBasicList*, const caf::DisplayCoordTransform*, const cvf::Camera*, int hostTimeStep ):isChecked().auto* proj = m_contourMapView->contourMapProjection();thenproj->generateResultsIfNecessary( timeStep ); proj->generateGeometryIfNecessary();— clamptimeStepto the source case's time step count, since the host view and the contour map's case need not have the same number of steps.RivContourMapFlatElevationfrommapElevation()and callappendProjectionToModel(...)whenm_showMapSurface.RivContourMapTopographyElevationand callappendContourLinesToModel(..., showContourLines = m_showContourLines, showContourLabels = false, ...). PassingshowContourLabels = falsealready short-circuitscreateContourLabels(RivContourMapProjectionPartMgr.cpp:149).Implement
double mapElevation() const:TOP_OF_CASE→proj->mapGrid()->expandedBoundingBox().max().z()BOTTOM_OF_CASE→proj->mapGrid()->origin3d().z()(today's 2D behaviour)USER_DEFINED_DEPTH→-m_userDefinedDepth()m_depthOffset()is added in all three cases.Implement legend forwarding:
legendConfig()returnsm_contourMapView->contourMapProjection()->legendConfig(), andupdateLegendRangesTextAndVisibility( RiuViewer*, bool )calls the source projection'supdateLegend()(which sets ranges and title) thenaddColorLegendToBottomLeftCorner( legendConfig()->titledOverlayFrame(), ... ), mirroringRimSurfaceInView::updateLegendRangesTextAndVisibility(RimSurfaceInView.cpp:269).Implement
fieldChangedByUi:clearGeometry()form_projectLinesOnGeometry(invalidates the topography cache), thenfirstAncestorOfType<Rim3dView>()->scheduleCreateDisplayModelAndRedraw().4. The in-view collection
The master collection
RimEclipseContourMapViewCollectionis a flatcaf::PdmObjectCollection<RimEclipseContourMapView>, not acaf::PdmNestedCollection, so the CRTP templateRimNestedMirrorCollectionInView(used byRimPolygonInViewCollection) does not apply. Model the sync on the flat half ofRimSurfaceInViewCollection::syncSurfacesWithView().ApplicationLibCode/ProjectDataModel/ContourMap/RimContourMapInViewCollection.{h,cpp}, deriving fromRimCheckableNamedObject:updateFromContourMapCollection(): orphan-sweep children whosePdmPtrFieldhas been auto-nulled by PDM, find-or-create a wrapper per source view, thenclearWithoutDelete()and push back in source order. Every new wrapper starts unchecked.5. Wiring into the views
ApplicationLibCode/Application/RiaDefines.h:269:RimGridView.{h,cpp}: addcaf::PdmChildField<RimContourMapInViewCollection*> m_contourMapInViewCollectionplus accessor, created eagerly in the constructor next tom_polygonInViewCollection(RimGridView.cpp:106). HandleItemIn3dView::CONTOUR_MAPinupdateViewTreeItems(RimGridView.cpp:533) by callingupdateFromContourMapCollection().RimEclipseView.cpp— scene assembly inonUpdateDisplayModelForCurrentTimeStep(), using the per-frame named-model pattern fromRimEclipseContourMapView.cpp:333(not a static viz model, because the data is time-step dependent):RimEclipseView.cpp— tree and legends:uiTreeOrdering.add( contourMapInViewCollection() )indefineUiTreeOrdering(~line 2141); append the collection's legend configs inlegendConfigs()(~line 2536); callupdateLegendRangesTextAndVisibility(...)inonUpdateLegends()(~line 1674) when checked.RimEclipseContourMapView.cpp: suppress the collection inside contour map views themselves (they derive fromRimEclipseView), the same waysurfaceInViewCollection()returnsnullptrthere (RimEclipseContourMapView.cpp:641) — don't add it to the tree and skip the append. Otherwise every contour map view would offer to render every other contour map.6. Change notification
RimEclipseContourMapViewCollection.cpp: afteraddView,removeChildand inonChildDeleted, broadcast to all views, followingRimPolygonCollection::updateViewTreeItems()(RimPolygonCollection.cpp:203):RicNewContourMapViewFeature.cpp: trigger the same broadcast after creating a map, so it appears in already-open 3D views without a reload.7. Build files
Headers are not listed in this project's cmake fragments — only
.cppfiles.ApplicationLibCode/ProjectDataModel/ContourMap/CMakeLists_files.cmake— addRimContourMapInView.cpp,RimContourMapInViewCollection.cppApplicationLibCode/ReservoirDataModel/ContourMap/CMakeLists_files.cmake— addRigContourMapTopography.cppApplicationLibCode/ModelVisualization/CMakeLists_files.cmake— addRivContourMapElevationProvider.cppCopyright (C) 2026- Equinor ASAheader (current year, perdocs/agents/coding-style.md)8. Verification
New Contour Mapfrom a 3D view) and confirm the 2D view is visually unchanged. This validates thetoDisplayCoordrefactor and the polygon offset fix.Contour Mapsappears in the tree with the map listed and unchecked. Check it — the coloured plane renders above the grid (TOP_OF_CASE) with contour lines, and its legend appears in the bottom-left corner.Map PositionthroughBottom of CaseandUser Defined Depth, and varyDepth Offset. The plane moves accordingly.Show Map SurfaceandShow Contour Linesindependently.Project Lines on Geometry. Lines follow the grid topography and are cut where no cell is visible. Apply a cell filter or property filter in the 3D view and confirm the drape follows the new visibility and does not z-fight.Files touched
New (8 files)
ProjectDataModel/ContourMap/RimContourMapInView.{h,cpp}ProjectDataModel/ContourMap/RimContourMapInViewCollection.{h,cpp}ReservoirDataModel/ContourMap/RigContourMapTopography.{h,cpp}ModelVisualization/RivContourMapElevationProvider.{h,cpp}Modified (~9 files)
ModelVisualization/RivContourMapProjectionPartMgr.{h,cpp},ProjectDataModel/RimGridView.{h,cpp},ProjectDataModel/RimEclipseView.cpp,ProjectDataModel/ContourMap/RimEclipseContourMapView.cpp,ProjectDataModel/ContourMap/RimEclipseContourMapViewCollection.cpp,Commands/RicNewContourMapViewFeature.cpp,Application/RiaDefines.h, plus 3CMakeLists_files.cmake.Known limitations (documented, not fixed here)
onViewNavigationChanged()hook inRimEclipseViewto stay correct while rotating.m_currentResultTimestep) will recompute on each redraw. Correct, but it costs time; worth revisiting if it proves annoying.Links
Issue
Contour map implementation (to reuse)
RivContourMapProjectionPartMgr.h— already decoupled from the projection object; takes vertices, grid, background colour and scalar mapper as argumentsRimContourMapProjection.h—generateResultsIfNecessary,generateGeometryIfNecessary,trianglesWithVertexValues,contourPolygons,mapGridRimEclipseContourMapView.cpp—updateGeometry()and the threeappend*ToModel()methods are the template for scene assemblyRigContourMapGrid.h—origin3d(),expandedBoundingBox(),generateVertices()(local,z = 0)In-view collection pattern (to follow)
RimSurfaceInViewCollection.cpp— hand-rolled flat + nested sync, legend handlingRimPolygonInViewCollection.h— the modern CRTP variant (not directly applicable here, the master collection is flat)RimNestedMirrorCollectionInView.h— the CRTP template and its documented contractDraping / z-fighting prior art
RivSeismicSectionPartMgr.cpp—projectPolyLineOntoSurface, the only per-point projection in the repoRivSurfaceIntersectionCurveTools.cpp— the canonical polygon-offset recipe for lines on a surfaceRigHexIntersectionTools.h—lineHexCellIntersectionRicCreateContourMapPolygonTools.cpp— existing local-to-domain conversion usingtopDepthBoundingBox()Project conventions
docs/agents/coding-style.mddocs/agents/build.md