Fem: Update constraint symbols when moving reference shape - fixes #6093
This commit is contained in:
@@ -55,16 +55,19 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include <App/FeaturePythonPyImp.h>
|
||||
#include <App/OriginFeature.h>
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <Mod/Part/App/Tools.h>
|
||||
|
||||
#include "FemConstraint.h"
|
||||
#include "FemTools.h"
|
||||
|
||||
|
||||
using namespace Fem;
|
||||
namespace sp = std::placeholders;
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
using Adaptor3d_HSurface = Adaptor3d_Surface;
|
||||
@@ -140,6 +143,18 @@ int Constraint::calcDrawScaleFactor() const
|
||||
return 1;
|
||||
}
|
||||
|
||||
void setSubShapeLocation(const Part::Feature* feat, TopoDS_Shape& sh)
|
||||
{
|
||||
// subshape placement is not necessarily the same as the
|
||||
// feature placement.
|
||||
Base::Matrix4D matrix = Part::TopoShape::convert(sh.Location().Transformation());
|
||||
Base::Placement shPla {matrix};
|
||||
Base::Placement featlPlaInv = feat->Placement.getValue().inverse();
|
||||
Base::Placement shGlobalPla = feat->globalPlacement() * featlPlaInv * shPla;
|
||||
|
||||
sh.Location(Part::Tools::fromPlacement(shGlobalPla));
|
||||
}
|
||||
|
||||
constexpr int CONSTRAINTSTEPLIMIT = 50;
|
||||
|
||||
void Constraint::onChanged(const App::Property* prop)
|
||||
@@ -163,6 +178,8 @@ void Constraint::onChanged(const App::Property* prop)
|
||||
sh = toposhape.getSubShape(SubElements[i].c_str(), !execute);
|
||||
|
||||
if (!sh.IsNull() && sh.ShapeType() == TopAbs_FACE) {
|
||||
setSubShapeLocation(feat, sh);
|
||||
|
||||
// Get face normal in center point
|
||||
TopoDS_Face face = TopoDS::Face(sh);
|
||||
BRepGProp_Face props(face);
|
||||
@@ -193,6 +210,37 @@ void Constraint::onChanged(const App::Property* prop)
|
||||
App::DocumentObject::onChanged(prop);
|
||||
}
|
||||
|
||||
void Constraint::slotChangedObject(const App::DocumentObject& obj, const App::Property& prop)
|
||||
{
|
||||
if (obj.isDerivedFrom<App::GeoFeature>()
|
||||
&& (prop.isDerivedFrom<App::PropertyPlacement>() || obj.isRemoving())) {
|
||||
auto values = References.getValues();
|
||||
for (const auto ref : values) {
|
||||
auto v = ref->getInListEx(true);
|
||||
if ((&obj == ref) || (std::find(v.begin(), v.end(), &obj) != v.end())) {
|
||||
this->touch();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Constraint::onSettingDocument()
|
||||
{
|
||||
App::Document* doc = getDocument();
|
||||
if (doc) {
|
||||
connDocChangedObject = doc->signalChangedObject.connect(
|
||||
std::bind(&Constraint::slotChangedObject, this, sp::_1, sp::_2));
|
||||
}
|
||||
|
||||
App::DocumentObject::onSettingDocument();
|
||||
}
|
||||
|
||||
void Constraint::unsetupObject()
|
||||
{
|
||||
connDocChangedObject.disconnect();
|
||||
}
|
||||
|
||||
void Constraint::onDocumentRestored()
|
||||
{
|
||||
// This seems to be the only way to make the ViewProvider display the constraint
|
||||
@@ -223,6 +271,8 @@ bool Constraint::getPoints(std::vector<Base::Vector3d>& points,
|
||||
return false;
|
||||
}
|
||||
|
||||
setSubShapeLocation(feat, sh);
|
||||
|
||||
if (sh.ShapeType() == TopAbs_VERTEX) {
|
||||
const TopoDS_Vertex& vertex = TopoDS::Vertex(sh);
|
||||
gp_Pnt p = BRep_Tool::Pnt(vertex);
|
||||
|
||||
@@ -179,6 +179,8 @@ protected:
|
||||
* of FemConstraint.
|
||||
*/
|
||||
void onDocumentRestored() override;
|
||||
void onSettingDocument() override;
|
||||
void unsetupObject() override;
|
||||
|
||||
/**
|
||||
* @brief Returns data based on References relevant for rendering widgets.
|
||||
@@ -247,6 +249,10 @@ protected:
|
||||
* variables. It should be rewritten at a different place.
|
||||
*/
|
||||
const Base::Vector3d getDirection(const App::PropertyLinkSub& direction);
|
||||
|
||||
private:
|
||||
void slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop);
|
||||
boost::signals2::connection connDocChangedObject;
|
||||
};
|
||||
|
||||
using ConstraintPython = App::FeaturePythonT<Constraint>;
|
||||
|
||||
@@ -717,7 +717,12 @@ class GmshTools():
|
||||
geo.write("// no boundary layer settings for this mesh\n")
|
||||
|
||||
def write_part_file(self):
|
||||
self.part_obj.Shape.exportBrep(self.temp_file_geometry)
|
||||
global_pla = self.part_obj.getGlobalPlacement()
|
||||
geom = self.part_obj.getPropertyOfGeometry()
|
||||
# get partner shape
|
||||
geom_trans = geom.transformed(FreeCAD.Placement().Matrix)
|
||||
geom_trans.Placement = global_pla
|
||||
geom_trans.exportBrep(self.temp_file_geometry)
|
||||
|
||||
def write_geo(self):
|
||||
temp_dir = os.path.dirname(self.temp_file_geo)
|
||||
|
||||
@@ -116,8 +116,7 @@ def get_femnodes_by_refshape(
|
||||
):
|
||||
nodes = []
|
||||
for refelement in ref[1]:
|
||||
# the following method getElement(element) does not return Solid elements
|
||||
r = geomtools.get_element(ref[0], refelement)
|
||||
r = sub_shape_at_global_placement(ref[0], refelement)
|
||||
FreeCAD.Console.PrintMessage(
|
||||
" "
|
||||
"ReferenceShape ... Type: {0}, "
|
||||
@@ -1127,7 +1126,7 @@ def get_force_obj_face_nodeload_table(
|
||||
sum_node_load = 0 # for debugging
|
||||
for o, elem_tup in frc_obj.References:
|
||||
for elem in elem_tup:
|
||||
ref_face = o.Shape.getElement(elem)
|
||||
ref_face = sub_shape_at_global_placement(o, elem)
|
||||
FreeCAD.Console.PrintMessage(
|
||||
" "
|
||||
"ReferenceShape ... Type: {0}, "
|
||||
@@ -1142,7 +1141,7 @@ def get_force_obj_face_nodeload_table(
|
||||
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)
|
||||
ref_face = sub_shape_at_global_placement(o, elem)
|
||||
|
||||
# face_table:
|
||||
# { meshfaceID : ( nodeID, ... , nodeID ) }
|
||||
@@ -1666,15 +1665,15 @@ def get_pressure_obj_faces(
|
||||
# How to find the orientation of a FEM mesh face?
|
||||
# https://forum.freecad.org/viewtopic.php?f=18&t=51898
|
||||
else:
|
||||
for sh, elems in femobj["Object"].References:
|
||||
for obj, elems in femobj["Object"].References:
|
||||
for e in elems:
|
||||
meshfaces = femmesh.getFacesByFace(sh.getSubObject(e))
|
||||
ref_face = sub_shape_at_global_placement(obj, e)
|
||||
meshfaces = femmesh.getFacesByFace(ref_face)
|
||||
for mf in meshfaces:
|
||||
pressure_faces.append([mf, -1])
|
||||
|
||||
return pressure_faces
|
||||
|
||||
|
||||
# ***** deprecated method for retrieving pressure faces *****************************************
|
||||
# for constraint pressure and finite solid element mesh
|
||||
# it was switched to the method get_ccxelement_faces_from_binary_search
|
||||
@@ -1996,21 +1995,13 @@ def get_reference_group_elements(
|
||||
else:
|
||||
key = obj.Name
|
||||
elements = []
|
||||
stype = None
|
||||
for r in obj.References:
|
||||
parent = r[0]
|
||||
childs = r[1]
|
||||
# FreeCAD.Console.PrintMessage("{}\n".format(parent))
|
||||
# FreeCAD.Console.PrintMessage("{}\n".format(childs))
|
||||
for child in childs:
|
||||
# the method getElement(element) does not return Solid elements
|
||||
ref_shape = geomtools.get_element(parent, child)
|
||||
if not stype:
|
||||
stype = ref_shape.ShapeType
|
||||
elif stype != ref_shape.ShapeType:
|
||||
FreeCAD.Console.PrintError(
|
||||
"Error, two refshapes in References with different ShapeTypes.\n"
|
||||
)
|
||||
ref_shape = parent.getSubObject(child)
|
||||
FreeCAD.Console.PrintLog("{}\n".format(ref_shape))
|
||||
found_element = geomtools.find_element_in_shape(aShape, ref_shape)
|
||||
if found_element is not None:
|
||||
@@ -2527,4 +2518,15 @@ def beam_reduced_integration(
|
||||
|
||||
f.truncate()
|
||||
f.close()
|
||||
|
||||
# ************************************************************************************************
|
||||
def sub_shape_at_global_placement(obj, sub_name):
|
||||
sub_sh = obj.getSubObject(sub_name)
|
||||
# get partner shape
|
||||
partner = sub_sh.transformed(FreeCAD.Placement().Matrix)
|
||||
partner.Placement = obj.getGlobalPlacement() \
|
||||
* obj.Placement.inverse() \
|
||||
* sub_sh.Placement
|
||||
|
||||
return partner
|
||||
## @}
|
||||
|
||||
Reference in New Issue
Block a user