FEM: Add index over frames visualizations
This commit is contained in:
@@ -116,6 +116,8 @@ class Extractor(base_fempythonobject.BaseFemPythonObject):
|
||||
return ["X", "Y"]
|
||||
case 3:
|
||||
return ["X", "Y", "Z"]
|
||||
case 6:
|
||||
return ["XX", "YY", "ZZ", "XY", "XZ", "YZ"]
|
||||
case _:
|
||||
return ["Not a vector"]
|
||||
|
||||
@@ -217,11 +219,13 @@ class Extractor1D(Extractor):
|
||||
component_array.SetName(array.GetName())
|
||||
table.AddColumn(component_array)
|
||||
|
||||
def _x_array_from_dataset(self, obj, dataset):
|
||||
def _x_array_from_dataset(self, obj, dataset, copy=True):
|
||||
# extracts the relevant array from the dataset and returns a copy
|
||||
# indices = None uses all indices, otherwise the values in this list
|
||||
|
||||
match obj.XField:
|
||||
case "Index":
|
||||
# index needs always to be build, ignore copy argument
|
||||
num = dataset.GetPoints().GetNumberOfPoints()
|
||||
array = vtkIntArray()
|
||||
array.SetNumberOfTuples(num)
|
||||
@@ -230,15 +234,22 @@ class Extractor1D(Extractor):
|
||||
array.SetValue(i,i)
|
||||
|
||||
case "Position":
|
||||
|
||||
orig_array = dataset.GetPoints().GetData()
|
||||
array = vtkDoubleArray()
|
||||
array.DeepCopy(orig_array)
|
||||
if copy:
|
||||
array = vtkDoubleArray()
|
||||
array.DeepCopy(orig_array)
|
||||
else:
|
||||
array = orig_array
|
||||
|
||||
case _:
|
||||
point_data = dataset.GetPointData()
|
||||
orig_array = point_data.GetAbstractArray(obj.XField)
|
||||
array = vtkDoubleArray()
|
||||
array.DeepCopy(orig_array)
|
||||
if copy:
|
||||
array = vtkDoubleArray()
|
||||
array.DeepCopy(orig_array)
|
||||
else:
|
||||
array = orig_array
|
||||
|
||||
return array
|
||||
|
||||
@@ -343,28 +354,29 @@ class Extractor2D(Extractor1D):
|
||||
component_array.SetName(array.GetName())
|
||||
table.AddColumn(component_array)
|
||||
|
||||
def _y_array_from_dataset(self, obj, dataset):
|
||||
def _y_array_from_dataset(self, obj, dataset, copy=True):
|
||||
# extracts the relevant array from the dataset and returns a copy
|
||||
# indices = None uses all indices, otherwise the values in this list
|
||||
|
||||
match obj.YField:
|
||||
case "Index":
|
||||
num = dataset.GetPoints().GetNumberOfPoints()
|
||||
array = vtkIntArray()
|
||||
array.SetNumberOfTuples(num)
|
||||
array.SetNumberOfComponents(1)
|
||||
for i in range(num):
|
||||
array.SetValue(i,i)
|
||||
|
||||
case "Position":
|
||||
|
||||
orig_array = dataset.GetPoints().GetData()
|
||||
array = vtkDoubleArray()
|
||||
array.DeepCopy(orig_array)
|
||||
if copy:
|
||||
array = vtkDoubleArray()
|
||||
array.DeepCopy(orig_array)
|
||||
else:
|
||||
array = orig_array
|
||||
|
||||
case _:
|
||||
point_data = dataset.GetPointData()
|
||||
orig_array = point_data.GetAbstractArray(obj.YField)
|
||||
array = vtkDoubleArray()
|
||||
array.DeepCopy(orig_array)
|
||||
|
||||
if copy:
|
||||
array = vtkDoubleArray()
|
||||
array.DeepCopy(orig_array)
|
||||
else:
|
||||
array = orig_array
|
||||
|
||||
return array
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ from . import base_fempostextractors
|
||||
from . import base_fempythonobject
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
|
||||
from vtkmodules.vtkCommonCore import vtkDoubleArray
|
||||
from vtkmodules.vtkCommonDataModel import vtkTable
|
||||
from vtkmodules.vtkCommonExecutionModel import vtkStreamingDemandDrivenPipeline
|
||||
|
||||
@@ -108,7 +109,7 @@ class PostFieldData1D(base_fempostextractors.Extractor1D):
|
||||
obj.Table = table
|
||||
|
||||
|
||||
class PostIndexData1D(base_fempostextractors.Extractor1D):
|
||||
class PostIndexOverFrames1D(base_fempostextractors.Extractor1D):
|
||||
"""
|
||||
A post processing extraction of one dimensional index data
|
||||
"""
|
||||
@@ -119,19 +120,67 @@ class PostIndexData1D(base_fempostextractors.Extractor1D):
|
||||
super().__init__(obj)
|
||||
|
||||
def _get_properties(self):
|
||||
prop =[ _PropHelper(
|
||||
type="App::PropertyBool",
|
||||
name="ExtractFrames",
|
||||
group="Multiframe",
|
||||
doc="Specify if the data at the index should be extracted for each frame",
|
||||
value=False,
|
||||
),
|
||||
_PropHelper(
|
||||
prop =[_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
name="XIndex",
|
||||
name="Index",
|
||||
group="X Data",
|
||||
doc="Specify for which point index the data should be extracted",
|
||||
doc="Specify for which index the data should be extracted",
|
||||
value=0,
|
||||
),
|
||||
]
|
||||
return super()._get_properties() + prop
|
||||
|
||||
def execute(self, obj):
|
||||
|
||||
# on execution we populate the vtk table
|
||||
table = vtkTable()
|
||||
|
||||
if not obj.Source:
|
||||
obj.Table = table
|
||||
return
|
||||
|
||||
dataset = obj.Source.getDataSet()
|
||||
if not dataset:
|
||||
obj.Table = table
|
||||
return
|
||||
|
||||
# check if we have timesteps (required!)
|
||||
abort = True
|
||||
info = obj.Source.getOutputAlgorithm().GetOutputInformation(0)
|
||||
if info.Has(vtkStreamingDemandDrivenPipeline.TIME_STEPS()):
|
||||
timesteps = info.Get(vtkStreamingDemandDrivenPipeline.TIME_STEPS())
|
||||
if len(timesteps) > 1:
|
||||
abort = False
|
||||
|
||||
if abort:
|
||||
FreeCAD.Console.PrintWarning("Not sufficient frames available in data, cannot extract data")
|
||||
obj.Table = table
|
||||
return
|
||||
|
||||
algo = obj.Source.getOutputAlgorithm()
|
||||
setup = False
|
||||
frame_array = vtkDoubleArray()
|
||||
|
||||
idx = obj.Index
|
||||
for i, timestep in enumerate(timesteps):
|
||||
|
||||
algo.UpdateTimeStep(timestep)
|
||||
dataset = algo.GetOutputDataObject(0)
|
||||
array = self._x_array_from_dataset(obj, dataset, copy=False)
|
||||
|
||||
if not setup:
|
||||
frame_array.SetNumberOfComponents(array.GetNumberOfComponents())
|
||||
frame_array.SetNumberOfTuples(len(timesteps))
|
||||
setup = True
|
||||
|
||||
frame_array.SetTuple(i, idx, array)
|
||||
|
||||
if frame_array.GetNumberOfComponents() > 1:
|
||||
frame_array.SetName(f"{obj.XField} ({obj.XComponent})")
|
||||
else:
|
||||
frame_array.SetName(f"{obj.XField}")
|
||||
|
||||
self._x_array_component_to_table(obj, frame_array, table)
|
||||
|
||||
# set the final table
|
||||
obj.Table = table
|
||||
|
||||
@@ -33,6 +33,7 @@ from . import base_fempostextractors
|
||||
from . import base_fempythonobject
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
|
||||
from vtkmodules.vtkCommonCore import vtkDoubleArray
|
||||
from vtkmodules.vtkCommonDataModel import vtkTable
|
||||
from vtkmodules.vtkCommonExecutionModel import vtkStreamingDemandDrivenPipeline
|
||||
|
||||
@@ -124,9 +125,9 @@ class PostFieldData2D(base_fempostextractors.Extractor2D):
|
||||
obj.Table = table
|
||||
|
||||
|
||||
class PostIndexData2D(base_fempostextractors.Extractor2D):
|
||||
class PostIndexOverFrames2D(base_fempostextractors.Extractor2D):
|
||||
"""
|
||||
A post processing extraction of one dimensional index data
|
||||
A post processing extraction for two dimensional data with X always being the frames
|
||||
"""
|
||||
|
||||
ExtractionType = "Index"
|
||||
@@ -135,19 +136,83 @@ class PostIndexData2D(base_fempostextractors.Extractor2D):
|
||||
super().__init__(obj)
|
||||
|
||||
def _get_properties(self):
|
||||
prop =[ _PropHelper(
|
||||
type="App::PropertyBool",
|
||||
name="ExtractFrames",
|
||||
group="Multiframe",
|
||||
doc="Specify if the data at the index should be extracted for each frame",
|
||||
value=False,
|
||||
),
|
||||
_PropHelper(
|
||||
prop =[_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
name="XIndex",
|
||||
group="X Data",
|
||||
name="Index",
|
||||
group="Data",
|
||||
doc="Specify for which point index the data should be extracted",
|
||||
value=0,
|
||||
),
|
||||
]
|
||||
return super()._get_properties() + prop
|
||||
|
||||
def _setup_x_component_property(self, obj, point_data):
|
||||
# override to only allow "Frames" as X data
|
||||
obj.XComponent = ["Not a vector"]
|
||||
|
||||
def _setup_x_properties(self, obj, dataset):
|
||||
# override to only allow "Frames" as X data
|
||||
obj.XField = ["Frames"]
|
||||
|
||||
def execute(self, obj):
|
||||
|
||||
# on execution we populate the vtk table
|
||||
table = vtkTable()
|
||||
|
||||
if not obj.Source:
|
||||
obj.Table = table
|
||||
return
|
||||
|
||||
dataset = obj.Source.getDataSet()
|
||||
if not dataset:
|
||||
obj.Table = table
|
||||
return
|
||||
|
||||
# check if we have timesteps (required!)
|
||||
abort = True
|
||||
info = obj.Source.getOutputAlgorithm().GetOutputInformation(0)
|
||||
if info.Has(vtkStreamingDemandDrivenPipeline.TIME_STEPS()):
|
||||
timesteps = info.Get(vtkStreamingDemandDrivenPipeline.TIME_STEPS())
|
||||
if len(timesteps) > 1:
|
||||
abort = False
|
||||
|
||||
if abort:
|
||||
FreeCAD.Console.PrintWarning("Not sufficient frames available in data, cannot extract data")
|
||||
obj.Table = table
|
||||
return
|
||||
|
||||
algo = obj.Source.getOutputAlgorithm()
|
||||
|
||||
frame_x_array = vtkDoubleArray()
|
||||
frame_x_array.SetNumberOfTuples(len(timesteps))
|
||||
frame_x_array.SetNumberOfComponents(1)
|
||||
|
||||
|
||||
frame_y_array = vtkDoubleArray()
|
||||
idx = obj.Index
|
||||
setup = False
|
||||
for i, timestep in enumerate(timesteps):
|
||||
|
||||
frame_x_array.SetTuple1(i, timestep)
|
||||
|
||||
algo.UpdateTimeStep(timestep)
|
||||
dataset = algo.GetOutputDataObject(0)
|
||||
array = self._y_array_from_dataset(obj, dataset, copy=False)
|
||||
if not setup:
|
||||
frame_y_array.SetNumberOfComponents(array.GetNumberOfComponents())
|
||||
frame_y_array.SetNumberOfTuples(len(timesteps))
|
||||
setup = True
|
||||
|
||||
frame_y_array.SetTuple(i, idx, array)
|
||||
|
||||
frame_x_array.SetName("Frames")
|
||||
if frame_y_array.GetNumberOfComponents() > 1:
|
||||
frame_y_array.SetName(f"{obj.YField} ({obj.YComponent})")
|
||||
else:
|
||||
frame_y_array.SetName(obj.YField)
|
||||
|
||||
table.AddColumn(frame_x_array)
|
||||
self._y_array_component_to_table(obj, frame_y_array, table)
|
||||
|
||||
# set the final table
|
||||
obj.Table = table
|
||||
|
||||
@@ -57,6 +57,14 @@ post_visualization.register_extractor("Histogram",
|
||||
"makePostHistogramFieldData")
|
||||
|
||||
|
||||
post_visualization.register_extractor("Histogram",
|
||||
"HistogramIndexOverFrames",
|
||||
":/icons/FEM_PostIndex.svg",
|
||||
"1D",
|
||||
"Index",
|
||||
"ObjectsFem",
|
||||
"makePostHistogramIndexOverFrames")
|
||||
|
||||
# Implementation
|
||||
# ##############
|
||||
|
||||
@@ -77,7 +85,11 @@ class PostHistogramFieldData(post_extract1D.PostFieldData1D):
|
||||
"""
|
||||
VisualizationType = "Histogram"
|
||||
|
||||
|
||||
class PostHistogramIndexOverFrames(post_extract1D.PostIndexOverFrames1D):
|
||||
"""
|
||||
A 1D index extraction for histogram.
|
||||
"""
|
||||
VisualizationType = "Histogram"
|
||||
|
||||
|
||||
class PostHistogram(base_fempostvisualizations.PostVisualization):
|
||||
|
||||
@@ -56,6 +56,14 @@ post_visualization.register_extractor("Lineplot",
|
||||
"ObjectsFem",
|
||||
"makePostLineplotFieldData")
|
||||
|
||||
post_visualization.register_extractor("Lineplot",
|
||||
"LineplotIndexOverFrames",
|
||||
":/icons/FEM_PostIndex.svg",
|
||||
"2D",
|
||||
"Index",
|
||||
"ObjectsFem",
|
||||
"makePostLineplotIndexOverFrames")
|
||||
|
||||
|
||||
# Implementation
|
||||
# ##############
|
||||
@@ -77,6 +85,12 @@ class PostLineplotFieldData(post_extract2D.PostFieldData2D):
|
||||
"""
|
||||
VisualizationType = "Lineplot"
|
||||
|
||||
class PostLineplotIndexOverFrames(post_extract2D.PostIndexOverFrames2D):
|
||||
"""
|
||||
A 2D index extraction for lineplot.
|
||||
"""
|
||||
VisualizationType = "Lineplot"
|
||||
|
||||
|
||||
|
||||
class PostLineplot(base_fempostvisualizations.PostVisualization):
|
||||
|
||||
Reference in New Issue
Block a user