├── README.md ├── GeomGroup.py ├── SelectInternalContour.py ├── PassGroups.py ├── CreateBeams.py ├── 3DContact.py ├── GeomFilterGroup.py └── GMSHMesh.py /README.md: -------------------------------------------------------------------------------- 1 | A script collection of different utilities for salome 2 | 3 | 4 | # Contact.py 5 | 6 | Script to automatically detect contacts of two o more parts. 7 | 8 | Video demostration: https://www.youtube.com/watch?v=QTaSs1JFrHw 9 | 10 | # Create Beams 11 | 12 | Script to create beams for bolts easily. 13 | 14 | # GeomFilterGroup 15 | 16 | Creating Geometry groups in the GEOM module using features and properties of another group. 17 | 18 | Video demostration: https://www.youtube.com/watch?v=Nil1zQtyf_8 19 | 20 | # GeomGroup 21 | 22 | Create mesh groups from geometry, even if the link does not exist. 23 | 24 | # PassGroups 25 | 26 | After an operation in the geometry module the groups are lost and must be done again. With this script you can pass the groups (or the majority) after performing an operation to the part. 27 | 28 | # SelectInternalContour 29 | 30 | Auto-selects the internal contour of a part. You have 2 options, select only the internal surface and set it as a group (for FEM), or create a new part with the control volume (for CFD). -------------------------------------------------------------------------------- /GeomGroup.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import salome 3 | 4 | salome.salome_init() 5 | theStudy = salome.myStudy 6 | import GEOM 7 | from salome.geom import geomBuilder 8 | import math 9 | import SALOMEDS 10 | import SMESH, SALOMEDS 11 | from salome.smesh import smeshBuilder 12 | smesh = smeshBuilder.New(theStudy) 13 | 14 | # Number selected objects 15 | selCount = salome.sg.SelectedCount() 16 | # Mesh selection 17 | selected = salome.sg.getSelected(0) 18 | Mesh_1 = salome.myStudy.FindObjectID(selected).GetObject() 19 | 20 | # Proceed if are two objects selected 21 | for i in range(1,selCount): 22 | try: 23 | selected_i = salome.sg.getSelected(i) 24 | selobj_i = salome.myStudy.FindObjectID(selected_i).GetObject() 25 | name_geom_group = selobj_i.GetName() 26 | elem = str(selobj_i.GetMaxShapeType()) 27 | if elem == "FACE": 28 | type_g = SMESH.FACE 29 | if elem == "EDGE": 30 | type_g = SMESH.EDGE 31 | if elem == "SOLID": 32 | type_g = SMESH.VOLUME 33 | # Criterios 34 | aCriteria = [] 35 | aCriterion1 = smesh.GetCriterion(type_g,SMESH.FT_BelongToGeom,SMESH.FT_Undefined,name_geom_group) 36 | aCriteria.append(aCriterion1) 37 | aFilter_1 = smesh.GetFilterFromCriteria(aCriteria) 38 | aFilter_1.SetMesh(Mesh_1.GetMesh()) 39 | Group_1 = Mesh_1.CreateGroupFromFilter( type_g, name_geom_group, aFilter_1 ) 40 | smesh.SetName(Group_1, name_geom_group) 41 | except: 42 | print "Error" 43 | print "Error con el grupo" + name_geom_group 44 | 45 | 46 | if salome.sg.hasDesktop(): 47 | salome.sg.updateObjBrowser(1) 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /SelectInternalContour.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | External_Volume_Result = True 5 | 6 | # Import the necessary 7 | import salome 8 | salome.salome_init() 9 | import GEOM 10 | import SALOMEDS 11 | from salome.geom import geomBuilder 12 | geompy = geomBuilder.New(salome.myStudy) 13 | 14 | # Number selected objects 15 | selCount = salome.sg.SelectedCount() 16 | 17 | # Solid 18 | selected = salome.sg.getSelected(0) # First selection 19 | selobj = salome.myStudy.FindObjectID(selected).GetObject() # Reference object 20 | 21 | # Internal Face 22 | selected2 = salome.sg.getSelected(1) # Second selection 23 | selobj2 = salome.myStudy.FindObjectID(selected2).GetObject() # Objetive object 24 | 25 | 26 | RemoveIntWires_1 = geompy.SuppressInternalWires(selobj, []) 27 | SuppressHoles_1 = geompy.SuppressHoles(RemoveIntWires_1, []) 28 | list_shell = geompy.ExtractShapes(SuppressHoles_1, geompy.ShapeType["SHELL"], True) 29 | n_shells = len(list_shell) 30 | 31 | if selCount == 2: 32 | for i in range(0,n_shells): 33 | isOk, res1, res2 = geompy.FastIntersect(list_shell[i], selobj2, 0) 34 | if isOk > 0: 35 | common1 = geompy.MakeCommon(selobj2, list_shell[i]) 36 | props = geompy.BasicProperties(common1) 37 | area_com = props[1] 38 | if area_com > 0: 39 | if External_Volume_Result == True: 40 | volume = geompy.MakeCompound([list_shell[i]]) 41 | geompy.addToStudy( volume, 'InternalVolume' ) 42 | gg = salome.ImportComponentGUI("GEOM") 43 | volume.SetColor(SALOMEDS.Color(1,0,0)) 44 | else: 45 | Group_ob = geompy.CreateGroup(selobj, geompy.ShapeType["FACE"]) 46 | list_faces = geompy.ExtractShapes(list_shell[i], geompy.ShapeType["FACE"], True) 47 | nlist = len(list_faces) 48 | for i in range(0,nlist): 49 | try: 50 | ID = geompy.GetSubShapeID(selobj, list_faces[i]) 51 | geompy.AddObject(Group_ob, ID) 52 | except: 53 | pass 54 | resGroup = geompy.addToStudyInFather(selobj, Group_ob, 'InternalSurface') 55 | gg = salome.ImportComponentGUI("GEOM") 56 | gg.setColor(resGroup,255,0,0) 57 | gg.createAndDisplayGO(resGroup) 58 | 59 | if salome.sg.hasDesktop(): 60 | salome.sg.updateObjBrowser(True) 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /PassGroups.py: -------------------------------------------------------------------------------- 1 | ###### Pass groups from objects ### 2 | 3 | # Import the necessary 4 | import salome 5 | salome.salome_init() 6 | import GEOM 7 | from salome.geom import geomBuilder 8 | geompy = geomBuilder.New(salome.myStudy) 9 | 10 | # Number selected objects 11 | selCount = salome.sg.SelectedCount() 12 | 13 | # Reference object and its groups 14 | selected = salome.sg.getSelected(0) # First selection 15 | selobj = salome.myStudy.FindObjectID(selected).GetObject() # Reference object 16 | SubObjsAll = geompy.GetGroups(selobj) # Groups of Reference 17 | n_groups = len(SubObjsAll) # Number of groups 18 | 19 | # Objetive object 20 | selec_obj = salome.sg.getSelected(1) # Second selection 21 | Objetive = salome.myStudy.FindObjectID(selec_obj).GetObject() # Objetive object 22 | 23 | # Proceed if are two objects selected 24 | if selCount == 2: 25 | for i in range(0,n_groups): 26 | group_p = SubObjsAll[i] 27 | name_g = group_p.GetName() 28 | type_g = str(group_p.GetShapeType()) 29 | props = geompy.BasicProperties(group_p) 30 | if type_g == "COMPOUND": 31 | if props[2]==0: 32 | type_g = "FACE" 33 | if props[1]==0: 34 | type_g = "EDGE" 35 | if props[2]>0: 36 | type_g = "SOLID" 37 | elements = geompy.ExtractShapes(group_p, geompy.ShapeType[type_g], True) 38 | Group_ob = geompy.CreateGroup(Objetive, geompy.ShapeType[type_g]) 39 | try: 40 | if len(elements) > 1: 41 | for elem in elements: 42 | group_pass = geompy.GetSame(Objetive, elem) 43 | Element_ID = geompy.GetSubShapeID(Objetive, group_pass) 44 | geompy.AddObject(Group_ob, Element_ID) 45 | geompy.addToStudyInFather(Objetive, Group_ob, name_g) 46 | else: 47 | group_pass = geompy.GetSame(Objetive, group_p) 48 | Element_ID = geompy.GetSubShapeID(Objetive, group_pass) 49 | geompy.AddObject(Group_ob, Element_ID) 50 | geompy.addToStudyInFather( Objetive, Group_ob, name_g ) 51 | except: 52 | print "error con" + name_g 53 | else: 54 | print "Only select two objects" 55 | 56 | 57 | if salome.sg.hasDesktop(): 58 | salome.sg.updateObjBrowser(1) 59 | 60 | -------------------------------------------------------------------------------- /CreateBeams.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Beams 4 | 5 | import salome 6 | salome.salome_init() 7 | import GEOM 8 | from salome.geom import geomBuilder 9 | geompy = geomBuilder.New(salome.myStudy) 10 | gg = salome.ImportComponentGUI("GEOM") 11 | import math 12 | #from PyQt4 import QtGui,QtCore 13 | import SALOMEDS 14 | 15 | ## Options 16 | 17 | Solid = False 18 | Vertex = False 19 | 20 | 21 | ###### PROCEED ###### 22 | 23 | # selected Objects 24 | selected=salome.sg.getSelected(0) 25 | selobjID=salome.myStudy.FindObjectID(selected) 26 | selobj=selobjID.GetObject() 27 | selected1=salome.sg.getSelected(1) 28 | selobjID1=salome.myStudy.FindObjectID(selected1) 29 | selobj1=selobjID1.GetObject() 30 | 31 | Face_1 = geompy.MakeFaceWires(selobj, 1) 32 | 33 | Face_2 = geompy.MakeFaceWires(selobj1, 1) 34 | 35 | faces1 = geompy.ExtractShapes(Face_1, geompy.ShapeType["FACE"], True) 36 | 37 | if faces1 == []: 38 | faces1 = [Face_1] 39 | 40 | group1=list() 41 | 42 | faces2 = geompy.ExtractShapes(Face_2, geompy.ShapeType["FACE"], True) 43 | 44 | if faces2 == []: 45 | faces2 = [Face_2] 46 | 47 | group2=list() 48 | 49 | for i in faces1: 50 | Vertex_1 = geompy.MakeVertexOnSurface(i, 0.5, 0.5) 51 | #V1 = geompy.addToStudy( Vertex_1, 'V1' ) 52 | group1.append(Vertex_1) 53 | 54 | for i in faces2: 55 | Vertex_2 = geompy.MakeVertexOnSurface(i, 0.5, 0.5) 56 | #V2 = geompy.addToStudy( Vertex_2, 'V2' ) 57 | group2.append(Vertex_2) 58 | 59 | groupL=list() 60 | groupS=list() 61 | prop_c = geompy.BasicProperties(faces1[0]) 62 | import math 63 | r = prop_c[0]/(2.0*math.pi) 64 | 65 | 66 | if len(group1)==len(group2): 67 | for i in range(0,len(group1)): 68 | Line = geompy.MakeLineTwoPnt(group1[i], group2[i]) 69 | prop = geompy.BasicProperties(Line) 70 | Cylinder = geompy.MakeCylinder(group1[i], Line, r, prop[0]) 71 | groupL.append(Line) 72 | groupS.append(Cylinder) 73 | compound = geompy.MakeCompound(groupL) 74 | compoundS = geompy.MakeCompound(groupS) 75 | if Solid == False: 76 | beams = geompy.addToStudy( compound, 'Beams' ) 77 | gg.createAndDisplayGO(beams) 78 | else: 79 | beamsS = geompy.addToStudy( compoundS, 'BeamsS' ) 80 | gg.createAndDisplayGO(beamsS) 81 | else: 82 | print "The groups no same number of elements" 83 | 84 | 85 | #Cylinder_1 = geompy.MakeCylinder(O, OZ, 100, 300) 86 | 87 | if salome.sg.hasDesktop(): 88 | salome.sg.updateObjBrowser(1) 89 | salome.sg.UpdateView() 90 | 91 | -------------------------------------------------------------------------------- /3DContact.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Detect and create 3D contact script 3 | # License: LGPL v 2.1 4 | # Autor: Lucio Gomez (psicofil@gmail.com) 5 | # Version: 17/06/2017 6 | 7 | ## Import necesary Libreries 8 | import sys 9 | import salome 10 | from platform import system 11 | import subprocess 12 | import tempfile 13 | try: 14 | from PyQt4 import QtGui,QtCore 15 | from PyQt4.QtGui import * 16 | from PyQt4.QtCore import * 17 | except: 18 | from PyQt5.QtWidgets import QWidget, QMessageBox 19 | from PyQt5 import QtCore, QtGui 20 | import PyQt5.QtCore as QtCore 21 | from PyQt5.QtWidgets import * 22 | from PyQt5.QtCore import Qt 23 | 24 | import GEOM 25 | from salome.geom import geomBuilder 26 | import math 27 | 28 | # Detect current study 29 | theStudy = salome.myStudy 30 | geompy = geomBuilder.New(theStudy) 31 | salome.salome_init() 32 | 33 | ### START OF MACRO 34 | 35 | class Conact3D(QWidget): 36 | def __init__(self): 37 | super(Conact3D, self).__init__() 38 | self.initUI() 39 | self.selectParts() 40 | def __del__(self): 41 | return 42 | def initUI(self): 43 | # 3D parts selected 44 | self.l_parts = QLabel("3D Parts for contact analysis: ", self) 45 | self.tb_parts = QTextBrowser() 46 | self.pb_loadpart = QPushButton() 47 | self.pb_loadpart.setText("Load selected") 48 | # Adjust Gap 49 | self.l_gap = QLabel("Gap: ") 50 | self.sb_gap = QDoubleSpinBox() 51 | self.sb_gap.setDecimals(3) 52 | self.sb_gap.setValue(0.000) 53 | self.sb_gap.setSingleStep(0.001) 54 | # Common open_gmsh_options 55 | self.cb_common = QCheckBox(" Compound Results",self) 56 | self.cb_common.setChecked(Qt.Checked) 57 | # Ok buttons: 58 | self.okbox = QDialogButtonBox(self) 59 | self.okbox.setOrientation(Qt.Horizontal) 60 | self.okbox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) 61 | # Layout: 62 | layout = QGridLayout() 63 | layout.addWidget(self.l_parts, 1, 0) 64 | layout.addWidget(self.tb_parts, 2, 0) 65 | layout.addWidget(self.pb_loadpart, 3, 0) 66 | layout.addWidget(self.l_gap, 4, 0) 67 | layout.addWidget(self.sb_gap, 5, 0) 68 | layout.addWidget(self.cb_common, 6, 0) 69 | layout.addWidget(self.okbox, 8, 0) 70 | self.setLayout(layout) 71 | # Connectors: 72 | self.okbox.accepted.connect(self.proceed) 73 | self.okbox.rejected.connect(self.cancel) 74 | self.pb_loadpart.clicked.connect(self.selectParts) 75 | 76 | def selectParts(self): 77 | try: 78 | selCount = salome.sg.SelectedCount() 79 | selobj = list() 80 | self.tb_parts.clear() 81 | for i in range(0, selCount): 82 | sel_i=salome.sg.getSelected(i) 83 | selobj_i=salome.myStudy.FindObjectID(sel_i).GetObject() 84 | selobj.append(selobj_i) 85 | self.tb_parts.append(selobj[i].GetName()) 86 | self.parts = selobj 87 | except: 88 | QMessageBox.critical(None,'Error',"error in selected parts",QMessageBox.Abort) 89 | 90 | def proceed(self): 91 | gap = eval(str(self.sb_gap.text())) 92 | if self.cb_common.isChecked(): 93 | Common = True 94 | else: 95 | Common = False 96 | #selobj = self.selectParts() 97 | try: 98 | selobj = self.parts 99 | selobj_i = selobj[0] 100 | selobj_j = selobj[1] 101 | selCount = len(selobj) 102 | except: 103 | QMessageBox.critical(None,'Error',"Select 2 or more parts 3D first",QMessageBox.Abort) 104 | num_cont = 0 105 | for i in range(0, selCount): 106 | for j in range(1, selCount): 107 | if i != j and i < j: 108 | try: 109 | isOk, res1, res2 = geompy.FastIntersect(selobj[i], selobj[j], gap) 110 | except: 111 | QMessageBox.critical(None,'Error 1',"Unexpected error",QMessageBox.Abort) 112 | if isOk > 0: 113 | N_C = len(res1) 114 | N_C2 = len(res2) 115 | #QMessageBox.information(None, "Informacion", str(res1), QMessageBox.Ok) 116 | CONT = geompy.SubShapes(selobj[i], res1) 117 | CONT2 = geompy.SubShapes(selobj[j], res2) 118 | cont_sf_i = list() 119 | cont_sf_j = list() 120 | for h in range(0, N_C): 121 | for k in range(0, N_C2): 122 | common1 = geompy.MakeCommon(CONT[h], CONT2[k]) 123 | props = geompy.BasicProperties(common1) 124 | area_com = props[1] 125 | if Common == False: 126 | if area_com > 0.0: 127 | name_group_i = 'CZ_' + str(i) + str(j) + '_' + str(k) 128 | geompy.addToStudyInFather( selobj[i], CONT[h], name_group_i ) 129 | name_group_j = 'CZ_' + str(j) + str(i) + '_' + str(h) 130 | geompy.addToStudyInFather( selobj[j], CONT2[k], name_group_j ) 131 | num_cont += 1 132 | if Common == True: 133 | if area_com > 0.0: 134 | cont_sf_i.append(CONT[h]) 135 | cont_sf_j.append(CONT2[k]) 136 | comp_sf_i = geompy.MakeCompound(cont_sf_i) 137 | name_group_i = 'CZ_' + str(i) + str(j) 138 | geompy.addToStudyInFather( selobj[i], comp_sf_i, name_group_i ) 139 | comp_sf_j = geompy.MakeCompound(cont_sf_j) 140 | name_group_j = 'CZ_' + str(j) + str(i) 141 | geompy.addToStudyInFather( selobj[j], comp_sf_j, name_group_j ) 142 | num_cont += 1 143 | msg_cont = "Cantidad de pares de contactos detectados: " + str(num_cont) 144 | QMessageBox.information(None, "Informacion", msg_cont, QMessageBox.Ok) 145 | if salome.sg.hasDesktop(): 146 | salome.sg.updateObjBrowser(1) 147 | 148 | # cancel function 149 | def cancel(self): 150 | self.close() 151 | d.close() 152 | 153 | d = QDockWidget() 154 | d.setWidget(Conact3D()) 155 | d.setAttribute(Qt.WA_DeleteOnClose) 156 | d.setWindowFlags(d.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) 157 | d.setWindowTitle(" 3D Contacts ") 158 | d.setGeometry(600, 300, 400, 400) 159 | d.show() 160 | 161 | # END OF MACRO -------------------------------------------------------------------------------- /GeomFilterGroup.py: -------------------------------------------------------------------------------- 1 | # Create groups form filters 2 | import GEOM 3 | from salome.geom.geomtools import getGeompy, GeomStudyTools 4 | import math 5 | import os 6 | import salome_pluginsmanager 7 | 8 | 9 | geompy = getGeompy() 10 | geomTool = GeomStudyTools() 11 | 12 | import sys 13 | import salome 14 | from platform import system 15 | import subprocess 16 | import tempfile 17 | try: 18 | from PyQt4 import QtGui,QtCore 19 | from PyQt4.QtGui import * 20 | from PyQt4.QtCore import * 21 | except: 22 | from PyQt5.QtWidgets import QWidget, QMessageBox 23 | from PyQt5 import QtCore, QtGui 24 | import PyQt5.QtCore as QtCore 25 | from PyQt5.QtWidgets import * 26 | from PyQt5.QtCore import Qt 27 | 28 | 29 | ###### PROCEED ###### 30 | 31 | # Selected Object 32 | def selectGroupRef(): 33 | try: 34 | # selected Object 35 | selobj = geomTool.getGeomObjectSelected() 36 | #str(self.selobj.GetTopologyType()) 37 | selected=salome.sg.getSelected(0) 38 | selobjID=salome.myStudy.FindObjectID(selected) 39 | selobj=selobjID.GetObject() 40 | type_o = str(selobj.GetShapeType()) 41 | # Set object Name 42 | le_ref_g.setText(selobj.GetName()) 43 | # Set normal availble 44 | if type_o=='FACE': 45 | cb_norm.setEnabled(True) 46 | else: 47 | cb_norm.setEnabled(False) 48 | except: 49 | selobj = None 50 | QMessageBox.critical(None,'Error',"error 101",QMessageBox.Abort) 51 | return selobj 52 | 53 | 54 | # Run proceed 55 | def proceed(): 56 | try: 57 | # selected Object 58 | selobj=selectGroupRef() 59 | # Is a group? 60 | isgroup = geompy.ShapeIdToType(selobj.GetType()) == 'GROUP' 61 | # The father of group 62 | father = geompy.GetMainShape(selobj) 63 | # Type of element 64 | elem = str(selobj.GetShapeType()) 65 | # Size 66 | props = geompy.BasicProperties(selobj) 67 | if elem=="EDGE": 68 | Sref = props[0] 69 | if elem=="FACE": 70 | Sref = props[1] 71 | if elem=="SOLID": 72 | Sref = props[2] 73 | # Location 74 | cm_ref = geompy.MakeCDG(selobj) 75 | coords_ref = geompy.PointCoordinates(cm_ref) 76 | # Normal (Element==Face) 77 | if elem=="FACE": 78 | vnorm_ref = geompy.GetNormal(selobj) 79 | else: 80 | vnorm_ref = None 81 | # Create container group 82 | group=list() 83 | # All Object elements of type elem 84 | elements = geompy.ExtractShapes(father, geompy.ShapeType[elem], True) 85 | # Create group 86 | Group_f = geompy.CreateGroup(father, geompy.ShapeType[elem]) 87 | # Options 88 | name_g = str(le_nam_g.text()) 89 | pr = eval(str(sb_tol.text())) 90 | except: 91 | QMessageBox.critical(None,'Error',"error 1",QMessageBox.Abort) 92 | try: 93 | # Selected elements for the group whit the desired conditios 94 | for i in elements: 95 | props = geompy.BasicProperties(i) 96 | cm = geompy.MakeCDG(i) 97 | coords = geompy.PointCoordinates(cm) 98 | # Element i coordinates 99 | x = coords[0] 100 | y = coords[1] 101 | z = coords[2] 102 | # Element i size 103 | if elem=="EDGE": 104 | S = props[0] 105 | if elem=="FACE": 106 | S = props[1] 107 | if elem=="SOLID": 108 | S = props[2] 109 | # Element==Face i Normal 110 | if vnorm_ref==None: 111 | vnorm=None 112 | else: 113 | vnorm = geompy.GetNormal(i) 114 | angle = geompy.GetAngle(vnorm_ref, vnorm) 115 | # Comparations 116 | cond = list() 117 | if cb_size.isChecked(): 118 | cond.append(SSref*(1-pr)) 119 | else: 120 | cond.append(True) 121 | if cb_locx.isChecked(): 122 | if coords_ref[0]>=0: 123 | cond.append(xcoords_ref[0]*(1-pr)) 124 | else: 125 | cond.append(x>coords_ref[0]*(1+pr) and x=0: 130 | cond.append(ycoords_ref[1]*(1-pr)) 131 | else: 132 | cond.append(y>coords_ref[1]*(1+pr) and y=0: 137 | cond.append(zcoords_ref[2]*(1-pr)) 138 | else: 139 | cond.append(z>coords_ref[2]*(1+pr) and z0.0-0.001) 144 | else: 145 | cond.append(True) 146 | if cond[0] and cond[1] and cond[2] and cond[3] and cond[4]: 147 | ID = geompy.GetSubShapeID(father,i) 148 | group.append(ID) 149 | cond.append(cond) 150 | except: 151 | QMessageBox.critical(None,'Error',"error 2",QMessageBox.Abort) 152 | # Add elements desired to Group 153 | try: 154 | geompy.UnionIDs(Group_f, group) 155 | ## Add group in hte gui 156 | resGroup = geompy.addToStudyInFather(father, Group_f, name_g) 157 | ## View group 158 | gg = salome.ImportComponentGUI("GEOM") 159 | # Set color of the group 160 | gg.setColor(resGroup,255,0,0) 161 | gg.createAndDisplayGO(resGroup) 162 | ## Update Object Browser 163 | if salome.sg.hasDesktop(): 164 | salome.sg.updateObjBrowser(1) 165 | except: 166 | QMessageBox.critical(None,'Error',"error 3",QMessageBox.Abort) 167 | return 0.0 168 | 169 | 170 | def hide(): 171 | dialog.hide() 172 | 173 | 174 | ### GUI APLIACTION ### 175 | dialog = QDialog() 176 | dialog.resize(400,300) 177 | dialog.setWindowTitle("Create Group for same criteriums") 178 | dialog.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) 179 | # Options 180 | l_ref_g = QLabel("Reference Group:") 181 | pb_ref_g = QPushButton() 182 | pb_ref_g.setText("Select") 183 | le_ref_g = QLineEdit() 184 | l_nam_g = QLabel("Name result Group:") 185 | le_nam_g = QLineEdit() 186 | le_nam_g.setText("Group_R") 187 | l_crit = QLabel("Criteriums") 188 | cb_size = QCheckBox("Size") 189 | cb_size.setChecked(QtCore.Qt.Checked) 190 | cb_locx = QCheckBox("Location X") 191 | cb_locy = QCheckBox("Location Y") 192 | cb_locz = QCheckBox("Location Z") 193 | cb_norm = QCheckBox("Normal") 194 | cb_norm.setEnabled(False) 195 | l_tol = QLabel("% Tolerance:") 196 | sb_tol = QDoubleSpinBox() 197 | sb_tol.setValue(0.01) 198 | sb_tol.setMaximum(1.00) 199 | sb_tol.setMinimum(0.01) 200 | okbox = QDialogButtonBox(dialog) 201 | okbox.setOrientation(QtCore.Qt.Horizontal) 202 | okbox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) 203 | # Call selectGroupRef function 204 | selectGroupRef() 205 | # Layout 206 | layout = QGridLayout(dialog) 207 | layout.addWidget(l_ref_g,1,0) 208 | layout.addWidget(pb_ref_g,2,0) 209 | layout.addWidget(le_ref_g,2,1) 210 | layout.addWidget(l_nam_g,3,0) 211 | layout.addWidget(le_nam_g,3,1) 212 | layout.addWidget(l_crit,4,0) 213 | layout.addWidget(cb_size,5,1) 214 | layout.addWidget(cb_locx,6,1) 215 | layout.addWidget(cb_locy,7,1) 216 | layout.addWidget(cb_locz,8,1) 217 | layout.addWidget(cb_norm,9,1) 218 | layout.addWidget(l_tol,10,0) 219 | layout.addWidget(sb_tol,11,1) 220 | layout.addWidget(okbox,12,1) 221 | dialog.setLayout(layout) 222 | # Conectios 223 | pb_ref_g.clicked.connect(selectGroupRef) 224 | okbox.accepted.connect(proceed) 225 | okbox.rejected.connect(hide) 226 | QtCore.QMetaObject.connectSlotsByName(dialog) 227 | 228 | # Dialog show 229 | dialog.show() 230 | -------------------------------------------------------------------------------- /GMSHMesh.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Mesh with GMSH inside of Salome 3 | # License: LGPL v 2.1 4 | # Version: 14/04/2017 5 | 6 | # CONFIGURATION - EDIT THE FOLLOWING LINE TO MATCH YOUR GMSH BINARY 7 | gmsh_bin_linux = "/usr/bin/gmsh" 8 | gmsh_bin_windwos = "C:\\Daten\\gmsh-2.10.0-Windows\\gmsh.exe" 9 | gmsh_bin_other = "/usr/bin/gmsh" 10 | 11 | # CONFIGURATION - Interactive console 12 | xterm_bin_linux = '/usr/bin/xterm -e ' 13 | 14 | # END CONFIGURATION 15 | 16 | # START OF MACRO 17 | import sys 18 | import salome 19 | from platform import system 20 | import subprocess 21 | import tempfile 22 | try: 23 | from PyQt4 import QtGui,QtCore 24 | from PyQt4.QtGui import * 25 | from PyQt4.QtCore import * 26 | except: 27 | from PyQt5.QtWidgets import QWidget 28 | from PyQt5 import QtCore, QtGui 29 | import PyQt5.QtCore as QtCore 30 | from PyQt5.QtWidgets import * 31 | from PyQt5.QtCore import Qt 32 | 33 | import GEOM 34 | from salome.geom import geomBuilder 35 | import math 36 | import SALOMEDS 37 | import SMESH, SALOMEDS 38 | from salome.smesh import smeshBuilder 39 | 40 | theStudy = salome.myStudy 41 | geompy = geomBuilder.New(theStudy) 42 | salome.salome_init() 43 | 44 | 45 | if system() == "Linux": 46 | gmsh_bin = gmsh_bin_linux 47 | path_sep = "/" 48 | elif system() == "Windows": 49 | gmsh_bin = gmsh_bin_windwos 50 | path_sep = "\\" 51 | else: 52 | gmsh_bin = gmsh_bin_other 53 | path_sep = "/" 54 | 55 | class MeshGmsh(QWidget): 56 | def __init__(self): 57 | super(MeshGmsh, self).__init__() 58 | self.initUI() 59 | def __del__(self): 60 | return 61 | def initUI(self): 62 | # Mesh dimension 63 | self.rb_1D = QRadioButton(" 1D", self) 64 | self.rb_2D = QRadioButton(" 2D", self) 65 | self.rb_3D = QRadioButton(" 3D", self) 66 | self.rb_3D.setChecked(Qt.Checked) 67 | # Optimized: 68 | self.cb_optimized = QCheckBox(" Optimized", self) 69 | self.cb_optimized.setChecked(Qt.Checked) 70 | # Algorithm: 71 | self.l_algorithm = QLabel("Algorithm ", self) 72 | self.cmb_algorithm = QComboBox(self) 73 | self.algorithm_list = [self.tr('iso'), self.tr('netgen'), self.tr('front2d'), self.tr('meshadapt'), self.tr('delquad'), self.tr('del3d'), self.tr('del2d'), self.tr('front3d'), self.tr('mmg3d'), self.tr('pack'), self.tr('tetgen'),] 74 | self.cmb_algorithm.addItems(self.algorithm_list) 75 | self.cmb_algorithm.setCurrentIndex(1) 76 | # Element max size: 77 | self.cb_max_elme_size = QCheckBox(" Set maximum mesh element size",self) 78 | self.cb_max_elme_size.setChecked(Qt.Checked) 79 | self.sb_max_element_size = QDoubleSpinBox(self) 80 | self.sb_max_element_size.setValue(20.0) 81 | self.sb_max_element_size.setMaximum(10000000.0) 82 | self.sb_max_element_size.setMinimum(0.00000001) 83 | # Element min size: 84 | self.cb_min_elme_size = QCheckBox(" Set minimum mesh element size",self) 85 | self.sb_min_element_size = QDoubleSpinBox(self) 86 | self.sb_min_element_size.setValue(5.0) 87 | self.sb_min_element_size.setMaximum(10000000.0) 88 | self.sb_min_element_size.setMinimum(0.00000001) 89 | self.sb_min_element_size.setEnabled(False) 90 | # Set Mesh Order: 91 | self.cb_mesh_order = QCheckBox(" mesh order",self) 92 | self.sb_mesh_order = QSpinBox(self) 93 | self.sb_mesh_order.setValue(2) 94 | self.sb_mesh_order.setMaximum(5) 95 | self.sb_mesh_order.setMinimum(1) 96 | # Interactive Follow up: 97 | self.cb_interact = QCheckBox(" Interactive Follow up", self) 98 | self.cb_interact.setChecked(Qt.Checked) 99 | # Other gmsh commands: 100 | self.l_cmd_line_opt = QLabel("Custom gmsh options ", self) 101 | self.le_cmd_line_opt = QLineEdit(self) 102 | self.le_cmd_line_opt.setToolTip("Those option will be appended to gmsh command line call") 103 | # Ok buttons: 104 | self.okbox = QDialogButtonBox(self) 105 | self.okbox.setOrientation(Qt.Horizontal) 106 | self.okbox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) 107 | # Web button 108 | self.pb_web = QPushButton(self) 109 | self.pb_web.setText("gmsh options (web)") 110 | # Layout: 111 | layout = QGridLayout() 112 | layout.addWidget(self.rb_1D, 1, 0) 113 | layout.addWidget(self.rb_2D, 1, 1) 114 | layout.addWidget(self.rb_3D, 2, 0) 115 | layout.addWidget(self.cb_optimized, 2, 1) 116 | layout.addWidget(self.l_algorithm, 3, 0) 117 | layout.addWidget(self.cmb_algorithm, 3, 1) 118 | layout.addWidget(self.cb_max_elme_size, 4, 0) 119 | layout.addWidget(self.sb_max_element_size, 4, 1) 120 | layout.addWidget(self.cb_min_elme_size, 5, 0) 121 | layout.addWidget(self.sb_min_element_size, 5, 1) 122 | layout.addWidget(self.cb_mesh_order, 6, 0) 123 | layout.addWidget(self.sb_mesh_order, 6, 1) 124 | layout.addWidget(self.cb_interact, 7, 1) 125 | layout.addWidget(self.l_cmd_line_opt, 8, 0) 126 | layout.addWidget(self.le_cmd_line_opt, 8, 1) 127 | layout.addWidget(self.pb_web, 9, 0) 128 | layout.addWidget(self.okbox, 9, 1) 129 | self.setLayout(layout) 130 | # Connectors: 131 | self.okbox.accepted.connect(self.proceed) 132 | self.okbox.rejected.connect(self.cancel) 133 | self.pb_web.clicked.connect(self.open_gmsh_options) 134 | self.cb_max_elme_size.stateChanged.connect(self.max_size_state) 135 | self.cb_min_elme_size.stateChanged.connect(self.min_size_state) 136 | self.cb_mesh_order.stateChanged.connect(self.mesh_order_state) 137 | 138 | def max_size_state(self, state): 139 | if state == Qt.Checked: 140 | self.sb_max_element_size.setEnabled(True) 141 | else: 142 | self.sb_max_element_size.setEnabled(False) 143 | 144 | def min_size_state(self, state): 145 | if state == Qt.Checked: 146 | self.sb_min_element_size.setEnabled(True) 147 | else: 148 | self.sb_min_element_size.setEnabled(False) 149 | 150 | def mesh_order_state(self, state): 151 | if state == Qt.Checked: 152 | self.sb_mesh_order.setEnabled(True) 153 | else: 154 | self.sb_mesh_order.setEnabled(False) 155 | 156 | def open_gmsh_options(self): 157 | import webbrowser 158 | webbrowser.open('http://www.geuz.org/gmsh/doc/texinfo/gmsh.html#Command_002dline-options') 159 | 160 | def cancel(self): 161 | self.close() 162 | d.close() 163 | 164 | def proceed(self): 165 | temp_file = tempfile.mkstemp(suffix='.brep')[1] 166 | selected = salome.sg.getSelected(0) 167 | selection = salome.myStudy.FindObjectID(selected).GetObject() 168 | if not selection: 169 | QMessageBox.critical(None, "GMSHMesh macro", "An object has to be selected to run gmsh!") 170 | ## Export a part in step format 171 | geompy.ExportBREP(selection, temp_file) 172 | selection_name = selection.GetName() 173 | ## Mesh temporaly file 174 | file_format = 'med' 175 | temp_mesh_file = tempfile.tempdir + path_sep + selection_name + '_Mesh.' + file_format 176 | ## OPTIONS GMSH: 177 | clmax = self.sb_max_element_size.text() 178 | clmin = self.sb_min_element_size.text() 179 | cmd_line_opt = self.le_cmd_line_opt.text() 180 | algo = self.cmb_algorithm.currentText() 181 | mesh_order = self.sb_mesh_order.text() 182 | if self.cb_optimized.isChecked(): 183 | cmd_optimize = ' -optimize' 184 | else: 185 | cmd_optimize = '' 186 | if self.rb_3D.isChecked(): 187 | dim = ' -3 ' 188 | if self.rb_2D.isChecked(): 189 | dim = ' -2 ' 190 | if self.rb_1D.isChecked(): 191 | dim = ' -1 ' 192 | if self.cb_max_elme_size.isChecked(): 193 | max_size = ' -clmax ' + clmax 194 | else: 195 | max_size = '' 196 | if self.cb_min_elme_size.isChecked(): 197 | min_size = ' -clmin ' + clmin 198 | else: 199 | min_size = '' 200 | if self.cb_mesh_order.isChecked(): 201 | order = ' -order ' + mesh_order 202 | else: 203 | order = '' 204 | options = ' -algo ' + algo + max_size + min_size + cmd_optimize + order + cmd_line_opt 205 | # RUN GMSH 206 | command = gmsh_bin + ' ' + temp_file + dim + '-format ' + file_format + ' -o ' + temp_mesh_file + '' + options 207 | try: 208 | if system() == "Linux": 209 | if self.cb_interact.isChecked(): 210 | output = subprocess.check_output([xterm_bin_linux + command, '-1'], shell=True, stderr=subprocess.STDOUT,) 211 | else: 212 | output = subprocess.check_output([command, '-1'], shell=True, stderr=subprocess.STDOUT,) 213 | elif system() == "Windows": 214 | output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT,) 215 | else: 216 | output = subprocess.check_output([command, '-1'], shell=True, stderr=subprocess.STDOUT,) 217 | smesh = smeshBuilder.New(theStudy) 218 | ([Mesh_1], status) = smesh.CreateMeshesFromMED(temp_mesh_file) 219 | smesh.SetName(Mesh_1.GetMesh(),selection_name) 220 | if salome.sg.hasDesktop(): 221 | salome.sg.updateObjBrowser(1) 222 | #self.close() 223 | #d.close() 224 | print "Succefull" 225 | except: 226 | QMessageBox.critical(None, "GMSHMesh macro", "Unexpected error in GMSHMesh macro!") 227 | finally: 228 | try: 229 | del temp_file 230 | except: 231 | pass 232 | try: 233 | del temp_mesh_file 234 | except: 235 | pass 236 | 237 | 238 | 239 | d = QDockWidget() 240 | d.setWidget(MeshGmsh()) 241 | d.toggleViewAction().setText("Gmsh") 242 | d.setAttribute(Qt.WA_DeleteOnClose) 243 | d.setWindowTitle(" GMSH Mesh Generator ") 244 | d.setGeometry(600, 300, 400, 600) 245 | d.show() 246 | 247 | # END OF MACRO 248 | --------------------------------------------------------------------------------