Fem: Change ConstraintPressure::Force property to App::PropertyForce
This commit is contained in:
@@ -42,6 +42,9 @@ ConstraintForce::ConstraintForce()
|
||||
"ConstraintForce",
|
||||
(App::PropertyType)(App::Prop_None),
|
||||
"Element giving direction of constraint");
|
||||
// RefDispl must get a global scope, see
|
||||
Direction.setScope(App::LinkScope::Global);
|
||||
|
||||
ADD_PROPERTY(Reversed, (0));
|
||||
ADD_PROPERTY_TYPE(Points,
|
||||
(Base::Vector3d()),
|
||||
@@ -53,8 +56,9 @@ ConstraintForce::ConstraintForce()
|
||||
"ConstraintForce",
|
||||
App::PropertyType(App::Prop_ReadOnly | App::Prop_Output),
|
||||
"Direction of arrows");
|
||||
naturalDirectionVector =
|
||||
Base::Vector3d(0, 0, 0); // by default use the null vector to indicate an invalid value
|
||||
|
||||
// by default use the null vector to indicate an invalid value
|
||||
naturalDirectionVector = Base::Vector3d(0, 0, 0);
|
||||
Points.setValues(std::vector<Base::Vector3d>());
|
||||
}
|
||||
|
||||
@@ -63,6 +67,21 @@ App::DocumentObjectExecReturn* ConstraintForce::execute()
|
||||
return Constraint::execute();
|
||||
}
|
||||
|
||||
void ConstraintForce::handleChangedPropertyType(Base::XMLReader& reader,
|
||||
const char* TypeName,
|
||||
App::Property* prop)
|
||||
{
|
||||
// property Force had App::PropertyFloat, was changed to App::PropertyForce
|
||||
if (prop == &Force && strcmp(TypeName, "App::PropertyFloat") == 0) {
|
||||
App::PropertyFloat ForceProperty;
|
||||
// restore the PropertyFloat to be able to set its value
|
||||
ForceProperty.Restore(reader);
|
||||
// force uses m while FreeCAD uses internally mm thus
|
||||
// e.g. "2.5" must become 2500 to result in 2.5 N
|
||||
Force.setValue(ForceProperty.getValue() * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
void ConstraintForce::onChanged(const App::Property* prop)
|
||||
{
|
||||
// Note: If we call this at the end, then the arrows are not oriented correctly initially
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
/// Constructor
|
||||
ConstraintForce();
|
||||
|
||||
App::PropertyFloat Force;
|
||||
App::PropertyForce Force;
|
||||
App::PropertyLinkSub Direction;
|
||||
App::PropertyBool Reversed;
|
||||
// Read-only (calculated values). These trigger changes in the ViewProvider
|
||||
@@ -55,6 +55,9 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void handleChangedPropertyType(Base::XMLReader& reader,
|
||||
const char* TypeName,
|
||||
App::Property* prop) override;
|
||||
void onChanged(const App::Property* prop) override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -57,35 +57,12 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce* C
|
||||
ui->setupUi(proxy);
|
||||
QMetaObject::connectSlotsByName(this);
|
||||
|
||||
// create a context menu for the listview of the references
|
||||
createDeleteAction(ui->listReferences);
|
||||
connect(deleteAction, &QAction::triggered, this, &TaskFemConstraintForce::onReferenceDeleted);
|
||||
connect(ui->spinForce,
|
||||
qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
|
||||
this,
|
||||
&TaskFemConstraintForce::onForceChanged);
|
||||
connect(ui->buttonDirection,
|
||||
&QToolButton::clicked,
|
||||
this,
|
||||
&TaskFemConstraintForce::onButtonDirection);
|
||||
connect(ui->checkReverse, &QCheckBox::toggled, this, &TaskFemConstraintForce::onCheckReverse);
|
||||
connect(ui->listReferences,
|
||||
&QListWidget::itemClicked,
|
||||
this,
|
||||
&TaskFemConstraintForce::setSelection);
|
||||
|
||||
this->groupLayout()->addWidget(proxy);
|
||||
|
||||
// Temporarily prevent unnecessary feature recomputes
|
||||
ui->spinForce->blockSignals(true);
|
||||
ui->listReferences->blockSignals(true);
|
||||
ui->buttonDirection->blockSignals(true);
|
||||
ui->checkReverse->blockSignals(true);
|
||||
|
||||
// Get the feature data
|
||||
Fem::ConstraintForce* pcConstraint =
|
||||
static_cast<Fem::ConstraintForce*>(ConstraintView->getObject());
|
||||
double f = pcConstraint->Force.getValue();
|
||||
auto force = pcConstraint->Force.getQuantityValue();
|
||||
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
|
||||
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
|
||||
std::vector<std::string> dirStrings = pcConstraint->Direction.getSubValues();
|
||||
@@ -96,9 +73,10 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce* C
|
||||
bool reversed = pcConstraint->Reversed.getValue();
|
||||
|
||||
// Fill data into dialog elements
|
||||
ui->spinForce->setUnit(pcConstraint->Force.getUnit());
|
||||
ui->spinForce->setMinimum(0);
|
||||
ui->spinForce->setMaximum(FLOAT_MAX);
|
||||
ui->spinForce->setValue(f);
|
||||
ui->spinForce->setValue(force);
|
||||
ui->listReferences->clear();
|
||||
for (std::size_t i = 0; i < Objects.size(); i++) {
|
||||
ui->listReferences->addItem(makeRefText(Objects[i], SubElements[i]));
|
||||
@@ -109,15 +87,25 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce* C
|
||||
ui->lineDirection->setText(dir.isEmpty() ? QString() : dir);
|
||||
ui->checkReverse->setChecked(reversed);
|
||||
|
||||
ui->spinForce->blockSignals(false);
|
||||
ui->listReferences->blockSignals(false);
|
||||
ui->buttonDirection->blockSignals(false);
|
||||
ui->checkReverse->blockSignals(false);
|
||||
// create a context menu for the listview of the references
|
||||
createDeleteAction(ui->listReferences);
|
||||
connect(deleteAction, &QAction::triggered, this, &TaskFemConstraintForce::onReferenceDeleted);
|
||||
connect(ui->buttonDirection,
|
||||
&QToolButton::clicked,
|
||||
this,
|
||||
&TaskFemConstraintForce::onButtonDirection);
|
||||
connect(ui->checkReverse, &QCheckBox::toggled, this, &TaskFemConstraintForce::onCheckReverse);
|
||||
connect(ui->listReferences,
|
||||
&QListWidget::itemClicked,
|
||||
this,
|
||||
&TaskFemConstraintForce::setSelection);
|
||||
|
||||
// Selection buttons
|
||||
buttonGroup->addButton(ui->btnAdd, (int)SelectionChangeModes::refAdd);
|
||||
buttonGroup->addButton(ui->btnRemove, (int)SelectionChangeModes::refRemove);
|
||||
|
||||
ui->spinForce->bind(pcConstraint->Force);
|
||||
|
||||
updateUI();
|
||||
}
|
||||
|
||||
@@ -259,13 +247,6 @@ void TaskFemConstraintForce::removeFromSelection()
|
||||
updateUI();
|
||||
}
|
||||
|
||||
void TaskFemConstraintForce::onForceChanged(double f)
|
||||
{
|
||||
Fem::ConstraintForce* pcConstraint =
|
||||
static_cast<Fem::ConstraintForce*>(ConstraintView->getObject());
|
||||
pcConstraint->Force.setValue(f);
|
||||
}
|
||||
|
||||
void TaskFemConstraintForce::onReferenceDeleted()
|
||||
{
|
||||
TaskFemConstraintForce::removeFromSelection(); // OvG: On right-click face is automatically
|
||||
@@ -359,9 +340,9 @@ void TaskFemConstraintForce::onCheckReverse(const bool pressed)
|
||||
pcConstraint->Reversed.setValue(pressed);
|
||||
}
|
||||
|
||||
double TaskFemConstraintForce::getForce() const
|
||||
const std::string TaskFemConstraintForce::getForce() const
|
||||
{
|
||||
return ui->spinForce->value().getValue();
|
||||
return ui->spinForce->value().getSafeUserString().toStdString();
|
||||
}
|
||||
|
||||
const std::string TaskFemConstraintForce::getReferences() const
|
||||
@@ -467,21 +448,10 @@ bool TaskDlgFemConstraintForce::accept()
|
||||
static_cast<const TaskFemConstraintForce*>(parameter);
|
||||
|
||||
try {
|
||||
// Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "FEM force constraint changed"));
|
||||
|
||||
if (parameterForce->getForce() <= 0) {
|
||||
QMessageBox::warning(parameter,
|
||||
tr("Input error"),
|
||||
tr("Please specify a force greater than 0"));
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
QByteArray num = QByteArray::number(parameterForce->getForce());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,
|
||||
"App.ActiveDocument.%s.Force = %s",
|
||||
name.c_str(),
|
||||
num.data());
|
||||
}
|
||||
Gui::Command::doCommand(Gui::Command::Doc,
|
||||
"App.ActiveDocument.%s.Force = \"%s\"",
|
||||
name.c_str(),
|
||||
parameterForce->getForce().c_str());
|
||||
|
||||
std::string dirname = parameterForce->getDirectionName().data();
|
||||
std::string dirobj = parameterForce->getDirectionObject().data();
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
explicit TaskFemConstraintForce(ViewProviderFemConstraintForce* ConstraintView,
|
||||
QWidget* parent = nullptr);
|
||||
~TaskFemConstraintForce() override;
|
||||
double getForce() const;
|
||||
const std::string getForce() const;
|
||||
const std::string getReferences() const override;
|
||||
const std::string getDirectionName() const;
|
||||
const std::string getDirectionObject() const;
|
||||
@@ -63,7 +63,6 @@ public:
|
||||
|
||||
private Q_SLOTS:
|
||||
void onReferenceDeleted();
|
||||
void onForceChanged(double);
|
||||
void onButtonDirection(const bool pressed = false);
|
||||
void onCheckReverse(bool);
|
||||
void addToSelection() override;
|
||||
|
||||
@@ -90,12 +90,18 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="labelForce">
|
||||
<property name="text">
|
||||
<string>Load [N]</string>
|
||||
<string>Force</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="spinForce">
|
||||
<property name="unit" stdset="0">
|
||||
<string>N</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>500.000000000000000</double>
|
||||
</property>
|
||||
|
||||
@@ -803,7 +803,8 @@ def get_force_obj_vertex_nodeload_table(
|
||||
# ("refshape_name.elemname", node_load_table)
|
||||
# ]
|
||||
force_obj_node_load_table = []
|
||||
node_load = frc_obj.Force / len(frc_obj.References)
|
||||
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
|
||||
node_load = force_quantity / len(frc_obj.References)
|
||||
for o, elem_tup in frc_obj.References:
|
||||
node_count = len(elem_tup)
|
||||
for elem in elem_tup:
|
||||
@@ -863,7 +864,8 @@ def get_force_obj_edge_nodeload_table(
|
||||
)
|
||||
sum_ref_edge_length += ref_edge.Length
|
||||
if sum_ref_edge_length != 0:
|
||||
force_per_sum_ref_edge_length = frc_obj.Force / sum_ref_edge_length
|
||||
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
|
||||
force_per_sum_ref_edge_length = force_quantity / sum_ref_edge_length
|
||||
for o, elem_tup in frc_obj.References:
|
||||
for elem in elem_tup:
|
||||
ref_edge = o.Shape.getElement(elem)
|
||||
@@ -907,7 +909,8 @@ def get_force_obj_edge_nodeload_table(
|
||||
for node in ref_shape[1]:
|
||||
sum_node_load += ref_shape[1][node] # for debugging
|
||||
|
||||
ratio = sum_node_load / frc_obj.Force
|
||||
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
|
||||
ratio = sum_node_load / force_quantity
|
||||
if ratio < 0.99 or ratio > 1.01:
|
||||
FreeCAD.Console.PrintMessage(
|
||||
"Deviation sum_node_load to frc_obj.Force is more than 1% : {}\n"
|
||||
@@ -927,7 +930,7 @@ def get_force_obj_edge_nodeload_table(
|
||||
)
|
||||
FreeCAD.Console.PrintMessage(
|
||||
" frc_obj.Force: {}\n"
|
||||
.format(frc_obj.Force)
|
||||
.format(force_quantity)
|
||||
)
|
||||
FreeCAD.Console.PrintMessage(
|
||||
" the reason could be simply a circle length --> "
|
||||
@@ -1135,7 +1138,8 @@ def get_force_obj_face_nodeload_table(
|
||||
)
|
||||
sum_ref_face_area += ref_face.Area
|
||||
if sum_ref_face_area != 0:
|
||||
force_per_sum_ref_face_area = frc_obj.Force / sum_ref_face_area
|
||||
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
|
||||
force_per_sum_ref_face_area = force_quantity / sum_ref_face_area
|
||||
for o, elem_tup in frc_obj.References:
|
||||
for elem in elem_tup:
|
||||
ref_face = o.Shape.getElement(elem)
|
||||
@@ -1178,7 +1182,8 @@ def get_force_obj_face_nodeload_table(
|
||||
for node in ref_shape[1]:
|
||||
sum_node_load += ref_shape[1][node] # for debugging
|
||||
|
||||
ratio = sum_node_load / frc_obj.Force
|
||||
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
|
||||
ratio = sum_node_load / force_quantity
|
||||
if ratio < 0.99 or ratio > 1.01:
|
||||
FreeCAD.Console.PrintMessage(
|
||||
"Deviation sum_node_load to frc_obj.Force is more than 1% : {}\n"
|
||||
@@ -1198,7 +1203,7 @@ def get_force_obj_face_nodeload_table(
|
||||
)
|
||||
FreeCAD.Console.PrintMessage(
|
||||
" frc_obj.Force: {}\n"
|
||||
.format(frc_obj.Force)
|
||||
.format(force_quantity)
|
||||
)
|
||||
FreeCAD.Console.PrintMessage(
|
||||
" the reason could be simply a circle area --> "
|
||||
|
||||
@@ -54,14 +54,15 @@ def write_meshdata_constraint(f, femobj, force_obj, ccxwriter):
|
||||
f.write("** {}\n".format(ref_shape[0]))
|
||||
for n in sorted(ref_shape[1]):
|
||||
node_load = ref_shape[1][n]
|
||||
# the loads in ref_shape[1][n] are without unit
|
||||
if abs(direction_vec.x) > dir_zero_tol:
|
||||
v1 = "{:.13E}".format(direction_vec.x * node_load)
|
||||
v1 = "{}".format(direction_vec.x * node_load)
|
||||
f.write("{},1,{}\n".format(n, v1))
|
||||
if abs(direction_vec.y) > dir_zero_tol:
|
||||
v2 = "{:.13E}".format(direction_vec.y * node_load)
|
||||
v2 = "{}".format(direction_vec.y * node_load)
|
||||
f.write("{},2,{}\n".format(n, v2))
|
||||
if abs(direction_vec.z) > dir_zero_tol:
|
||||
v3 = "{:.13E}".format(direction_vec.z * node_load)
|
||||
v3 = "{}".format(direction_vec.z * node_load)
|
||||
f.write("{},3,{}\n".format(n, v3))
|
||||
f.write("\n")
|
||||
f.write("\n")
|
||||
|
||||
@@ -97,7 +97,7 @@ class DeformationWriter:
|
||||
for obj in self.write.getMember("Fem::ConstraintForce"):
|
||||
if obj.References:
|
||||
for name in obj.References[0][1]:
|
||||
force = self.write.getFromUi(obj.Force, "N", "M*L*T^-2")
|
||||
force = float(obj.Force.getValueAs("N"))
|
||||
self.write.boundary(name, "Force 1", obj.DirectionVector.x * force)
|
||||
self.write.boundary(name, "Force 2", obj.DirectionVector.y * force)
|
||||
self.write.boundary(name, "Force 3", obj.DirectionVector.z * force)
|
||||
|
||||
@@ -313,7 +313,7 @@ class ElasticityWriter:
|
||||
for obj in self.write.getMember("Fem::ConstraintForce"):
|
||||
if obj.References:
|
||||
for name in obj.References[0][1]:
|
||||
force = self.write.getFromUi(obj.Force, "N", "M*L*T^-2")
|
||||
force = float(obj.Force.getValueAs("N"))
|
||||
self.write.boundary(name, "Force 1", obj.DirectionVector.x * force)
|
||||
self.write.boundary(name, "Force 2", obj.DirectionVector.y * force)
|
||||
self.write.boundary(name, "Force 3", obj.DirectionVector.z * force)
|
||||
|
||||
@@ -50,6 +50,7 @@ def add_con_force(f, model, mystran_writer):
|
||||
for ref_shape in femobj["NodeLoadTable"]:
|
||||
force_code += "# {}\n".format(ref_shape[0])
|
||||
for n in sorted(ref_shape[1]):
|
||||
# the loads in ref_shape[1][n] are without unit
|
||||
node_load = ref_shape[1][n]
|
||||
force_code += (
|
||||
"model.add_force(sid={}, node={}, mag={}, xyz=({}, {}, {}))\n"
|
||||
|
||||
@@ -157,6 +157,7 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
|
||||
direction_vec = femobj["Object"].DirectionVector
|
||||
for ref_shape in femobj["NodeLoadTable"]:
|
||||
for n in sorted(ref_shape[1]):
|
||||
# the loads in ref_shape[1][n] are without unit
|
||||
node_load = ref_shape[1][n]
|
||||
if (direction_vec.x != 0.0):
|
||||
v1 = direction_vec.x * node_load
|
||||
|
||||
Reference in New Issue
Block a user