diff --git a/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py b/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py
index 067d36f8..3c6f38aa 100644
--- a/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py
+++ b/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py
@@ -7,6 +7,7 @@
from pathlib import Path
from enum import Enum
from typing import Any, Union, cast
+from typing_extensions import Self
import numpy as np
import numpy.typing as npt
@@ -18,10 +19,12 @@
from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found]
# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py
-from typing_extensions import Self
from vtkmodules.vtkCommonCore import vtkDataArraySelection as vtkDAS
-from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector
-from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid
+from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector, vtkStringArray, vtkIntArray
+from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid, vtkMultiBlockDataSet, vtkPolyData, vtkCompositeDataSet
+from vtkmodules.vtkCommonTransforms import vtkTransform
+from vtkmodules.vtkRenderingFreeType import vtkVectorText
+from vtkmodules.vtkFiltersGeneral import vtkTransformPolyDataFilter
# Update sys.path to load all GEOS Python Package dependencies
geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent.parent
@@ -73,7 +76,7 @@
* Extract a few number of cells with the `ExtractSelection` ParaView Filter, then use the `MergeBlocks` ParaView Filter
* Select the resulting mesh in the pipeline
-* Select the filter: Filters > { FilterCategory.GENERIC_PROCESSING.value } > Plot Mohr's Circle
+* Select the filter: Filters > { FilterCategory.GEOS_POST_PROCESSING.value } > Plot Mohr's Circle
* Select the cell Ids and time steps you want
* (Optional) Set rock cohesion and/or friction angle
* Apply
@@ -89,7 +92,7 @@
@smproxy.filter( name="PVMohrCirclePlot", label="Plot Mohr's Circles" )
@smhint.xml( f"""
-
+
""" )
@smproperty.input( name="Input", port_index=0 )
@@ -104,7 +107,10 @@ def __init__( self: Self ) -> None:
Mohr's circles are plotted using a Python View.
"""
- super().__init__( nInputPorts=1, nOutputPorts=1, outputType="vtkDataObject" )
+ super().__init__( nInputPorts=1,
+ nOutputPorts=1,
+ inputType="vtkUnstructuredGrid",
+ outputType="vtkMultiBlockDataSet" )
# Create a new PythonView
self.pythonView: Any = buildNewLayoutWithPythonView()
@@ -719,9 +725,9 @@ def RequestDataObject(
outData = self.GetOutputData( outInfoVec, 0 )
assert inData is not None
- if ( outData is None ) or ( not outData.IsA( inData.GetClassName() ) ):
- outData = inData.NewInstance()
- outInfoVec.GetInformationObject( 0 ).Set( outData.DATA_OBJECT(), outData )
+ if outData is None or ( not outData.IsA( "vtkMultiBlockDataSet" ) ):
+ outData = vtkMultiBlockDataSet()
+ outInfoVec.GetInformationObject( 0 ).Set( outData.DATA_OBJECT(), outData ) # type: ignore
return super().RequestDataObject( request, inInfoVec, outInfoVec ) # type: ignore[no-any-return]
def RequestData(
@@ -774,8 +780,67 @@ def RequestData(
self.frictionAngle,
self._getUserChoices(),
)
+
Render()
+ # Cell indexes annotation
+ nbCells = inputMesh.GetNumberOfCells()
+ inputData = inputMesh.NewInstance()
+ inputData.ShallowCopy( inputMesh )
+ outputMesh: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 0 )
+
+ cellId = vtkStringArray()
+ cellId.SetName( "cellId" )
+ cellId.SetNumberOfValues( nbCells )
+
+ cellMask = vtkIntArray()
+ cellMask.SetName( "CellMask" )
+ cellMask.SetNumberOfValues( nbCells )
+
+ selected_local = set()
+ originalCellIds = inputMesh.GetCellData().GetArray( "vtkOriginalCellIds" )
+ for localCellId in range( nbCells ):
+ if str( originalCellIds.GetValue( localCellId ) ) in self.requestedCellIds:
+ selected_local.add( localCellId )
+ cellId.SetValue( localCellId, f"{ originalCellIds.GetValue( localCellId ) }" )
+ cellMask.SetValue( localCellId, 1 )
+ else:
+ cellMask.SetValue( localCellId, 0 )
+
+ inputData.GetCellData().AddArray( cellId )
+ inputData.GetCellData().AddArray( cellMask )
+
+ idBlock = 0
+ for localCellId in selected_local:
+ globalCellId = f"{ originalCellIds.GetValue( localCellId ) }"
+ text = vtkVectorText()
+ text.SetText( globalCellId )
+ text.Update()
+
+ cellBounds = inputMesh.GetCell( localCellId ).GetBounds()
+ transformFilter = vtkTransform()
+ transformFilter.Translate( cellBounds[ 1 ], cellBounds[ 3 ], cellBounds[ 5 ] )
+
+ scaleX = ( cellBounds[ 1 ] - cellBounds[ 0 ] ) / 4
+ scaleY = ( cellBounds[ 3 ] - cellBounds[ 2 ] ) / 4
+ scaleZ = ( cellBounds[ 5 ] - cellBounds[ 4 ] ) / 4
+ transformFilter.Scale( scaleX, scaleY, scaleZ )
+
+ transformFromPolyDataFilter = vtkTransformPolyDataFilter()
+ transformFromPolyDataFilter.SetTransform( transformFilter )
+ transformFromPolyDataFilter.SetInputData( text.GetOutput() )
+ transformFromPolyDataFilter.Update()
+
+ meshText = vtkPolyData()
+ meshText.ShallowCopy( transformFromPolyDataFilter.GetOutput() )
+
+ outputMesh.SetBlock( idBlock, meshText )
+ outputMesh.GetMetaData( idBlock ).Set( vtkCompositeDataSet.NAME(), f"Cell_{ globalCellId }" )
+ idBlock += 1
+
+ outputMesh.SetBlock( idBlock, inputData )
+ outputMesh.GetMetaData( idBlock ).Set( vtkCompositeDataSet.NAME(), "Input Data" )
+
except Exception as e:
self.logger.error( "Mohr circles cannot be plotted due to:" )
self.logger.error( e )
@@ -812,12 +877,21 @@ def _createMohrCirclesAtTimeStep(
def _filterMohrCircles( self: Self ) -> list[ MohrCircle ]:
"""Filter the list of all MohrCircle to get those to plot.
+ Mohr circles are sort by cell indexes first then by timesteps.
+
Returns:
list[MohrCircle]: list of MohrCircle to plot.
"""
# Circle ids to plot
circleIds: list[ str ] = self._getCircleIds()
- return [ mohrCircle for mohrCircle in self.mohrCircles if mohrCircle.getCircleId() in circleIds ]
+ mohrCircleToPlot: list[ MohrCircle ] = [ MohrCircle( "-1" ) for i in range( len( circleIds ) ) ]
+ for mohrCircle in self.mohrCircles:
+ try:
+ mohrCircleToPlot[ circleIds.index( str( mohrCircle.getCircleId() ) ) ] = mohrCircle
+ except ValueError:
+ continue
+
+ return mohrCircleToPlot
def _updateRequestedTimeSteps( self: Self ) -> None:
"""Update the requestedTimeStepsIndexes attribute from user choice."""
@@ -842,13 +916,15 @@ def _getUserChoices( self: Self ) -> dict[ str, Any ]:
def _getCircleIds( self: Self ) -> list[ str ]:
"""Get circle ids to plot.
+ This list of circle indexes is sort by cell indexes first then by timesteps
+
Returns:
list[str]: list of circle ids to plot.
"""
cellIds: list[ str ] = pvt.getArrayChoices( self.a01GetCellIdsDAS() )
timeSteps: list[ str ] = pvt.getArrayChoices( self.a02GetTimestepsToPlot() )
- return [ mcf.getMohrCircleId( cellId, timeStep ) for timeStep in timeSteps for cellId in cellIds ]
+ return [ mcf.getMohrCircleId( cellId, timeStep ) for cellId in cellIds for timeStep in timeSteps ]
def _defineCurvesAspect( self: Self ) -> None:
"""Add curve aspect parameters according to user choices."""