FreeCAD / src /Mod /Fem /femobjects /post_extract2D.py
AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
# ***************************************************************************
# * Copyright (c) 2025 Stefan Tröger <stefantroeger@gmx.net> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__title__ = "FreeCAD post extractors 2D"
__author__ = "Stefan Tröger"
__url__ = "https://www.freecad.org"
## @package post_histogram
# \ingroup FEM
# \brief Post processing plot displaying lines
import FreeCAD
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
from PySide.QtCore import QT_TRANSLATE_NOOP
class PostFieldData2D(base_fempostextractors.Extractor2D):
"""
A post processing extraction of two dimensional field data
"""
ExtractionType = "Field"
def __init__(self, obj):
super().__init__(obj)
def _get_properties(self):
prop = [
_PropHelper(
type="App::PropertyBool",
name="ExtractFrames",
group="Multiframe",
doc=QT_TRANSLATE_NOOP(
"FEM", "Specify if the field shall be extracted for every available frame"
),
value=False,
),
]
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
timesteps = []
if obj.ExtractFrames:
# check if we have timesteps
info = obj.Source.getOutputAlgorithm().GetOutputInformation(0)
if info.Has(vtkStreamingDemandDrivenPipeline.TIME_STEPS()):
timesteps = info.Get(vtkStreamingDemandDrivenPipeline.TIME_STEPS())
else:
FreeCAD.Console.PrintWarning(
'No frames available in data, ignoring "ExtractFrames" property'
)
if not timesteps:
# get the dataset and extract the correct array
xarray = self._x_array_from_dataset(obj, dataset)
if xarray.GetNumberOfComponents() > 1:
xarray.SetName(obj.XField + " (" + obj.XComponent + ")")
else:
xarray.SetName(obj.XField)
self._x_array_component_to_table(obj, xarray, table)
yarray = self._y_array_from_dataset(obj, dataset)
if yarray.GetNumberOfComponents() > 1:
yarray.SetName(obj.YField + " (" + obj.YComponent + ")")
else:
yarray.SetName(obj.YField)
self._y_array_component_to_table(obj, yarray, table)
else:
algo = obj.Source.getOutputAlgorithm()
for timestep in timesteps:
algo.UpdateTimeStep(timestep)
dataset = algo.GetOutputDataObject(0)
xarray = self._x_array_from_dataset(obj, dataset)
if xarray.GetNumberOfComponents() > 1:
xarray.SetName(f"X - {obj.XField} ({obj.XComponent}) - {timestep}")
else:
xarray.SetName(f"X - {obj.XField} - {timestep}")
self._x_array_component_to_table(obj, xarray, table)
yarray = self._y_array_from_dataset(obj, dataset)
if yarray.GetNumberOfComponents() > 1:
yarray.SetName(f"{obj.YField} ({obj.YComponent}) - {timestep}")
else:
yarray.SetName(f"{obj.YField} - {timestep}")
self._y_array_component_to_table(obj, yarray, table)
# set the final table
obj.Table = table
class PostIndexOverFrames2D(base_fempostextractors.Extractor2D):
"""
A post processing extraction for two dimensional data with X always being the frames
"""
ExtractionType = "Index"
def __init__(self, obj):
super().__init__(obj)
def _get_properties(self):
prop = [
_PropHelper(
type="App::PropertyInteger",
name="Index",
group="Data",
doc=QT_TRANSLATE_NOOP(
"FEM", "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!)
timesteps = []
info = obj.Source.getOutputAlgorithm().GetOutputInformation(0)
if info.Has(vtkStreamingDemandDrivenPipeline.TIME_STEPS()):
timesteps = info.Get(vtkStreamingDemandDrivenPipeline.TIME_STEPS())
algo = obj.Source.getOutputAlgorithm()
frame_x_array = vtkDoubleArray()
frame_y_array = vtkDoubleArray()
idx = obj.Index
if timesteps:
setup = False
frame_x_array.SetNumberOfTuples(len(timesteps))
frame_x_array.SetNumberOfComponents(1)
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)
# safeguard for invalid access
if idx < 0 or array.GetNumberOfTuples() - 1 < idx:
raise Exception(
f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}"
)
if not setup:
frame_y_array.SetNumberOfComponents(array.GetNumberOfComponents())
frame_y_array.SetNumberOfTuples(len(timesteps))
setup = True
frame_y_array.SetTuple(i, idx, array)
else:
frame_x_array.SetNumberOfTuples(1)
frame_x_array.SetNumberOfComponents(1)
frame_x_array.SetTuple1(0, 0)
algo.Update()
dataset = algo.GetOutputDataObject(0)
array = self._y_array_from_dataset(obj, dataset, copy=False)
# safeguard for invalid access
if idx < 0 or array.GetNumberOfTuples() - 1 < idx:
raise Exception(
f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}"
)
frame_y_array.SetNumberOfComponents(array.GetNumberOfComponents())
frame_y_array.SetNumberOfTuples(1)
frame_y_array.SetTuple(0, idx, array)
frame_x_array.SetName("Frames")
if frame_y_array.GetNumberOfComponents() > 1:
frame_y_array.SetName(f"{obj.YField} ({obj.YComponent}) @Idx {obj.Index}")
else:
frame_y_array.SetName(f"{obj.YField} @Idx {obj.Index}")
table.AddColumn(frame_x_array)
self._y_array_component_to_table(obj, frame_y_array, table)
# set the final table
obj.Table = table