Salome HOME
99cf05509b9be8ed056a56f07d5a5f232c273a0f
[modules/smesh.git] / src / Tools / MGCleanerPlug / MGCleanerMonPlugDialog.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013  EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20
21 # Modules Python
22 # Modules Eficas
23
24 import os, subprocess
25 from MGCleanerPlugDialog import Ui_MGCleanerPlugDialog
26 from MGCleanerMonViewText import MGCleanerMonViewText
27 from PyQt4.QtGui import *
28 from PyQt4.QtCore import *
29
30
31 class MGCleanerMonPlugDialog(Ui_MGCleanerPlugDialog,QWidget):
32   """
33   """
34   def __init__(self):
35         QWidget.__init__(self)
36         self.setupUi(self)
37         self.connecterSignaux()
38         self.fichierIn=""
39         self.fichierOut=""
40         self.MeshIn="" 
41         self.num=1
42
43         # complex whith QResources: not used
44         # The icon are supposed to be located in the $SMESH_ROOT_DIR/share/salome/resources/smesh folder,
45         # other solution could be in the same folder than this python module file:
46         # iconfolder=os.path.dirname(os.path.abspath(__file__))
47
48         iconfolder=os.environ['SMESH_ROOT_DIR']+'/share/salome/resources/smesh'
49         #print "MGCleanerMonPlugDialog iconfolder",iconfolder
50         icon = QIcon()
51         icon.addFile(os.path.join(iconfolder,"select1.png"))
52         self.PB_MeshSmesh.setIcon(icon)
53         icon = QIcon()
54         icon.addFile(os.path.join(iconfolder,"open.png"))
55         self.PB_ParamsFileExplorer.setIcon(icon)
56
57         #Ces parametres ne sont pas remis à rien par le clean
58         self.paramsFile= os.path.abspath(os.path.join(os.environ['HOME'],'.MGCleaner.dat'))
59         self.LE_ParamsFile.setText(self.paramsFile)
60         self.LE_MeshFile.setText("")
61         self.LE_MeshSmesh.setText("")
62         
63         self.clean()
64
65   def connecterSignaux(self) :
66         self.connect(self.PB_Cancel,SIGNAL("clicked()"),self.PBCancelPressed)
67         self.connect(self.PB_Default,SIGNAL("clicked()"),self.clean)
68         self.connect(self.PB_Help,SIGNAL("clicked()"),self.PBHelpPressed)
69         self.connect(self.PB_Load,SIGNAL("clicked()"),self.PBLoadPressed)
70         self.connect(self.PB_OK,SIGNAL("clicked()"),self.PBOKPressed)
71         self.connect(self.PB_Save,SIGNAL("clicked()"),self.PBSavePressed)
72         self.connect(self.PB_MeshFile,SIGNAL("clicked()"),self.PBMeshFilePressed)
73         self.connect(self.PB_MeshSmesh,SIGNAL("clicked()"),self.PBMeshSmeshPressed)
74         self.connect(self.PB_ParamsFileExplorer,SIGNAL("clicked()"),self.setParamsFileName)
75         self.connect(self.LE_MeshFile,SIGNAL("returnPressed()"),self.meshFileNameChanged)
76         self.connect(self.LE_ParamsFile,SIGNAL("returnPressed()"),self.paramsFileNameChanged)
77
78
79   def PBHelpPressed(self):
80         try :
81           mydir=os.environ['SMESH_ROOT_DIR']
82         except Exception:
83           QMessageBox.warning( self, "Help unavailable $SMESH_ROOT_DIR not found")
84         maDoc=mydir+"/share/doc/salome/gui/SMESH/MGCleaner/_downloads/mg-cleaner_user_manual.pdf"
85         command="xdg-open "+maDoc+";"
86         subprocess.call(command, shell=True)
87
88
89   def PBOKPressed(self):
90         if not(self.PrepareLigneCommande()) : return
91         self.PBSavePressed(NomHypo=True)
92         maFenetre=MGCleanerMonViewText(self,self.commande)
93         if os.path.isfile(self.fichierOut) :self.enregistreResultat()
94
95   def enregistreResultat(self):
96         import smesh
97         import SMESH
98         import salome
99         from salome.kernel import studyedit
100
101         maStudy=studyedit.getActiveStudy()
102         smesh.SetCurrentStudy(maStudy)
103         (outputMesh, status) = smesh.CreateMeshesFromGMF(self.fichierOut)
104         meshname = 'MGCleaner'+str(self.num)
105         smesh.SetName(outputMesh.GetMesh(), meshname)
106         outputMesh.Compute()
107
108
109         self.editor = studyedit.getStudyEditor()    # 
110         moduleEntry=self.editor.findOrCreateComponent("SMESH","SMESH")
111         HypReMeshEntry = self.editor.findOrCreateItem( moduleEntry, name = 'HypoForRemesh',
112                                            comment = 'HypoForRemeshing')
113         monStudyBuilder=maStudy.NewBuilder();
114         monStudyBuilder.NewCommand();
115         newStudyIter=monStudyBuilder.NewObject(HypReMeshEntry)
116         aNameAttrib=monStudyBuilder.FindOrCreateAttribute(newStudyIter,"AttributeName")
117         hypoName = 'anHypo_MGCleaner_'+str(self.num)
118         aNameAttrib.SetValue(hypoName)
119         aCommentAttrib=monStudyBuilder.FindOrCreateAttribute(newStudyIter,"AttributeComment")
120         aCommentAttrib.SetValue(str(self.commande))
121         
122         SOMesh=maStudy.FindObjectByName(meshname ,"SMESH")[0]
123         newLink=monStudyBuilder.NewObject(SOMesh)
124         monStudyBuilder.Addreference(newLink, newStudyIter);
125         if salome.sg.hasDesktop(): salome.sg.updateObjBrowser(0)
126         self.num+=1
127         return True
128
129   def PBSavePressed(self,NomHypo=False):
130         if NomHypo : text = '# Params for Hypothese : anHypo_MGCleaner_'+str(self.num - 1)+"\n"
131         else :       text = '# Save intermediate params \n' 
132         text += "# Params for mesh : " +  self.LE_MeshSmesh.text() +'\n'
133         for RB in self.GBOptim.findChildren(QRadioButton,):
134             if RB.isChecked()==True:
135                text+="Optimisation ='"+RB.text()+"'\n"
136                break
137         for RB in self.GBUnit.findChildren(QRadioButton,):
138             if RB.isChecked()==True:
139                text+="Units ='"+RB.text()+"'\n"
140         text+='Chordal_Tolerance_Deviation='+str(self.SP_Tolerance.value())+'\n'
141
142         text+='Ridge_Detection=' + str(self.CB_Ridge.isChecked())+'\n'
143         text+='Split_Edge='      + str(self.CB_SplitEdge.isChecked())+'\n'
144         text+='Point_Smoothing=' + str(self.CB_Point.isChecked())+'\n'
145         text+='Geometrical_Approximation='+ str(self.SP_Geomapp.value())  +'\n'
146         text+='Ridge_Angle='              + str(self.SP_Ridge.value())    +'\n'
147         text+='Maximum_Size='             + str(self.SP_MaxSize.value())  +'\n'
148         text+='Minimum_Size='             + str(self.SP_MaxSize.value())  +'\n'
149         text+='Mesh_Gradation='           + str(self.SP_Gradation.value())+'\n'
150
151         text+='Verbosity='                + str(self.SP_Verbosity.value())+'\n'
152         text+='Memory='                   + str(self.SP_Memory.value())+'\n'
153         text+='\n\n'
154
155         try :
156            f=open(self.paramsFile,'a')
157         except :
158            QMessageBox.warning( self, "File", "Unable to open "+self.paramsFile)
159            return
160         try :
161            f.write(text)
162         except :
163            QMessageBox.warning( self, "File", "Unable to write "+self.paramsFile)
164            return
165         f.close()
166
167   def PBLoadPressed(self):
168         try :
169            f=open(self.paramsFile,'r')
170         except :
171            QMessageBox.warning( self, "File", "Unable to open "+self.paramsFile)
172            return
173         try :
174            text=f.read()
175         except :
176            QMessageBox.warning( self, "File", "Unable to read "+self.paramsFile)
177            return
178         f.close()
179         d={}
180         exec text in d
181         for RB in self.GBOptim.findChildren(QRadioButton,):
182             if d['Optimisation']== RB.text():
183                RB.setChecked(True)
184                break
185         for RB in self.GBUnit.findChildren(QRadioButton,):
186             if d['Units']== RB.text():
187                RB.setChecked(True)
188                break
189         self.SP_Tolerance.setValue(d['Chordal_Tolerance_Deviation'])
190
191         self.CB_Ridge.setChecked(d['Ridge_Detection'])
192         self.CB_Point.setChecked(d['Point_Smoothing'])
193         self.CB_SplitEdge.setChecked(d['Split_Edge'])
194         self.SP_Geomapp.setValue(d['Geometrical_Approximation'])
195         self.SP_Ridge.setValue(d['Ridge_Angle'])
196         self.SP_MaxSize.setValue(d['Maximum_Size'])
197         self.SP_MinSize.setValue(d['Minimum_Size'])
198         self.SP_Gradation.setValue(d['Mesh_Gradation'])
199
200         self.SP_Verbosity.setValue(d['Verbosity'])
201         self.SP_Memory.setValue(d['Memory'])
202
203
204   def PBCancelPressed(self):
205         self.close()
206
207   def PBMeshFilePressed(self):
208        fd = QFileDialog(self, "select an existing Mesh file", self.LE_MeshFile.text(), "Mesh-Files (*.mesh);;All Files (*)")
209        if fd.exec_():
210           infile = fd.selectedFiles()[0]
211           self.LE_MeshFile.setText(infile)
212           self.fichierIn=infile.toLatin1()
213
214   def setParamsFileName(self):
215        fd = QFileDialog(self, "select a file", self.LE_ParamsFile.text(), "dat Files (*.dat);;All Files (*)")
216        if fd.exec_():
217           infile = fd.selectedFiles()[0]
218           self.LE_ParamsFile.setText(infile)
219           self.paramsFile=infile.toLatin1()
220
221
222   def meshFileNameChanged(self):
223       self.fichierIn=self.LE_MeshFile.text()
224       if os.path.exists(self.fichierIn): return
225       QMessageBox.warning( self, "Unknown File", "File doesn't exist")
226
227   def paramsFileNameChanged(self):
228       self.paramsFile=self.LE_ParamsFile.text()
229
230   def PBMeshSmeshPressed(self):
231       import salome
232       import smesh
233       from salome.kernel import studyedit
234       from salome.smesh.smeshstudytools import SMeshStudyTools
235       from salome.gui import helper as guihelper
236       from omniORB import CORBA
237
238       mySObject, myEntry = guihelper.getSObjectSelected()
239       if CORBA.is_nil(mySObject) or mySObject==None:
240          QMessageBox.critical(self, "Mesh", "select an input mesh")
241          return
242       self.smeshStudyTool = SMeshStudyTools()
243       self.__selectedMesh = self.smeshStudyTool.getMeshObjectFromSObject(mySObject)
244       if CORBA.is_nil(self.__selectedMesh):
245          QMessageBox.critical(self, "Mesh", "select an input mesh")
246          return
247       myName = mySObject.GetName()
248       self.MeshIn=myName
249       self.LE_MeshSmesh.setText(myName)
250
251   def prepareFichier(self):
252       self.fichierIn="/tmp/PourMGCleaner_"+str(self.num)+".mesh"
253       import SMESH
254       self.__selectedMesh.ExportGMF(self.__selectedMesh,self.fichierIn, True)
255
256   def PrepareLigneCommande(self):
257       """
258       #use doc examples of mg-cleaner:
259       ls -al /data/tmplgls/salome/prerequis/install/COMMON_64/MeshGems-1.0/bin
260       source /data/tmplgls/salome/prerequis/install/LICENSE/dlim8.var.sh
261       export PATH=/data/tmplgls/salome/prerequis/install/COMMON_64/MeshGems-1.0/bin/Linux_64:$PATH
262       cp -r /data/tmplgls/salome/prerequis/install/COMMON_64/MeshGems-1.0/examples .
263       cd examples
264       mg-cleaner.exe --help
265       mg-cleaner.exe --in case7.mesh --out case7-test.mesh --check
266       mg-cleaner.exe case7.mesh case7-fix.mesh --fix
267       mg-cleaner.exe --in Porsche.mesh --out Porsche-test.mesh --check
268       mg-cleaner.exe --in Porsche.mesh --out Porschefix.mesh --fix
269       mg-cleaner.exe --in Porsche.mesh --out PorscheNewfix.mesh --fix --resolution_length 0.03
270       """
271
272       self.commande="mg-cleaner.exe "
273       verbosity=str(self.SP_Verbosity.value())
274       self.commande+="-v "+verbosity
275       for obj in self.mesRB.children():
276           try :
277            if obj.isChecked():
278               self.style=obj.objectName().remove(0,3)
279               self.style.replace("_","-")
280               break
281           except :
282               pass
283       self.commande+=" -O "+self.style.toLatin1()
284       if self.fichierIn=="" and self.MeshIn=="" :
285          QMessageBox.critical(self, "Mesh", "select an input mesh")
286          return False
287       if self.MeshIn!="" : self.prepareFichier()
288       if not (os.path.isfile(self.fichierIn)):
289          QMessageBox.critical(self, "File", "unable to read GMF Mesh in "+str(self.fichierIn))
290          return False
291
292       deb=os.path.splitext(self.fichierIn)
293       self.fichierOut=deb[0]+'.d.meshb'
294
295       if self.RB_Absolute.isChecked()==True :
296          self.commande+=' -Dabsolute'
297       else :
298          self.commande+=' -Drelative'
299       self.commande+=',tolerance=%f'%self.SP_Tolerance.value()
300       if self.CB_Ridge.isChecked()==False : self.commande+=',nr'
301       if self.CB_Point.isChecked()==False : self.commande+=',ns'
302       if self.SP_Geomapp.value()!=0.04 : self.commande+=',geomapp=%f'%self.SP_Geomapp.value()
303       if self.SP_Ridge.value()!=45.0 : self.commande+=',ridge=%f'%self.SP_Ridge.value()
304       if self.SP_MaxSize.value()!=100 : self.commande+=',maxsize=%f'%self.SP_MaxSize.value()
305       if self.SP_MinSize.value()!=5 : self.commande+=',minsize=%f'%self.SP_MinSize.value()
306       if self.SP_Gradation.value()!=1.3 : self.commande+=',gradation=%f'%self.SP_MaxSize.value()
307       if self.CB_SplitEdge.isChecked()==True : self.commande+=',splitedge=1'
308
309       if self.SP_Verbosity.value()!=3 : self.commande+=' -v %d'%self.SP_Verbosity.value()
310       if self.SP_Memory.value()!=0 : self.commande+=' -m %d'%self.SP_Memory.value()
311
312       self.commande+=" "+self.fichierIn
313       
314       #for the moment
315       deb=os.path.splitext(self.fichierIn)     
316       self.fichierOut=deb[0]+'_fix.mesh'
317       self.commande="mg-cleaner.exe --in " + self.fichierIn + " --out " + self.fichierOut + " --fix" 
318       
319       return True
320
321   def clean(self):
322       self.RB_Check.setChecked(False)
323       self.RB_Fix1.setChecked(False)
324       self.RB_Fix2.setChecked(True)
325       self.CB_Preserve.setChecked(False)
326       self.CB_FillHoles.setChecked(False)
327       self.CB_RemeshPlanes.setChecked(False)
328       
329       self.SP_minHoleSize.setProperty("value", 0)
330       self.SP_toleranceDisplacement.setProperty("value", 0)
331       self.SP_resolutionLength.setProperty("value", 0)
332       self.SP_foldingAngle.setProperty("value", 15)
333       self.SP_overlapdistance.setProperty("value", 0)
334       self.SP_overlapAngle.setProperty("value", 15)
335       self.SP_Verbosity.setProperty("value", 3)
336       
337       self.CB_computedToleranceDisplacement.setChecked(True)
338       self.CB_computedResolutionLength.setChecked(True)
339       self.CB_computedOverlapDistance.setChecked(True)
340
341 __dialog=None
342 def getDialog():
343     """
344     This function returns a singleton instance of the plugin dialog.
345     c est obligatoire pour faire un show sans parent...
346     """
347     global __dialog
348     if __dialog is None:
349         __dialog = MGCleanerMonPlugDialog()
350     #else :
351     #   __dialog.clean()
352     return __dialog
353