X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH_SWIG%2FsmeshDC.py;h=94ffee1c925f7025151a07183b176c0673a873d9;hb=68f20ecf75a5a1d60883b99499a9829816bb0bc1;hp=4789415c96b2ac875e48a97c99d1d6f60d907771;hpb=2daa321efae3d0c6ce41199fa5a2482630d505d9;p=modules%2Fsmesh.git diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index 4789415c9..94ffee1c9 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -1,8 +1,5 @@ # -*- coding: iso-8859-1 -*- -# Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE -# -# Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -# CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +# Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -20,6 +17,7 @@ # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + # File : smesh.py # Author : Francis KLOSS, OCC # Module : SMESH @@ -99,6 +97,7 @@ from SMESH import * import StdMeshers import SALOME +import SALOMEDS # import NETGENPlugin module if possible noNETGENPlugin = 0 @@ -162,6 +161,8 @@ Hexa = 8 Hexotic = 9 BLSURF = 10 GHS3DPRL = 11 +QUADRANGLE = 0 +RADIAL_QUAD = 1 # MirrorType enumeration POINT = SMESH_MeshEditor.POINT @@ -194,6 +195,13 @@ DefaultSize, DefaultGeom, Custom = 0,0,1 PrecisionConfusion = 1e-07 +# TopAbs_State enumeration +[TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN] = range(4) + +# Methods of splitting a hexahedron into tetrahedra +Hex_5Tet, Hex_6Tet, Hex_24Tet = 1, 2, 3 + + ## Converts an angle from degrees to radians def DegreesToRadians(AngleInDegrees): from math import pi @@ -391,13 +399,33 @@ NO_NAME = "NoName" ## Gets object name def GetName(obj): - ior = salome.orb.object_to_string(obj) - sobj = salome.myStudy.FindObjectIOR(ior) - if sobj is None: - return NO_NAME - else: - attr = sobj.FindAttribute("AttributeName")[1] - return attr.Value() + if obj: + # object not null + if isinstance(obj, SALOMEDS._objref_SObject): + # study object + return obj.GetName() + ior = salome.orb.object_to_string(obj) + if ior: + # CORBA object + studies = salome.myStudyManager.GetOpenStudies() + for sname in studies: + s = salome.myStudyManager.GetStudyByName(sname) + if not s: continue + sobj = s.FindObjectIOR(ior) + if not sobj: continue + return sobj.GetName() + if hasattr(obj, "GetName"): + # unknown CORBA object, having GetName() method + return obj.GetName() + else: + # unknown CORBA object, no GetName() method + return NO_NAME + pass + if hasattr(obj, "GetName"): + # unknown non-CORBA object, having GetName() method + return obj.GetName() + pass + raise RuntimeError, "Null or invalid object" ## Prints error message if a hypothesis was not assigned. def TreatHypoStatus(status, hypName, geomName, isAlgo): @@ -413,6 +441,7 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo): elif status == HYP_NOTCONFORM : reason = "a non-conform mesh would be built" elif status == HYP_ALREADY_EXIST : + if isAlgo: return # it does not influence anything reason = hypType + " of the same dimension is already assigned to this shape" elif status == HYP_BAD_DIM : reason = hypType + " mismatches the shape" @@ -432,10 +461,12 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo): return hypName = '"' + hypName + '"' geomName= '"' + geomName+ '"' - if status < HYP_UNKNOWN_FATAL: + if status < HYP_UNKNOWN_FATAL and not geomName =='""': print hypName, "was assigned to", geomName,"but", reason - else: + elif not geomName == '""': print hypName, "was not assigned to",geomName,":", reason + else: + print hypName, "was not assigned:", reason pass ## Check meshing plugin availability @@ -485,6 +516,20 @@ class smeshDC(SMESH._objref_SMESH_Gen): def EnumToLong(self,theItem): return theItem._v + ## Returns a string representation of the color. + # To be used with filters. + # @param c color value (SALOMEDS.Color) + # @ingroup l1_controls + def ColorToString(self,c): + val = "" + if isinstance(c, SALOMEDS.Color): + val = "%s;%s;%s" % (c.R, c.G, c.B) + elif isinstance(c, str): + val = c + else: + raise ValueError, "Color value should be of string or SALOMEDS.Color type" + return val + ## Gets PointStruct from vertex # @param theVertex a GEOM object(vertex) # @return SMESH.PointStruct @@ -645,6 +690,9 @@ class smeshDC(SMESH._objref_SMESH_Gen): def Concatenate( self, meshes, uniteIdenticalGroups, mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False): mergeTolerance,Parameters = geompyDC.ParseParameters(mergeTolerance) + for i,m in enumerate(meshes): + if isinstance(m, Mesh): + meshes[i] = m.GetMesh() if allGroups: aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups( self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance) @@ -725,8 +773,28 @@ class smeshDC(SMESH._objref_SMESH_Gen): else: print "Error: The treshold should be a string." return None + elif CritType == FT_ElemGeomType: + # Checks the treshold + try: + aCriterion.Threshold = self.EnumToLong(aTreshold) + except: + if isinstance(aTreshold, int): + aCriterion.Threshold = aTreshold + else: + print "Error: The treshold should be an integer or SMESH.GeometryType." + return None + pass + pass + elif CritType == FT_GroupColor: + # Checks the treshold + try: + aCriterion.ThresholdStr = self.ColorToString(aTreshold) + except: + print "Error: The threshold value should be of SALOMEDS.Color type" + return None + pass elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_BadOrientedVolume, FT_FreeNodes, - FT_FreeFaces, FT_ElemGeomType, FT_GroupColor]: + FT_FreeFaces, FT_LinearOrQuadratic]: # At this point the treshold is unnecessary if aTreshold == FT_LogicalNOT: aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT) @@ -1031,17 +1099,20 @@ class Mesh: if (isinstance(algo, geompyDC.GEOM._objref_GEOM_Object)): geom = algo algo = MEFISTO - return Mesh_Triangle(self, algo, geom) ## Creates a quadrangle 2D algorithm for faces. # If the optional \a geom parameter is not set, this algorithm is global. # \n Otherwise, this algorithm defines a submesh based on \a geom subshape. # @param geom If defined, the subshape to be meshed (GEOM_Object) + # @param algo values are: smesh.QUADRANGLE || smesh.RADIAL_QUAD # @return an instance of Mesh_Quadrangle algorithm # @ingroup l3_algos_basic - def Quadrangle(self, geom=0): - return Mesh_Quadrangle(self, geom) + def Quadrangle(self, geom=0, algo=QUADRANGLE): + if algo==RADIAL_QUAD: + return Mesh_RadialQuadrangle1D2D(self,geom) + else: + return Mesh_Quadrangle(self, geom) ## Creates a tetrahedron 3D algorithm for solids. # The parameter \a algo permits to choose the algorithm: NETGEN or GHS3D @@ -1134,9 +1205,13 @@ class Mesh: ## Computes the mesh and returns the status of the computation + # @param geom geomtrical shape on which mesh data should be computed + # @param discardModifs if True and the mesh has been edited since + # a last total re-compute and that may prevent successful partial re-compute, + # then the mesh is cleaned before Compute() # @return True or False # @ingroup l2_construct - def Compute(self, geom=0): + def Compute(self, geom=0, discardModifs=False): if geom == 0 or not isinstance(geom, geompyDC.GEOM._objref_GEOM_Object): if self.geom == 0: geom = self.mesh.GetShapeToMesh() @@ -1144,6 +1219,8 @@ class Mesh: geom = self.geom ok = False try: + if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693 + self.mesh.Clear() ok = self.smeshpyD.Compute(self.mesh, geom) except SALOME.SALOME_Exception, ex: print "Mesh computation failed, exception caught:" @@ -1153,8 +1230,64 @@ class Mesh: print "Mesh computation failed, exception caught:" traceback.print_exc() if True:#not ok: - errors = self.smeshpyD.GetAlgoState( self.mesh, geom ) allReasons = "" + + # Treat compute errors + computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom ) + for err in computeErrors: + shapeText = "" + if self.mesh.HasShapeToMesh(): + try: + mainIOR = salome.orb.object_to_string(geom) + for sname in salome.myStudyManager.GetOpenStudies(): + s = salome.myStudyManager.GetStudyByName(sname) + if not s: continue + mainSO = s.FindObjectIOR(mainIOR) + if not mainSO: continue + if err.subShapeID == 1: + shapeText = ' on "%s"' % mainSO.GetName() + subIt = s.NewChildIterator(mainSO) + while subIt.More(): + subSO = subIt.Value() + subIt.Next() + obj = subSO.GetObject() + if not obj: continue + go = obj._narrow( geompyDC.GEOM._objref_GEOM_Object ) + if not go: continue + ids = go.GetSubShapeIndices() + if len(ids) == 1 and ids[0] == err.subShapeID: + shapeText = ' on "%s"' % subSO.GetName() + break + if not shapeText: + shape = self.geompyD.GetSubShape( geom, [err.subShapeID]) + if shape: + shapeText = " on %s #%s" % (shape.GetShapeType(), err.subShapeID) + else: + shapeText = " on subshape #%s" % (err.subShapeID) + except: + shapeText = " on subshape #%s" % (err.subShapeID) + errText = "" + stdErrors = ["OK", #COMPERR_OK + "Invalid input mesh", #COMPERR_BAD_INPUT_MESH + "std::exception", #COMPERR_STD_EXCEPTION + "OCC exception", #COMPERR_OCC_EXCEPTION + "SALOME exception", #COMPERR_SLM_EXCEPTION + "Unknown exception", #COMPERR_EXCEPTION + "Memory allocation problem", #COMPERR_MEMORY_PB + "Algorithm failed", #COMPERR_ALGO_FAILED + "Unexpected geometry"]#COMPERR_BAD_SHAPE + if err.code > 0: + if err.code < len(stdErrors): errText = stdErrors[err.code] + else: + errText = "code %s" % -err.code + if errText: errText += ". " + errText += err.comment + if allReasons != "":allReasons += "\n" + allReasons += '"%s" failed%s. Error: %s' %(err.algoName, shapeText, errText) + pass + + # Treat hyp errors + errors = self.smeshpyD.GetAlgoState( self.mesh, geom ) for err in errors: if err.isGlobalAlgo: glob = "global" @@ -1180,9 +1313,7 @@ class Mesh: reason = "For unknown reason."+\ " Revise Mesh.Compute() implementation in smeshDC.py!" pass - if allReasons != "": - allReasons += "\n" - pass + if allReasons != "":allReasons += "\n" allReasons += reason pass if allReasons != "": @@ -1201,6 +1332,18 @@ class Mesh: pass return ok + ## Return submesh objects list in meshing order + # @return list of list of submesh objects + # @ingroup l2_construct + def GetMeshOrder(self): + return self.mesh.GetMeshOrder() + + ## Return submesh objects list in meshing order + # @return list of list of submesh objects + # @ingroup l2_construct + def SetMeshOrder(self, submeshes): + return self.mesh.SetMeshOrder(submeshes) + ## Removes all nodes and elements # @ingroup l2_construct def Clear(self): @@ -1271,7 +1414,11 @@ class Mesh: pass status = self.mesh.AddHypothesis(geom, hyp) isAlgo = hyp._narrow( SMESH_Algo ) - TreatHypoStatus( status, GetName( hyp ), GetName( geom ), isAlgo ) + hyp_name = GetName( hyp ) + geom_name = "" + if geom: + geom_name = GetName( geom ) + TreatHypoStatus( status, hyp_name, geom_name, isAlgo ) return status ## Unassigns a hypothesis @@ -1316,25 +1463,29 @@ class Mesh: def Group(self, grp, name=""): return self.GroupOnGeom(grp, name) - ## Deprecated, used only for compatibility! Please, use ExportMED() method instead. + ## Deprecated, used only for compatibility! Please, use ExportToMEDX() method instead. # Exports the mesh in a file in MED format and chooses the \a version of MED format + ## allowing to overwrite the file if it exists or add the exported data to its contents # @param f the file name # @param version values are SMESH.MED_V2_1, SMESH.MED_V2_2 # @param opt boolean parameter for creating/not creating # the groups Group_On_All_Nodes, Group_On_All_Faces, ... + # @param overwrite boolean parameter for overwriting/not overwriting the file # @ingroup l2_impexp - def ExportToMED(self, f, version, opt=0): - self.mesh.ExportToMED(f, opt, version) + def ExportToMED(self, f, version, opt=0, overwrite=1): + self.mesh.ExportToMEDX(f, opt, version, overwrite) - ## Exports the mesh in a file in MED format + ## Exports the mesh in a file in MED format and chooses the \a version of MED format + ## allowing to overwrite the file if it exists or add the exported data to its contents # @param f is the file name # @param auto_groups boolean parameter for creating/not creating # the groups Group_On_All_Nodes, Group_On_All_Faces, ... ; # the typical use is auto_groups=false. # @param version MED format version(MED_V2_1 or MED_V2_2) + # @param overwrite boolean parameter for overwriting/not overwriting the file # @ingroup l2_impexp - def ExportMED(self, f, auto_groups=0, version=MED_V2_2): - self.mesh.ExportToMED(f, auto_groups, version) + def ExportMED(self, f, auto_groups=0, version=MED_V2_2, overwrite=1): + self.mesh.ExportToMEDX(f, auto_groups, version, overwrite) ## Exports the mesh in a file in DAT format # @param f the file name @@ -1855,7 +2006,7 @@ class Mesh: return self.mesh.GetElementsId() ## Returns the list of IDs of mesh elements with the given type - # @param elementType the required type of elements + # @param elementType the required type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE or SMESH.VOLUME) # @return list of integer values # @ingroup l1_meshinfo def GetElementsByType(self, elementType): @@ -1876,6 +2027,12 @@ class Mesh: def GetElementType(self, id, iselem): return self.mesh.GetElementType(id, iselem) + ## Returns the geometric type of mesh element + # @return the value from SMESH::EntityType enumeration + # @ingroup l1_meshinfo + def GetElementGeomType(self, id): + return self.mesh.GetElementGeomType(id) + ## Returns the list of submesh elements IDs # @param Shape a geom object(subshape) IOR # Shape must be the subshape of a ShapeToMesh() @@ -1999,6 +2156,16 @@ class Mesh: def ElemNbFaces(self, id): return self.mesh.ElemNbFaces(id) + ## Returns nodes of given face (counted from zero) for given volumic element. + # @ingroup l1_meshinfo + def GetElemFaceNodes(self,elemId, faceIndex): + return self.mesh.GetElemFaceNodes(elemId, faceIndex) + + ## Returns an element based on all given nodes. + # @ingroup l1_meshinfo + def FindElementByNodes(self,nodes): + return self.mesh.FindElementByNodes(nodes) + ## Returns true if the given element is a polygon # @ingroup l1_meshinfo def IsPoly(self, id): @@ -2034,6 +2201,12 @@ class Mesh: def RemoveNodes(self, IDsOfNodes): return self.editor.RemoveNodes(IDsOfNodes) + ## Removes all orphan (free) nodes from mesh + # @return number of the removed nodes + # @ingroup l2_modif_del + def RemoveOrphanNodes(self): + return self.editor.RemoveOrphanNodes() + ## Add a node to the mesh by coordinates # @return Id of the new node # @ingroup l2_modif_add @@ -2241,6 +2414,11 @@ class Mesh: def FindElementsByPoint(self, x, y, z, elementType = SMESH.ALL): return self.editor.FindElementsByPoint(x, y, z, elementType) + # Return point state in a closed 2D mesh in terms of TopAbs_State enumeration. + # TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails. + + def GetPointState(self, x, y, z): + return self.editor.GetPointState(x, y, z) ## Finds the node closest to a point and moves it to a point location # @param x the X coordinate of a point @@ -2373,6 +2551,18 @@ class Mesh: def BestSplit (self, IDOfQuad, theCriterion): return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion)) + ## Splits volumic elements into tetrahedrons + # @param elemIDs either list of elements or mesh or group or submesh + # @param method flags passing splitting method: Hex_5Tet, Hex_6Tet, Hex_24Tet + # Hex_5Tet - split the hexahedron into 5 tetrahedrons, etc + # @ingroup l2_modif_cutquadr + def SplitVolumesIntoTetra(self, elemIDs, method=Hex_5Tet ): + if isinstance( elemIDs, Mesh ): + elemIDs = elemIDs.GetMesh() + if ( isinstance( elemIDs, list )): + elemIDs = self.editor.MakeIDSource(elemIDs, SMESH.VOLUME) + self.editor.SplitVolumesIntoTetra(elemIDs, method) + ## Splits quadrangle faces near triangular facets of volumes # # @ingroup l1_auxiliary @@ -2585,6 +2775,9 @@ class Mesh: ## Converts the mesh to quadratic, deletes old elements, replacing # them with quadratic with the same id. + # @param theForce3d new node creation method: + # 0 - the medium node lies at the geometrical edge from which the mesh element is built + # 1 - the medium node lies at the middle of the line segments connecting start and end node of a mesh element # @ingroup l2_modif_tofromqu def ConvertToQuadratic(self, theForce3d): self.editor.ConvertToQuadratic(theForce3d) @@ -2602,7 +2795,30 @@ class Mesh: # @ingroup l2_modif_edit def Make2DMeshFrom3D(self): return self.editor. Make2DMeshFrom3D() - + + ## Creates missing boundary elements + # @param elements - elements whose boundary is to be checked: + # mesh, group, sub-mesh or list of elements + # @param dimension - defines type of boundary elements to create: + # SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D + # @param groupName - a name of group to store created boundary elements in, + # "" means not to create the group + # @param meshName - a name of new mesh to store created boundary elements in, + # "" means not to create the new mesh + # @param toCopyElements - if true, the checked elements will be copied into the new mesh + # @param toCopyExistingBondary - if true, not only new but also pre-existing + # boundary elements will be copied into the new mesh + # @return tuple (mesh, group) where bondary elements were added to + # @ingroup l2_modif_edit + def MakeBoundaryMesh(self, elements, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="", + toCopyElements=False, toCopyExistingBondary=False): + if isinstance( elements, Mesh ): + elements = elements.GetMesh() + if ( isinstance( elements, list )): + elements = self.editor.MakeIDSource(elements, SMESH.ALL) + return self.editor.MakeBoundaryMesh(elements,dimension,groupName,meshName, + toCopyElements,toCopyExistingBondary) + ## Renumber mesh nodes # @ingroup l2_modif_renumber def RenumberNodes(self): @@ -3227,6 +3443,51 @@ class Mesh: mesh.SetParameters(Parameters) return Mesh( self.smeshpyD, self.geompyD, mesh ) + + + ## Scales the object + # @param theObject - the object to translate (mesh, submesh, or group) + # @param thePoint - base point for scale + # @param theScaleFact - list of 1-3 scale factors for axises + # @param Copy - allows copying the translated elements + # @param MakeGroups - forces the generation of new groups from existing + # ones (if Copy) + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, + # empty list otherwise + def Scale(self, theObject, thePoint, theScaleFact, Copy, MakeGroups=False): + if ( isinstance( theObject, Mesh )): + theObject = theObject.GetMesh() + if ( isinstance( theObject, list )): + theObject = self.editor.MakeIDSource(theObject, SMESH.ALL) + + thePoint, Parameters = ParsePointStruct(thePoint) + self.mesh.SetParameters(Parameters) + + if Copy and MakeGroups: + return self.editor.ScaleMakeGroups(theObject, thePoint, theScaleFact) + self.editor.Scale(theObject, thePoint, theScaleFact, Copy) + return [] + + ## Creates a new mesh from the translated object + # @param theObject - the object to translate (mesh, submesh, or group) + # @param thePoint - base point for scale + # @param theScaleFact - list of 1-3 scale factors for axises + # @param MakeGroups - forces the generation of new groups from existing ones + # @param NewMeshName - the name of the newly created mesh + # @return instance of Mesh class + def ScaleMakeMesh(self, theObject, thePoint, theScaleFact, MakeGroups=False, NewMeshName=""): + if (isinstance(theObject, Mesh)): + theObject = theObject.GetMesh() + if ( isinstance( theObject, list )): + theObject = self.editor.MakeIDSource(theObject,SMESH.ALL) + + mesh = self.editor.ScaleMakeMesh(theObject, thePoint, theScaleFact, + MakeGroups, NewMeshName) + #mesh.SetParameters(Parameters) + return Mesh( self.smeshpyD, self.geompyD, mesh ) + + + ## Rotates the elements # @param IDsOfElements list of elements ids # @param Axis the axis of rotation (AxisStruct or geom line) @@ -3343,10 +3604,17 @@ class Mesh: ## Finds groups of ajacent nodes within Tolerance. # @param Tolerance the value of tolerance # @param SubMeshOrGroup SubMesh or Group + # @param exceptNodes list of either SubMeshes, Groups or node IDs to exclude from search # @return the list of groups of nodes # @ingroup l2_modif_trsf - def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance): - return self.editor.FindCoincidentNodesOnPart(SubMeshOrGroup, Tolerance) + def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance, exceptNodes=[]): + if (isinstance( SubMeshOrGroup, Mesh )): + SubMeshOrGroup = SubMeshOrGroup.GetMesh() + if not isinstance( ExceptSubMeshOrGroups, list): + ExceptSubMeshOrGroups = [ ExceptSubMeshOrGroups ] + if ExceptSubMeshOrGroups and isinstance( ExceptSubMeshOrGroups[0], int): + ExceptSubMeshOrGroups = [ self.editor.MakeIDSource( ExceptSubMeshOrGroups, SMESH.NODE)] + return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,ExceptSubMeshOrGroups) ## Merges nodes # @param GroupsOfNodes the list of groups of nodes @@ -3451,7 +3719,7 @@ class Mesh: ## Creates a hole in a mesh by doubling the nodes of some particular elements # This method provided for convenience works as DoubleNodes() described above. - # @param theNodes identifiers of node to be doubled + # @param theNodeId identifiers of node to be doubled # @param theModifiedElems identifiers of elements to be updated # @return TRUE if operation has been completed successfully, FALSE otherwise # @ingroup l2_modif_edit @@ -3462,11 +3730,15 @@ class Mesh: # This method provided for convenience works as DoubleNodes() described above. # @param theNodes group of nodes to be doubled # @param theModifiedElems group of elements to be updated. - # @return TRUE if operation has been completed successfully, FALSE otherwise + # @param theMakeGroup forces the generation of a group containing new nodes. + # @return TRUE or a created group if operation has been completed successfully, + # FALSE or None otherwise # @ingroup l2_modif_edit - def DoubleNodeGroup(self, theNodes, theModifiedElems): + def DoubleNodeGroup(self, theNodes, theModifiedElems, theMakeGroup=False): + if theMakeGroup: + return self.editor.DoubleNodeGroupNew(theNodes, theModifiedElems) return self.editor.DoubleNodeGroup(theNodes, theModifiedElems) - + ## Creates a hole in a mesh by doubling the nodes of some particular elements # This method provided for convenience works as DoubleNodes() described above. # @param theNodes list of groups of nodes to be doubled @@ -3505,10 +3777,13 @@ class Mesh: # @param theNodesNot - group of nodes not to replicated # @param theAffectedElems - group of elements to which the replicated nodes # should be associated to. + # @param theMakeGroup forces the generation of a group containing new elements. # @ingroup l2_modif_edit - def DoubleNodeElemGroup(self, theElems, theNodesNot, theAffectedElems): + def DoubleNodeElemGroup(self, theElems, theNodesNot, theAffectedElems, theMakeGroup=False): + if theMakeGroup: + return self.editor.DoubleNodeElemGroupNew(theElems, theNodesNot, theAffectedElems) return self.editor.DoubleNodeElemGroup(theElems, theNodesNot, theAffectedElems) - + ## Creates a hole in a mesh by doubling the nodes of some particular elements # This method provided for convenience works as DoubleNodes() described above. # @param theElems - group of of elements (edges or faces) to be replicated @@ -3518,7 +3793,7 @@ class Mesh: # The replicated nodes should be associated to affected elements. # @ingroup l2_modif_edit def DoubleNodeElemGroupInRegion(self, theElems, theNodesNot, theShape): - return self.editor.DoubleNodeElemGroup(theElems, theNodesNot, theShape) + return self.editor.DoubleNodeElemGroupInRegion(theElems, theNodesNot, theShape) ## Creates a hole in a mesh by doubling the nodes of some particular elements # This method provided for convenience works as DoubleNodes() described above. @@ -3685,19 +3960,23 @@ class Mesh_Algorithm: raise RuntimeError, "Attemp to create " + algo + " algoritm on None shape" self.mesh = mesh piece = mesh.geom + name = "" if not geom: self.geom = piece else: self.geom = geom - name = GetName(geom) - if name==NO_NAME: + try: + name = GetName(geom) + pass + except: name = mesh.geompyD.SubShapeName(geom, piece) mesh.geompyD.addToStudyInFather(piece, geom, name) + pass self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName()) self.algo = algo status = mesh.mesh.AddHypothesis(self.geom, self.algo) - TreatHypoStatus( status, algo.GetName(), GetName(self.geom), True ) + TreatHypoStatus( status, algo.GetName(), name, True ) def CompareHyp (self, hyp, args): print "CompareHyp is not implemented for ", self.__class__.__name__, ":", hyp.GetName() @@ -3902,10 +4181,13 @@ class Mesh_Segment(Mesh_Algorithm): def FixedPoints1D(self, points, nbSegs=[1], reversedEdges=[], UseExisting=0): if not isinstance(reversedEdges,list): #old version script, before adding reversedEdges reversedEdges, UseExisting = [], reversedEdges + if reversedEdges and isinstance( reversedEdges[0], geompyDC.GEOM._objref_GEOM_Object ): + for i in range( len( reversedEdges )): + reversedEdges[i] = self.mesh.geompyD.GetSubShapeID(self.mesh.geom, reversedEdges[i] ) entry = self.MainShapeEntry() hyp = self.Hypothesis("FixedPoints1D", [points, nbSegs, reversedEdges, entry], UseExisting=UseExisting, - CompareMethod=self.CompareArithmetic1D) + CompareMethod=self.CompareFixedPoints1D) hyp.SetPoints(points) hyp.SetNbSegments(nbSegs) hyp.SetReversedEdges(reversedEdges) @@ -4014,11 +4296,14 @@ class Mesh_Segment(Mesh_Algorithm): ### 0D algorithm if self.geom is None: raise RuntimeError, "Attemp to create SegmentAroundVertex_0D algoritm on None shape" - name = GetName(self.geom) - if name == NO_NAME: + try: + name = GetName(self.geom) + pass + except: piece = self.mesh.geom name = self.mesh.geompyD.SubShapeName(self.geom, piece) self.mesh.geompyD.addToStudyInFather(piece, self.geom, name) + pass algo = self.FindAlgorithm("SegmentAroundVertex_0D", self.mesh.smeshpyD) if algo is None: algo = self.mesh.smeshpyD.CreateHypothesis("SegmentAroundVertex_0D", "libStdMeshersEngine.so") @@ -4192,7 +4477,7 @@ class Mesh_Triangle(Mesh_Algorithm): self.Parameters().SetPhyMax(theVal) ## Sets a way to define maximum angular deflection of mesh from CAD model. - # @param theGeometricMesh is: DefaultGeom or Custom + # @param theGeometricMesh is: 0 (None) or 1 (Custom) # @ingroup l3_hypos_blsurf def SetGeometricMesh(self, theGeometricMesh=0): # Parameter of BLSURF algo @@ -4415,6 +4700,25 @@ class Mesh_Quadrangle(Mesh_Algorithm): CompareMethod=self.CompareEqualHyp) return hyp + ## Defines "QuadrangleParams" hypothesis + # @param vertex: vertex of a trilateral geometrical face, around which triangles + # will be created while other elements will be quadrangles. + # Vertex can be either a GEOM_Object or a vertex ID within the + # shape to mesh + # @param UseExisting: if ==true - searches for the existing hypothesis created with + # the same parameters, else (default) - creates a new one + # + # @ingroup l3_hypos_additi + def TriangleVertex(self, vertex, UseExisting=0): + vertexID = vertex + if isinstance( vertexID, geompyDC.GEOM._objref_GEOM_Object ): + vertexID = self.mesh.geompyD.GetSubShapeID( self.mesh.geom, vertex ) + hyp = self.Hypothesis("QuadrangleParams", [vertexID], UseExisting = UseExisting, + CompareMethod=lambda hyp,args: hyp.GetTriaVertex()==args[0]) + hyp.SetTriaVertex( vertexID ) + return hyp + + # Public class: Mesh_Tetrahedron # ------------------------------ @@ -4912,6 +5216,7 @@ class Mesh_RadialPrism3D(Mesh_Algorithm): self.mesh.GetMesh().RemoveHypothesis( self.geom, self.nbLayers ) self.mesh.GetMesh().AddHypothesis( self.geom, self.distribHyp ) study = self.mesh.smeshpyD.GetCurrentStudy() # prevents publishing own 1D hypothesis + self.mesh.smeshpyD.SetCurrentStudy( None ) hyp = self.mesh.smeshpyD.CreateHypothesis(hypType, so) self.mesh.smeshpyD.SetCurrentStudy( study ) # enables publishing self.distribHyp.SetLayerDistribution( hyp ) @@ -4998,7 +5303,7 @@ class Mesh_RadialQuadrangle1D2D(Mesh_Algorithm): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, "RadialQuadrangle_1D2D") - self.distribHyp = self.Hypothesis("LayerDistribution2D", UseExisting=0) + self.distribHyp = None #self.Hypothesis("LayerDistribution2D", UseExisting=0) self.nbLayers = None ## Return 2D hypothesis holding the 1D one @@ -5009,21 +5314,26 @@ class Mesh_RadialQuadrangle1D2D(Mesh_Algorithm): # hypothesis. Returns the created hypothesis def OwnHypothesis(self, hypType, args=[], so="libStdMeshersEngine.so"): #print "OwnHypothesis",hypType - if not self.nbLayers is None: + if self.nbLayers: self.mesh.GetMesh().RemoveHypothesis( self.geom, self.nbLayers ) + if self.distribHyp is None: + self.distribHyp = self.Hypothesis("LayerDistribution2D", UseExisting=0) + else: self.mesh.GetMesh().AddHypothesis( self.geom, self.distribHyp ) study = self.mesh.smeshpyD.GetCurrentStudy() # prevents publishing own 1D hypothesis + self.mesh.smeshpyD.SetCurrentStudy( None ) hyp = self.mesh.smeshpyD.CreateHypothesis(hypType, so) self.mesh.smeshpyD.SetCurrentStudy( study ) # enables publishing self.distribHyp.SetLayerDistribution( hyp ) return hyp - ## Defines "NumberOfLayers2D" hypothesis, specifying the number of layers + ## Defines "NumberOfLayers" hypothesis, specifying the number of layers # @param n number of layers # @param UseExisting if ==true - searches for the existing hypothesis created with # the same parameters, else (default) - creates a new one - def NumberOfLayers2D(self, n, UseExisting=0): - self.mesh.GetMesh().RemoveHypothesis( self.geom, self.distribHyp ) + def NumberOfLayers(self, n, UseExisting=0): + if self.distribHyp: + self.mesh.GetMesh().RemoveHypothesis( self.geom, self.distribHyp ) self.nbLayers = self.Hypothesis("NumberOfLayers2D", [n], UseExisting=UseExisting, CompareMethod=self.CompareNumberOfLayers) self.nbLayers.SetNumberOfLayers( n )