From 0e6d1cf5f99f828796f024de6ea00411cdb8189d Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 25 Jul 2024 14:02:34 -0300 Subject: [PATCH] Fem: Move MeshGmsh proxy from Fem::FemMeshObject to Fem::FemMeshShapeBaseObject - fixes #14897 --- src/Mod/Fem/ObjectsFem.py | 2 +- src/Mod/Fem/femcommands/commands.py | 10 +- src/Mod/Fem/femmesh/gmshtools.py | 6 +- src/Mod/Fem/femmesh/meshsetsgetter.py | 2 - src/Mod/Fem/femobjects/mesh_gmsh.py | 544 +++++++++--------- .../Fem/femsolver/elmer/equations/equation.py | 2 +- src/Mod/Fem/femsolver/elmer/writer.py | 18 +- .../task_constraint_bodyheatsource.py | 3 +- .../task_constraint_currentdensity.py | 3 +- .../task_constraint_electrostaticpotential.py | 3 +- .../task_constraint_flowvelocity.py | 3 +- .../task_constraint_initialflowvelocity.py | 3 +- .../task_constraint_initialpressure.py | 3 +- .../task_constraint_magnetization.py | 3 +- src/Mod/Fem/femtaskpanels/task_mesh_gmsh.py | 7 +- src/Mod/Fem/femtools/femutils.py | 17 - 16 files changed, 292 insertions(+), 337 deletions(-) diff --git a/src/Mod/Fem/ObjectsFem.py b/src/Mod/Fem/ObjectsFem.py index a35b866892..4c6042ad56 100644 --- a/src/Mod/Fem/ObjectsFem.py +++ b/src/Mod/Fem/ObjectsFem.py @@ -490,7 +490,7 @@ def makeMeshBoundaryLayer(doc, base_mesh, name="MeshBoundaryLayer"): def makeMeshGmsh(doc, name="MeshGmsh"): """makeMeshGmsh(document, [name]): makes a Gmsh FEM mesh object""" - obj = doc.addObject("Fem::FemMeshObjectPython", name) + obj = doc.addObject("Fem::FemMeshShapeBaseObjectPython", name) from femobjects import mesh_gmsh mesh_gmsh.MeshGmsh(obj) diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index e92e9088ff..ab06364159 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -762,10 +762,18 @@ class _MeshGmshFromShape(CommandManager): "ObjectsFem.makeMeshGmsh(FreeCAD.ActiveDocument, '" + mesh_obj_name + "')" ) FreeCADGui.doCommand( - "FreeCAD.ActiveDocument.ActiveObject.Part = FreeCAD.ActiveDocument.{}".format( + "FreeCAD.ActiveDocument.ActiveObject.Shape = FreeCAD.ActiveDocument.{}".format( self.selobj.Name ) ) + FreeCADGui.doCommand("FreeCAD.ActiveDocument.ActiveObject.ElementOrder = '2nd'") + # SecondOrderLinear gives much better meshes in the regard of + # nonpositive jacobians but on curved faces the constraint nodes + # will no longer found thus standard will be False + # https://forum.freecad.org/viewtopic.php?t=41738 + # https://forum.freecad.org/viewtopic.php?f=18&t=45260&start=20#p389494 + FreeCADGui.doCommand("FreeCAD.ActiveDocument.ActiveObject.SecondOrderLinear = False") + # Gmsh mesh object could be added without an active analysis # but if there is an active analysis move it in there import FemGui diff --git a/src/Mod/Fem/femmesh/gmshtools.py b/src/Mod/Fem/femmesh/gmshtools.py index a3d7fbaa0a..487d8da2fc 100644 --- a/src/Mod/Fem/femmesh/gmshtools.py +++ b/src/Mod/Fem/femmesh/gmshtools.py @@ -57,7 +57,7 @@ class GmshTools: self.analysis = None # part to mesh - self.part_obj = self.mesh_obj.Part + self.part_obj = self.mesh_obj.Shape # clmax, CharacteristicLengthMax: float, 0.0 = 1e+22 self.clmax = Units.Quantity(self.mesh_obj.CharacteristicLengthMax).Value @@ -982,7 +982,7 @@ doc.recompute() box_obj.ViewObject.Visibility = False femmesh_obj = ObjectsFem.makeMeshGmsh(doc, box_obj.Name + "_Mesh") -femmesh_obj.Part = box_obj +femmesh_obj.Shape = box_obj doc.recompute() from femmesh.gmshtools import GmshTools as gt @@ -1009,7 +1009,7 @@ for len in max_mesh_sizes: quantity_len = "{}".format(len) print("\n\n Start length = {}".format(quantity_len)) femmesh_obj = ObjectsFem.makeMeshGmsh(doc, box_obj.Name + "_Mesh") - femmesh_obj.Part = box_obj + femmesh_obj.Shape = box_obj femmesh_obj.CharacteristicLengthMax = "{}".format(quantity_len) femmesh_obj.CharacteristicLengthMin = "{}".format(quantity_len) doc.recompute() diff --git a/src/Mod/Fem/femmesh/meshsetsgetter.py b/src/Mod/Fem/femmesh/meshsetsgetter.py index 8aeaa81da0..27ccf458b5 100644 --- a/src/Mod/Fem/femmesh/meshsetsgetter.py +++ b/src/Mod/Fem/femmesh/meshsetsgetter.py @@ -64,8 +64,6 @@ class MeshSetsGetter: if self.mesh_object: if hasattr(self.mesh_object, "Shape"): self.theshape = self.mesh_object.Shape - elif hasattr(self.mesh_object, "Part"): - self.theshape = self.mesh_object.Part else: FreeCAD.Console.PrintWarning( "A finite mesh without a link to a Shape was given. " diff --git a/src/Mod/Fem/femobjects/mesh_gmsh.py b/src/Mod/Fem/femobjects/mesh_gmsh.py index 5c7beefd17..df66bd8acd 100644 --- a/src/Mod/Fem/femobjects/mesh_gmsh.py +++ b/src/Mod/Fem/femobjects/mesh_gmsh.py @@ -31,6 +31,8 @@ __url__ = "https://www.freecad.org" from . import base_fempythonobject +_PropHelper = base_fempythonobject._PropHelper + class MeshGmsh(base_fempythonobject.BaseFemPythonObject): """ @@ -40,295 +42,267 @@ class MeshGmsh(base_fempythonobject.BaseFemPythonObject): Type = "Fem::FemMeshGmsh" # they will be used from the task panel too, thus they need to be outside of the __init__ - known_element_dimensions = ["From Shape", "1D", "2D", "3D"] - known_element_orders = ["1st", "2nd"] - known_mesh_algorithm_2D = [ - "Automatic", - "MeshAdapt", - "Delaunay", - "Frontal", - "BAMG", - "DelQuad", - "Packing Parallelograms", - ] - known_mesh_algorithm_3D = [ - "Automatic", - "Delaunay", - "New Delaunay", - "Frontal", - "MMG3D", - "R-tree", - "HXT", - ] - known_mesh_RecombinationAlgorithms = [ - "Simple", - "Blossom", - "Simple full-quad", - "Blossom full-quad", - ] - known_mesh_HighOrderOptimizers = [ - "None", - "Optimization", - "Elastic+Optimization", - "Elastic", - "Fast curving", - ] - known_mesh_SubdivisionAlgorithms = ["None", "All Quadrangles", "All Hexahedra", "Barycentric"] def __init__(self, obj): super().__init__(obj) - self.add_properties(obj) + + for prop in self._get_properties(): + prop.add_to_object(obj) + + def _get_properties(self): + prop = [] + + prop.append( + _PropHelper( + type="App::PropertyLinkList", + name="MeshBoundaryLayerList", + group="Base", + doc="Mesh boundaries need inflation layers", + value=[], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLinkList", + name="MeshRegionList", + group="Base", + doc="Mesh refinments of the mesh", + value=[], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLinkList", + name="MeshGroupList", + group="Base", + doc="Mesh groups of the mesh", + value=[], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="CharacteristicLengthMax", + group="FEM Gmsh Mesh Params", + doc="Max mesh element size (0.0 means infinity)", + value=0.0, # will be 1e+22 + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="CharacteristicLengthMin", + group="FEM Gmsh Mesh Params", + doc="Min mesh element size", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="ElementDimension", + group="FEM Gmsh Mesh Params", + doc="Dimension of mesh elements ('From Shape': according ShapeType of part to mesh)", + value=["From Shape", "1D", "2D", "3D"], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="ElementOrder", + group="FEM Gmsh Mesh Params", + doc="Order of mesh elements", + value=["1st", "2nd"], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="OptimizeStd", + group="FEM Gmsh Mesh Params", + doc="Optimize tetrahedral elements", + value=True, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="OptimizeNetgen", + group="FEM Gmsh Mesh Params", + doc="Optimize tetra elements by use of Netgen", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="HighOrderOptimize", + group="FEM Gmsh Mesh Params", + doc="Optimization of high order meshes", + value=[ + "None", + "Optimization", + "Elastic+Optimization", + "Elastic", + "Fast curving", + ], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="RecombineAll", + group="FEM Gmsh Mesh Params", + doc="Apply recombination algorithm to all surfaces", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="Recombine3DAll", + group="FEM Gmsh Mesh Params", + doc="Apply recombination algorithm to all volumes", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="RecombinationAlgorithm", + group="FEM Gmsh Mesh Params", + doc="Recombination algorithm", + value=[ + "Simple", + "Blossom", + "Simple full-quad", + "Blossom full-quad", + ], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="CoherenceMesh", + group="FEM Gmsh Mesh Params", + doc="Removes all duplicate mesh vertices", + value=True, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyFloat", + name="GeometryTolerance", + group="FEM Gmsh Mesh Params", + doc="Geometrical Tolerance (0.0 means GMSH std = 1e-08)", + value=1e-06, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="SecondOrderLinear", + group="FEM Gmsh Mesh Params", + doc="Second order nodes are created by linear interpolation", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyIntegerConstraint", + name="MeshSizeFromCurvature", + group="FEM Gmsh Mesh Params", + doc="Number of elements per 2*pi radians, 0 to deactivate", + value=(12, 0, 10000, 1), + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="Algorithm2D", + group="FEM Gmsh Mesh Params", + doc="Mesh algorithm 2D", + value=[ + "Automatic", + "MeshAdapt", + "Delaunay", + "Frontal", + "BAMG", + "DelQuad", + "Packing Parallelograms", + ], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="Algorithm3D", + group="FEM Gmsh Mesh Params", + doc="Mesh algorithm 3D", + value=[ + "Automatic", + "Delaunay", + "New Delaunay", + "Frontal", + "MMG3D", + "R-tree", + "HXT", + ], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="GroupsOfNodes", + group="FEM Gmsh Mesh Params", + doc="For each group create not only the elements but the nodes too", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="SubdivisionAlgorithm", + group="FEM Gmsh Mesh Params", + doc="Mesh subdivision algorithm", + value=["None", "All Quadrangles", "All Hexahedra", "Barycentric"], + ) + ) + + return prop def onDocumentRestored(self, obj): + # update old project with new properties + for prop in self._get_properties(): + try: + obj.getPropertyByName(prop.name) + if prop.name == "Algorithm3D": + # refresh the list of known 3D algorithms + obj.Algorithm3D = prop.value + elif prop.name == "HighOrderOptimize": + # HighOrderOptimize was once App::PropertyBool, so check this + if type(obj.HighOrderOptimize) is bool: + value = obj.HighOrderOptimize + obj.setPropertyStatus("HighOrderOptimize", "-LockDynamic") + obj.removeProperty("HighOrderOptimize") + prop.add_to_object(obj) + obj.HighOrderOptimize = "Optimization" if value else "None" + except: + prop.add_to_object(obj) - # HighOrderOptimize - # was once App::PropertyBool, so check this - high_order_optimizer = "" - if obj.HighOrderOptimize is True: - high_order_optimizer = "Optimization" - elif obj.HighOrderOptimize is False: - high_order_optimizer = "None" - obj.removeProperty("HighOrderOptimize") - # add new HighOrderOptimize property - self.add_properties(obj) - # write the stored high_order_optimizer - if high_order_optimizer: - obj.HighOrderOptimize = high_order_optimizer - - # Algorithm3D - # refresh the list of known 3D algorithms for existing meshes - # since some algos are meanwhile deprecated and new algos are available - obj.Algorithm3D = MeshGmsh.known_mesh_algorithm_3D - - def add_properties(self, obj): - - # this method is called from onDocumentRestored - # thus only add and or set a attribute - # if the attribute does not exist - - if not hasattr(obj, "MeshBoundaryLayerList"): - obj.addProperty( - "App::PropertyLinkList", - "MeshBoundaryLayerList", - "Base", - "Mesh boundaries need inflation layers", + # migrate old Part property to Shape property + try: + value_part = obj.getPropertyByName("Part") + obj.setPropertyStatus("Part", "-LockDynamic") + obj.removeProperty("Part") + # old object is Fem::FemMeshObjectPython (does not have Shape property with global scope) + prop = _PropHelper( + type="App::PropertyLinkGlobal", + name="Shape", + group="FEM Mesh", + doc="Geometry object, the mesh is made from. The geometry object has to have a Shape", + value=value_part, ) - obj.setPropertyStatus("MeshBoundaryLayerList", "LockDynamic") - obj.MeshBoundaryLayerList = [] - - if not hasattr(obj, "MeshRegionList"): - obj.addProperty( - "App::PropertyLinkList", "MeshRegionList", "Base", "Mesh refinments of the mesh" - ) - obj.setPropertyStatus("MeshRegionList", "LockDynamic") - obj.MeshRegionList = [] - - if not hasattr(obj, "MeshGroupList"): - obj.addProperty( - "App::PropertyLinkList", "MeshGroupList", "Base", "Mesh groups of the mesh" - ) - obj.setPropertyStatus("MeshGroupList", "LockDynamic") - obj.MeshGroupList = [] - - if not hasattr(obj, "Part"): - obj.addProperty( - "App::PropertyLink", - "Part", - "FEM Mesh", - "Geometry object, the mesh is made from. The geometry object has to have a Shape.", - ) - obj.setPropertyStatus("Part", "LockDynamic") - obj.Part = None - - if not hasattr(obj, "CharacteristicLengthMax"): - obj.addProperty( - "App::PropertyLength", - "CharacteristicLengthMax", - "FEM Gmsh Mesh Params", - "Max mesh element size (0.0 = infinity)", - ) - obj.setPropertyStatus("CharacteristicLengthMax", "LockDynamic") - obj.CharacteristicLengthMax = 0.0 # will be 1e+22 - - if not hasattr(obj, "CharacteristicLengthMin"): - obj.addProperty( - "App::PropertyLength", - "CharacteristicLengthMin", - "FEM Gmsh Mesh Params", - "Min mesh element size", - ) - obj.setPropertyStatus("CharacteristicLengthMin", "LockDynamic") - obj.CharacteristicLengthMin = 0.0 - - if not hasattr(obj, "ElementDimension"): - obj.addProperty( - "App::PropertyEnumeration", - "ElementDimension", - "FEM Gmsh Mesh Params", - "Dimension of mesh elements (Auto = according ShapeType of part to mesh)", - ) - obj.setPropertyStatus("ElementDimension", "LockDynamic") - obj.ElementDimension = MeshGmsh.known_element_dimensions - obj.ElementDimension = "From Shape" # according ShapeType of Part to mesh - - if not hasattr(obj, "ElementOrder"): - obj.addProperty( - "App::PropertyEnumeration", - "ElementOrder", - "FEM Gmsh Mesh Params", - "Order of mesh elements", - ) - obj.setPropertyStatus("ElementOrder", "LockDynamic") - obj.ElementOrder = MeshGmsh.known_element_orders - obj.ElementOrder = "2nd" - - if not hasattr(obj, "OptimizeStd"): - obj.addProperty( - "App::PropertyBool", - "OptimizeStd", - "FEM Gmsh Mesh Params", - "Optimize tetrahedral elements", - ) - obj.setPropertyStatus("OptimizeStd", "LockDynamic") - obj.OptimizeStd = True - - if not hasattr(obj, "OptimizeNetgen"): - obj.addProperty( - "App::PropertyBool", - "OptimizeNetgen", - "FEM Gmsh Mesh Params", - "Optimize tetra elements by use of Netgen", - ) - obj.setPropertyStatus("OptimizeNetgen", "LockDynamic") - obj.OptimizeNetgen = False - - if not hasattr(obj, "HighOrderOptimize"): - obj.addProperty( - "App::PropertyEnumeration", - "HighOrderOptimize", - "FEM Gmsh Mesh Params", - "Optimization of high order meshes", - ) - obj.setPropertyStatus("HighOrderOptimize", "LockDynamic") - obj.HighOrderOptimize = MeshGmsh.known_mesh_HighOrderOptimizers - obj.HighOrderOptimize = "None" - - if not hasattr(obj, "RecombineAll"): - obj.addProperty( - "App::PropertyBool", - "RecombineAll", - "FEM Gmsh Mesh Params", - "Apply recombination algorithm to all surfaces", - ) - obj.setPropertyStatus("RecombineAll", "LockDynamic") - obj.RecombineAll = False - - if not hasattr(obj, "Recombine3DAll"): - obj.addProperty( - "App::PropertyBool", - "Recombine3DAll", - "FEM Gmsh Mesh Params", - "Apply recombination algorithm to all volumes", - ) - obj.setPropertyStatus("Recombine3DAll", "LockDynamic") - obj.Recombine3DAll = False - - if not hasattr(obj, "RecombinationAlgorithm"): - obj.addProperty( - "App::PropertyEnumeration", - "RecombinationAlgorithm", - "FEM Gmsh Mesh Params", - "Recombination algorithm", - ) - obj.setPropertyStatus("RecombinationAlgorithm", "LockDynamic") - obj.RecombinationAlgorithm = MeshGmsh.known_mesh_RecombinationAlgorithms - obj.RecombinationAlgorithm = "Simple" - - if not hasattr(obj, "CoherenceMesh"): - obj.addProperty( - "App::PropertyBool", - "CoherenceMesh", - "FEM Gmsh Mesh Params", - "Removes all duplicate mesh vertices", - ) - obj.setPropertyStatus("CoherenceMesh", "LockDynamic") - obj.CoherenceMesh = True - - if not hasattr(obj, "GeometryTolerance"): - obj.addProperty( - "App::PropertyFloat", - "GeometryTolerance", - "FEM Gmsh Mesh Params", - "Geometrical Tolerance (0.0 = GMSH std = 1e-08)", - ) - obj.setPropertyStatus("GeometryTolerance", "LockDynamic") - obj.GeometryTolerance = 1e-06 - - if not hasattr(obj, "SecondOrderLinear"): - obj.addProperty( - "App::PropertyBool", - "SecondOrderLinear", - "FEM Gmsh Mesh Params", - "Second order nodes are created by linear interpolation", - ) - obj.setPropertyStatus("SecondOrderLinear", "LockDynamic") - obj.SecondOrderLinear = False - # gives much better meshes in the regard of nonpositive jacobians - # but - # on curved faces the constraint nodes will no longer found - # thus standard will be False - # https://forum.freecad.org/viewtopic.php?t=41738 - # https://forum.freecad.org/viewtopic.php?f=18&t=45260&start=20#p389494 - - if not hasattr(obj, "MeshSizeFromCurvature"): - obj.addProperty( - "App::PropertyIntegerConstraint", - "MeshSizeFromCurvature", - "FEM Gmsh Mesh Params", - "number of elements per 2*pi radians, 0 to deactivate", - ) - obj.setPropertyStatus("MeshSizeFromCurvature", "LockDynamic") - obj.MeshSizeFromCurvature = (12, 0, 10000, 1) - - if not hasattr(obj, "Algorithm2D"): - obj.addProperty( - "App::PropertyEnumeration", - "Algorithm2D", - "FEM Gmsh Mesh Params", - "mesh algorithm 2D", - ) - obj.setPropertyStatus("Algorithm2D", "LockDynamic") - obj.Algorithm2D = MeshGmsh.known_mesh_algorithm_2D - obj.Algorithm2D = "Automatic" - - if not hasattr(obj, "Algorithm3D"): - obj.addProperty( - "App::PropertyEnumeration", - "Algorithm3D", - "FEM Gmsh Mesh Params", - "mesh algorithm 3D", - ) - obj.setPropertyStatus("Algorithm3D", "LockDynamic") - obj.Algorithm3D = MeshGmsh.known_mesh_algorithm_3D - obj.Algorithm3D = "Automatic" - - if not hasattr(obj, "GroupsOfNodes"): - obj.addProperty( - "App::PropertyBool", - "GroupsOfNodes", - "FEM Gmsh Mesh Params", - "For each group create not only the elements but the nodes too.", - ) - obj.setPropertyStatus("GroupsOfNodes", "LockDynamic") - obj.GroupsOfNodes = False - - if not hasattr(obj, "SubdivisionAlgorithm"): - obj.addProperty( - "App::PropertyEnumeration", - "SubdivisionAlgorithm", - "FEM Gmsh Mesh Params", - "Mesh subdivision algorithm", - ) - obj.setPropertyStatus("SubdivisionAlgorithm", "LockDynamic") - obj.SubdivisionAlgorithm = MeshGmsh.known_mesh_SubdivisionAlgorithms - obj.SubdivisionAlgorithm = "None" + prop.add_to_object(obj) + except: + pass diff --git a/src/Mod/Fem/femsolver/elmer/equations/equation.py b/src/Mod/Fem/femsolver/elmer/equations/equation.py index 97f8b544d3..52e58c28d2 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/equation.py +++ b/src/Mod/Fem/femsolver/elmer/equations/equation.py @@ -85,7 +85,7 @@ class _TaskPanel: self.form = [self.refWidget, propWidget] analysis = obj.getParentGroup() self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") - self._part = self._mesh.Part if self._mesh is not None else None + self._part = self._mesh.Shape if self._mesh is not None else None self._partVisible = None self._meshVisible = None diff --git a/src/Mod/Fem/femsolver/elmer/writer.py b/src/Mod/Fem/femsolver/elmer/writer.py index 65b66f4922..17c88b6fc9 100644 --- a/src/Mod/Fem/femsolver/elmer/writer.py +++ b/src/Mod/Fem/femsolver/elmer/writer.py @@ -758,24 +758,24 @@ class Writer: obj = self.getSingleMember("Fem::FemMeshObject") bodyCount = 0 prefix = "" - if obj.Part.Shape.Solids: + if obj.Shape.Shape.Solids: prefix = "Solid" - bodyCount = len(obj.Part.Shape.Solids) - elif obj.Part.Shape.Faces: + bodyCount = len(obj.Shape.Shape.Solids) + elif obj.Shape.Shape.Faces: prefix = "Face" - bodyCount = len(obj.Part.Shape.Faces) - elif obj.Part.Shape.Edges: + bodyCount = len(obj.Shape.Shape.Faces) + elif obj.Shape.Shape.Edges: prefix = "Edge" - bodyCount = len(obj.Part.Shape.Edges) + bodyCount = len(obj.Shape.Shape.Edges) return [prefix + str(i + 1) for i in range(bodyCount)] def getMeshDimension(self): obj = self.getSingleMember("Fem::FemMeshObject") - if obj.Part.Shape.Solids: + if obj.Shape.Shape.Solids: return 3 - if obj.Part.Shape.Faces: + if obj.Shape.Shape.Faces: return 2 - if obj.Part.Shape.Edges: + if obj.Shape.Shape.Edges: return 1 return None diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_bodyheatsource.py b/src/Mod/Fem/femtaskpanels/task_constraint_bodyheatsource.py index cd4634e8f9..6de249179a 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_bodyheatsource.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_bodyheatsource.py @@ -36,7 +36,6 @@ import FreeCADGui from femguiutils import selection_widgets -from femtools import femutils from femtools import membertools @@ -84,7 +83,7 @@ class _TaskPanel: if analysis is not None: self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") if self._mesh is not None: - self._part = femutils.get_part_to_mesh(self._mesh) + self._part = self._mesh.Shape self._partVisible = None self._meshVisible = None diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_currentdensity.py b/src/Mod/Fem/femtaskpanels/task_constraint_currentdensity.py index 46632d0fad..14a6292dcd 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_currentdensity.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_currentdensity.py @@ -34,7 +34,6 @@ import FreeCADGui from femguiutils import selection_widgets -from femtools import femutils from femtools import membertools @@ -63,7 +62,7 @@ class _TaskPanel: if analysis is not None: self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") if self._mesh is not None: - self._part = femutils.get_part_to_mesh(self._mesh) + self._part = self._mesh.Shape self._partVisible = None self._meshVisible = None diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py b/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py index 0b9e73e108..5f26f3da88 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py @@ -37,7 +37,6 @@ import FreeCAD import FreeCADGui from femguiutils import selection_widgets -from femtools import femutils from femtools import membertools @@ -66,7 +65,7 @@ class _TaskPanel: if analysis is not None: self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") if self._mesh is not None: - self._part = femutils.get_part_to_mesh(self._mesh) + self._part = self._mesh.Shape self._partVisible = None self._meshVisible = None diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_flowvelocity.py b/src/Mod/Fem/femtaskpanels/task_constraint_flowvelocity.py index 6c8538fba9..2c36e9be75 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_flowvelocity.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_flowvelocity.py @@ -36,7 +36,6 @@ import FreeCAD import FreeCADGui from femguiutils import selection_widgets -from femtools import femutils from femtools import membertools @@ -64,7 +63,7 @@ class _TaskPanel: if analysis is not None: self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") if self._mesh is not None: - self._part = femutils.get_part_to_mesh(self._mesh) + self._part = self._mesh.Shape self._partVisible = None self._meshVisible = None diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_initialflowvelocity.py b/src/Mod/Fem/femtaskpanels/task_constraint_initialflowvelocity.py index 42b6fe7704..fe2106e765 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_initialflowvelocity.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_initialflowvelocity.py @@ -36,7 +36,6 @@ import FreeCAD import FreeCADGui from femguiutils import selection_widgets -from femtools import femutils from femtools import membertools @@ -64,7 +63,7 @@ class _TaskPanel: if analysis is not None: self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") if self._mesh is not None: - self._part = femutils.get_part_to_mesh(self._mesh) + self._part = self._mesh.Shape self._partVisible = None self._meshVisible = None diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_initialpressure.py b/src/Mod/Fem/femtaskpanels/task_constraint_initialpressure.py index 9ed9e1bec9..93f94afd9f 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_initialpressure.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_initialpressure.py @@ -33,7 +33,6 @@ import FreeCAD import FreeCADGui from femguiutils import selection_widgets -from femtools import femutils from femtools import membertools @@ -62,7 +61,7 @@ class _TaskPanel: if analysis is not None: self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") if self._mesh is not None: - self._part = femutils.get_part_to_mesh(self._mesh) + self._part = self._mesh.Shape self._partVisible = None self._meshVisible = None diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_magnetization.py b/src/Mod/Fem/femtaskpanels/task_constraint_magnetization.py index 05c4c56ec1..919f48c2ff 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_magnetization.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_magnetization.py @@ -34,7 +34,6 @@ import FreeCADGui from femguiutils import selection_widgets -from femtools import femutils from femtools import membertools @@ -63,7 +62,7 @@ class _TaskPanel: if analysis is not None: self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") if self._mesh is not None: - self._part = femutils.get_part_to_mesh(self._mesh) + self._part = self._mesh.Shape self._partVisible = None self._meshVisible = None diff --git a/src/Mod/Fem/femtaskpanels/task_mesh_gmsh.py b/src/Mod/Fem/femtaskpanels/task_mesh_gmsh.py index 0e0dfbdfb7..d2fee5f904 100644 --- a/src/Mod/Fem/femtaskpanels/task_mesh_gmsh.py +++ b/src/Mod/Fem/femtaskpanels/task_mesh_gmsh.py @@ -41,7 +41,6 @@ import FreeCAD import FreeCADGui import FemGui -from femobjects import mesh_gmsh from femtools.femutils import is_of_type from femtools.femutils import getOutputWinColor @@ -80,9 +79,9 @@ class _TaskPanel: self.form.pb_get_gmsh_version, QtCore.SIGNAL("clicked()"), self.get_gmsh_version ) - self.form.cb_dimension.addItems(mesh_gmsh.MeshGmsh.known_element_dimensions) + self.form.cb_dimension.addItems(self.mesh_obj.getEnumerationsOfProperty("ElementDimension")) - self.form.cb_order.addItems(mesh_gmsh.MeshGmsh.known_element_orders) + self.form.cb_order.addItems(self.mesh_obj.getEnumerationsOfProperty("ElementOrder")) self.get_mesh_params() self.get_active_analysis() @@ -195,7 +194,7 @@ class _TaskPanel: gmsh_mesh = gmshtools.GmshTools(self.mesh_obj, self.analysis) QApplication.setOverrideCursor(Qt.WaitCursor) - part = self.mesh_obj.Part + part = self.mesh_obj.Shape if ( self.mesh_obj.MeshRegionList and part.Shape.ShapeType == "Compound" diff --git a/src/Mod/Fem/femtools/femutils.py b/src/Mod/Fem/femtools/femutils.py index ccc7d57a3a..468cb03c6e 100644 --- a/src/Mod/Fem/femtools/femutils.py +++ b/src/Mod/Fem/femtools/femutils.py @@ -244,23 +244,6 @@ def make_dir(specific_path): # ************************************************************************************************ # other -def get_part_to_mesh(mesh_obj): - """ - gmsh mesh object: the Attribute is Part - netgen mesh object: the Attribute is Shape - other mesh objects: do not have a Attribute which holds the part to mesh - """ - if is_derived_from(mesh_obj, "Fem::FemMeshGmsh"): - return mesh_obj.Part - elif is_derived_from(mesh_obj, "Fem::FemMeshShapeNetgenObject"): - return mesh_obj.Shape - else: - return None - # TODO: the Attributes should be named with the same name - # should it be Shape or Part? - # IMHO Part since the Attributes references the document object and not a Shape - - def getBoundBoxOfAllDocumentShapes(doc): """Calculate bounding box containing all objects inside *doc*.