@@ -23,6 +23,7 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <cmath>
|
||||
#include <Python.h>
|
||||
#include <vtkAppendFilter.h>
|
||||
#include <vtkDataSetReader.h>
|
||||
@@ -313,10 +314,23 @@ void FemPostPipeline::read(std::vector<Base::FileInfo>& files,
|
||||
std::string& frame_type)
|
||||
{
|
||||
if (files.size() != values.size()) {
|
||||
Base::Console().Error("Result files and frame values have different length.\n");
|
||||
return;
|
||||
throw Base::ValueError("Result files and frame values have different length");
|
||||
}
|
||||
|
||||
// make sure we do not have invalid values
|
||||
for (auto& value : values) {
|
||||
if (!std::isfinite(value)) {
|
||||
throw Base::ValueError("Values need to be finite");
|
||||
}
|
||||
}
|
||||
|
||||
// ensure no double values for frames
|
||||
std::set<double> value_set(values.begin(), values.end());
|
||||
if (value_set.size() != values.size()) {
|
||||
throw Base::ValueError("Values need to be unique");
|
||||
}
|
||||
|
||||
|
||||
// setup the time information for the multiblock
|
||||
vtkStringArray* TimeInfo = vtkStringArray::New();
|
||||
TimeInfo->SetName("TimeInfo");
|
||||
@@ -650,8 +664,20 @@ void FemPostPipeline::load(std::vector<FemResultObject*>& res,
|
||||
{
|
||||
|
||||
if (res.size() != values.size()) {
|
||||
Base::Console().Error("Result values and frame values have different length.\n");
|
||||
return;
|
||||
throw Base::ValueError("Result values and frame values have different length");
|
||||
}
|
||||
|
||||
// make sure we do not have invalid values
|
||||
for (auto& value : values) {
|
||||
if (!std::isfinite(value)) {
|
||||
throw Base::ValueError("Values need to be finite");
|
||||
}
|
||||
}
|
||||
|
||||
// ensure no double values for frames
|
||||
std::set<double> value_set(values.begin(), values.end());
|
||||
if (value_set.size() != values.size()) {
|
||||
throw Base::ValueError("Values need to be unique");
|
||||
}
|
||||
|
||||
// setup the time information for the multiblock
|
||||
@@ -664,8 +690,7 @@ void FemPostPipeline::load(std::vector<FemResultObject*>& res,
|
||||
for (ulong i = 0; i < res.size(); i++) {
|
||||
|
||||
if (!res[i]->Mesh.getValue()->isDerivedFrom<FemMeshObject>()) {
|
||||
Base::Console().Error("Result mesh object is not derived from Fem::FemMeshObject.\n");
|
||||
return;
|
||||
throw Base::ValueError("Result mesh object is not derived from Fem::FemMeshObject");
|
||||
}
|
||||
|
||||
// first copy the mesh over
|
||||
|
||||
@@ -172,7 +172,8 @@ PyObject* FemPostPipelinePy::load(PyObject* args)
|
||||
|
||||
std::string error = std::string(
|
||||
"Result and value must be list of ResultObject and number respectively.");
|
||||
throw Base::TypeError(error);
|
||||
PyErr_SetString(PyExc_TypeError, error.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// extract the result objects
|
||||
@@ -186,11 +187,15 @@ PyObject* FemPostPipelinePy::load(PyObject* args)
|
||||
if (!PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) {
|
||||
std::string error =
|
||||
std::string("type in result list must be 'ResultObject', not ");
|
||||
throw Base::TypeError(error);
|
||||
PyErr_SetString(PyExc_TypeError, error.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
auto obj = static_cast<DocumentObjectPy*>(*item)->getDocumentObjectPtr();
|
||||
if (!obj->isDerivedFrom<FemResultObject>()) {
|
||||
throw Base::TypeError("object is not a result object");
|
||||
std::string error =
|
||||
std::string("type in result list must be 'ResultObject', not ");
|
||||
PyErr_SetString(PyExc_TypeError, error.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
results[i] = static_cast<FemResultObject*>(obj);
|
||||
}
|
||||
@@ -202,12 +207,12 @@ PyObject* FemPostPipelinePy::load(PyObject* args)
|
||||
values.resize(size);
|
||||
|
||||
for (Py::Sequence::size_type i = 0; i < size; i++) {
|
||||
Py::Object item = values_list[i];
|
||||
if (!PyFloat_Check(*item)) {
|
||||
std::string error = std::string("Values must be float");
|
||||
throw Base::TypeError(error);
|
||||
Py::Object value = values_list[i];
|
||||
if (!value.isNumeric()) {
|
||||
PyErr_SetString(PyExc_TypeError, "Values must be numbers");
|
||||
return nullptr;
|
||||
}
|
||||
values[i] = PyFloat_AsDouble(*item);
|
||||
values[i] = Py::Float(value).as_double();
|
||||
}
|
||||
|
||||
// extract the unit
|
||||
@@ -223,7 +228,8 @@ PyObject* FemPostPipelinePy::load(PyObject* args)
|
||||
else {
|
||||
std::string error = std::string(
|
||||
"Multistep load requires 4 arguments: ResultList, ValueList, unit, type");
|
||||
throw Base::TypeError(error);
|
||||
PyErr_SetString(PyExc_ValueError, error.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
@@ -211,7 +211,7 @@ void PropertyPostDataObject::createDataObjectByExternalType(vtkSmartPointer<vtkD
|
||||
m_dataObject = vtkSmartPointer<vtkMultiPieceDataSet>::New();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
throw Base::TypeError("Unsupported VTK data type");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -432,7 +432,7 @@ void PropertyPostDataObject::RestoreDocFile(Base::Reader& reader)
|
||||
|
||||
// TODO: read in of composite data structures need to be coded,
|
||||
// including replace of "GetOutputAsDataSet()"
|
||||
vtkSmartPointer<vtkXMLReader> xmlReader;
|
||||
vtkSmartPointer<vtkXMLReader> xmlReader = nullptr;
|
||||
if (extension == "vtp") {
|
||||
xmlReader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
|
||||
}
|
||||
@@ -489,31 +489,39 @@ void PropertyPostDataObject::RestoreDocFile(Base::Reader& reader)
|
||||
xmlReader = vtkSmartPointer<vtkXMLMultiBlockDataReader>::New();
|
||||
}
|
||||
|
||||
xmlReader->SetFileName(fi.filePath().c_str());
|
||||
xmlReader->Update();
|
||||
if (xmlReader) {
|
||||
xmlReader->SetFileName(fi.filePath().c_str());
|
||||
xmlReader->Update();
|
||||
|
||||
if (!xmlReader->GetOutputDataObject(0)) {
|
||||
// Note: Do NOT throw an exception here because if the tmp. created file could
|
||||
// not be read it's NOT an indication for an invalid input stream 'reader'.
|
||||
// We only print an error message but continue reading the next files from the
|
||||
// stream...
|
||||
App::PropertyContainer* father = this->getContainer();
|
||||
if (father && father->isDerivedFrom<App::DocumentObject>()) {
|
||||
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
|
||||
Base::Console().Error("Dataset file '%s' with data of '%s' seems to be empty\n",
|
||||
fi.filePath().c_str(),
|
||||
obj->Label.getValue());
|
||||
if (!xmlReader->GetOutputDataObject(0)) {
|
||||
// Note: Do NOT throw an exception here because if the tmp. created file could
|
||||
// not be read it's NOT an indication for an invalid input stream 'reader'.
|
||||
// We only print an error message but continue reading the next files from the
|
||||
// stream...
|
||||
App::PropertyContainer* father = this->getContainer();
|
||||
if (father && father->isDerivedFrom<App::DocumentObject>()) {
|
||||
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
|
||||
Base::Console().Error("Dataset file '%s' with data of '%s' seems to be empty\n",
|
||||
fi.filePath().c_str(),
|
||||
obj->Label.getValue());
|
||||
}
|
||||
else {
|
||||
Base::Console().Warning("Loaded Dataset file '%s' seems to be empty\n",
|
||||
fi.filePath().c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Warning("Loaded Dataset file '%s' seems to be empty\n",
|
||||
fi.filePath().c_str());
|
||||
aboutToSetValue();
|
||||
createDataObjectByExternalType(xmlReader->GetOutputDataObject(0));
|
||||
m_dataObject->DeepCopy(xmlReader->GetOutputDataObject(0));
|
||||
hasSetValue();
|
||||
}
|
||||
}
|
||||
else {
|
||||
aboutToSetValue();
|
||||
createDataObjectByExternalType(xmlReader->GetOutputDataObject(0));
|
||||
m_dataObject->DeepCopy(xmlReader->GetOutputDataObject(0));
|
||||
hasSetValue();
|
||||
Base::Console().Error(
|
||||
"Dataset file '%s' is of unsupported type: %s. Data not loaded.\n",
|
||||
fi.filePath().c_str(),
|
||||
extension);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -316,9 +316,11 @@ void TaskDlgPost::appendBox(TaskPostBox* box)
|
||||
|
||||
void TaskDlgPost::open()
|
||||
{
|
||||
// a transaction is already open at creation time of the pad
|
||||
QString msg = QObject::tr("Edit post processing object");
|
||||
Gui::Command::openCommand(msg.toUtf8().constData());
|
||||
// only open a new command if none is pending (e.g. if the object was newly created)
|
||||
if (!Gui::Command::hasPendingCommand()) {
|
||||
auto text = std::string("Edit ") + m_view->getObject()->Label.getValue();
|
||||
Gui::Command::openCommand(text.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void TaskDlgPost::clicked(int button)
|
||||
|
||||
@@ -32,6 +32,7 @@ __url__ = "https://www.freecad.org"
|
||||
# \brief FreeCAD Calculix FRD Reader for FEM workbench
|
||||
|
||||
import os
|
||||
import math
|
||||
|
||||
import FreeCAD
|
||||
from FreeCAD import Console
|
||||
@@ -133,6 +134,8 @@ def importFrd(filename, analysis=None, result_name_prefix="", result_analysis_ty
|
||||
else:
|
||||
eigenmode_number = 0
|
||||
step_time = result_set["time"]
|
||||
if not math.isfinite(step_time):
|
||||
step_time = 0
|
||||
step_time = round(step_time, 2)
|
||||
if eigenmode_number > 0:
|
||||
results_name = "{}EigenMode_{}_Results".format(
|
||||
@@ -252,6 +255,7 @@ def importFrd(filename, analysis=None, result_name_prefix="", result_analysis_ty
|
||||
elif result_analysis_type == "check":
|
||||
results_name = f"{result_name_prefix}Check"
|
||||
res_obj = make_result_mesh(results_name)
|
||||
setupPipeline(doc, analysis, results_name, [res_obj])
|
||||
if analysis:
|
||||
analysis.addObject(res_obj)
|
||||
|
||||
@@ -276,6 +280,7 @@ def importFrd(filename, analysis=None, result_name_prefix="", result_analysis_ty
|
||||
results_name = "Results"
|
||||
res_obj = ObjectsFem.makeResultMechanical(doc, results_name)
|
||||
res_obj.Mesh = result_mesh_object
|
||||
setupPipeline(doc, analysis, results_name, [res_obj])
|
||||
# TODO, node numbers in result obj could be set
|
||||
if analysis:
|
||||
analysis.addObject(res_obj)
|
||||
|
||||
Reference in New Issue
Block a user