1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2021 CEA/DEN, EDF R&D
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, or (at your option) any later version.
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.
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
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 """Obtention des surfaces médianes à partir d'un objet GEOM ou SHAPER
22 On sait traiter les faces :
29 Version initiale par :
30 alexandre.prunie@blastsolutions.io
31 guillaume.schweitzer@blastsolutions.io
37 __revision__ = "V10.09"
39 #========================= Les imports - Début ===================================
47 from salome.shaper import model
48 from salome.geom import geomBuilder
49 from salome.geom import geomtools
50 from salome.kernel.studyedit import getStudyEditor
54 #========================== Les imports - Fin ====================================
57 D_FMT["stp"] = ["stp", "step"]
58 D_FMT["igs"] = ["igs", "iges"]
59 for CLE in ("brep", "xao"):
62 #========================= Début de la fonction ==================================
64 def decode_cao (fmt_cao):
65 """Décode le format de la cao
68 :fmt_cao: format du fichier, step, iges, etc.
70 :fmt_cao_0: format décodé
75 fmt_cao_low = fmt_cao.lower()
77 for cle, l_aux in D_FMT.items():
78 if ( fmt_cao_low in l_aux ):
84 #========================= Fin de la fonction ===================================
86 #========================= Début de la fonction ==================================
88 def import_cao (part_doc, ficcao, verbose=False):
89 """Importation d'une cao
93 :ficcao: le fichier de la CAO
95 :objet: l'objet importé dans SHAPER
100 message = "Fichier '{}'\n".format(ficcao)
106 laux = ficcao.split(".")
107 fmt_cao_0 = decode_cao (laux[-1])
109 if ( fmt_cao_0 not in ("stp", "brep", "igs", "xao") ):
110 message += "Le format de CAO est inconnu"
114 message += "Le fichier de CAO n'a pas été décodé correctement."
117 elif not os.path.isfile(ficcao):
118 message += "Le fichier de CAO est inconnu."
124 objet = model.addImport(part_doc, ficcao)
129 texte = "Objet : '{}'\n".format(objet.result().name())
130 texte += "De type : '{}'".format(objet.result().shapeType())
134 return erreur, message, objet
136 #========================= Fin de la fonction ===================================
138 #=================================== La classe ===================================
140 class SurfaceMediane (object):
142 """Calcul des surfaces médianes de solides minces
144 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
145 une structure qui est un solide ou un assemblage de solides (compound).
146 Pour réaliser l'opération, deux façons de faire :
148 1. On sélectionne la structure dans l'arbre d'étude ou dans la fenêtre graphique de GEOM, puis on lance le script.
150 2. On écrit un script python dans lequel on réalise la création ou l'importation d'une CAO. \
151 On insère cette classe dans le script, puis on lance surf_fic_cao, surf_objet_shaper ou surf_objet_geom selon le point de départ.
153 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
154 de taille identique et supérieure aux autres faces du solide pour des polyèdres ou \
155 s'il a reconnu des formes canoniques.
156 Il crée alors une surface au milieu de ces deux grandes faces. Cette face est coloriée en vert.
158 Si les 2 faces les plus grandes sont planes mais que leurs tailles ne sont pas identiques, le programme \
159 crée néanmoins une face basée sur la plus grande de ces faces. Un message est émis et cette face médiane \
160 est coloriée en bleu. Le volume correspondant n'est pas détruit et est colorié en rouge.
162 On sait traiter les faces :
175 . Suppression des solides et faces créés par l'explosion des objets. Par défaut, la suppression est faite.
178 . Retour dans Shaper. Par défaut, les faces restent dans GEOM.
179 -retour_shaper/-no_retour_shaper
188 affiche_aide_globale = 0
194 _retour_shaper = False
203 l_faces_trans = list()
208 #=========================== Début de la méthode =================================
210 def __init__ ( self, liste_option ):
212 """Le constructeur de la classe SurfaceMediane
214 Décodage des arguments
215 On cherche ici les arguments généraux : aide, verbeux
218 for option in liste_option :
221 if isinstance(option,str):
222 saux = option.upper()
224 if saux in ( "-H", "-HELP" ):
225 self.affiche_aide_globale = 1
228 elif saux == "-VMAX" :
230 self._verbose_max = 1
231 elif saux == "-MENAGE" :
233 elif saux == "-NO_MENAGE" :
235 elif saux == "-RETOUR_SHAPER":
236 self._retour_shaper = True
237 elif saux == "-NO_RETOUR_SHAPER":
238 self._retour_shaper = False
240 #=========================== Fin de la méthode ==================================
242 #=========================== Début de la méthode =================================
245 """A la suppression de l'instance de classe"""
246 if self._verbose_max:
247 print ("Suppression de l'instance de la classe.")
249 #=========================== Fin de la méthode ==================================
251 #=========================== Début de la méthode =================================
253 def _selection_objet_graphique ( self, geompy ):
254 """Sélectionne l'objet dans la fenêtre graphique
257 :geompy: environnement de GEOM
260 :objet: objet à traiter
263 nom_fonction = __name__ + "/_selection_objet_graphique"
264 blabla = "\nDans {} :\n".format(nom_fonction)
270 while ( not erreur ):
272 # 1. Contrôle du nombre d'objets sélectionnés graphiquement
273 nb_objet = salome.sg.SelectedCount()
274 if self._verbose_max:
275 print (blabla+"Nombre d'objets sélectionnés : {}.".format(nb_objet))
277 if ( nb_objet != 1 ):
278 message = "Nombre d'objets sélectionnés : {}.\nIl en faut un et un seul.".format(nb_objet)
282 # 2. Récupération de l'ID de l'objet en cours
283 entry = salome.sg.getSelected(0)
284 # Récupération de l'objet
285 objet = salome.myStudy.FindObjectID( entry ).GetObject()
286 if self._verbose_max:
287 print (geompy.WhatIs(objet))
291 return erreur, message, objet
293 #=========================== Fin de la méthode ==================================
295 #=========================== Début de la méthode =================================
297 def _les_solides ( self, geompy, objet ):
298 """Les solides de l'objet à traiter
301 :geompy: environnement de GEOM
302 :objet: l'objet à traiter
305 :l_solides: liste des solides de la sélection
308 nom_fonction = __name__ + "/_les_solides"
309 blabla = "\nDans {} :\n".format(nom_fonction)
310 if self._verbose_max:
317 while ( not erreur ):
319 # 1. Nombre de solides composant l'objet à traiter
320 d_shape_info = geompy.ShapeInfo(objet)
321 n_solides = d_shape_info["SOLID"]
322 if self._verbose_max:
323 print ("Nombre de solides : {}".format(n_solides))
325 nom_objet = objet.GetName()
327 print (". Traitement de l'objet '{}'".format(nom_objet))
329 # 2. Liste des solides qui composent l'objet
330 if ( n_solides == 0 ):
331 message = "Aucun solide dans l'objet sélectionné."
334 elif ( n_solides == 1 ):
335 l_solides.append(objet)
337 l_solides = geompy.ExtractShapes(objet, geompy.ShapeType["SOLID"], True)
338 for iaux, solide in enumerate(l_solides):
339 geompy.addToStudyInFather( objet, solide, "{}_{:03d}".format(nom_objet,iaux+1) )
340 if self._verbose_max:
341 print ("l_solides : {}.".format(l_solides))
342 for iaux, solide in enumerate(l_solides):
343 print (geompy.WhatIs(solide))
347 return erreur, message, l_solides
349 #=========================== Fin de la méthode ==================================
351 #=========================== Début de la méthode =================================
353 def _faces_du_solide ( self, geompy, solide ):
354 """Détermine les faces d'un solide
357 :geompy: environnement de GEOM
358 :solide: le solide à traiter
361 :l_faces: liste des faces du solide
364 nom_fonction = __name__ + "/_faces_du_solide"
365 blabla = "\nDans {} :\n".format(nom_fonction)
366 if self._verbose_max:
373 while ( not erreur ):
375 self.nom_solide = solide.GetName()
377 print (".. Traitement du solide '{}'".format(self.nom_solide))
379 # 1. Le solide est-il un solide unique ?
380 if self._verbose_max:
381 print (geompy.WhatIs(solide))
382 longueur, aire, volume = geompy.BasicProperties(solide)
383 if self._verbose_max:
384 print (". longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume))
386 d_shape_info = geompy.ShapeInfo(solide)
387 n_solides = d_shape_info["SOLID"]
388 if self._verbose_max:
389 print ("Nombre de solides : {}".format(n_solides))
390 if ( n_solides != 1 ):
391 message = "Nombre de solides : {}.\nIl en faut un et un seul.".format(n_solides)
395 # 2. Liste des faces qui composent le solide
396 l_faces = geompy.ExtractShapes(solide, geompy.ShapeType["FACE"], True)
397 for iaux, face in enumerate(l_faces):
398 geompy.addToStudyInFather( solide, face, "Face_{}".format(iaux+1) )
399 if self._verbose_max:
400 print ("l_faces : {}".format(l_faces))
401 for iaux, face in enumerate(l_faces):
402 print (geompy.WhatIs(face))
406 return erreur, message, l_faces
408 #=========================== Fin de la méthode ==================================
410 #=========================== Début de la méthode =================================
412 def _calcul_caract_faces ( self, geompy, l_faces ):
413 """Calcule les caractéristiques géométriques des faces
416 :geompy: environnement de GEOM
417 :l_faces: liste des faces du solide
420 :tb_caract: tableau des caractéristiques géométriques des faces
423 nom_fonction = __name__ + "/_calcul_caract_faces"
424 blabla = "\nDans {} :\n".format(nom_fonction)
426 nb_faces = len(l_faces)
427 if self._verbose_max:
428 print (blabla+"Nombre de faces : {}.".format(nb_faces))
430 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
431 for iaux, face in enumerate(l_faces):
432 _, aire, _ = geompy.BasicProperties(face)
433 #longueur, aire, volume = geompy.BasicProperties(face)
434 if self._verbose_max:
435 texte = "\t. Face numéro {}".format(iaux)
436 #texte += "\n\t. longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume)
439 tb_caract [iaux][0] = face
440 tb_caract [iaux][1] = aire
441 tb_caract [iaux][2] = geompy.KindOfShape(face)
442 if self._verbose_max:
443 print ("\t. tb_caract : {} {}".format(aire,tb_caract[iaux][2]))
447 #=========================== Fin de la méthode ==================================
449 #=========================== Début de la méthode =================================
451 def _tri_faces ( self, tb_caract ):
452 """Trie les faces en fonction de leurs surfaces
455 :geompy: environnement de GEOM
458 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
464 nom_fonction = __name__ + "/_tri_faces"
465 blabla = "\nDans {} :\n".format(nom_fonction)
467 # Tri du tableau en fonction des surfaces
468 if self._verbose_max:
469 print (blabla+"tb_caract brut : {}".format(tb_caract))
470 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
471 if self._verbose_max:
472 print ("tb_caract trié : {}".format(tb_caract_1))
475 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
476 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
479 # La surface suivante doit être différente, sinon ce n'est pas un solide mince
480 if ( np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1]) < self.epsilon ):
481 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
482 message += ". Surface de la face suivante : {}\n".format(tb_caract_1[-2][1])
483 message += ". Surface de la 3ème face suivante : {}\n".format(tb_caract_1[-3][1])
484 message += "==> L'écart est trop faible.\n"
485 message += "Impossible de créer la face médiane pour le solide '{}' ".format(self.nom_solide)
486 message += "car le solide n'est pas assez mince."
489 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
491 #=========================== Fin de la méthode ==================================
493 #=========================== Début de la méthode =================================
495 def _calcul_caract_aretes_face ( self, geompy, caract_face ):
496 """Détermine les caractéristiques des arêtes d'une face
499 :geompy: environnement de GEOM
500 :caract_face: les caractéristiques de la face
503 :caract_arete_face: les caractéristiques des arêtes de la face
506 nom_fonction = __name__ + "/_calcul_caract_aretes_face"
507 blabla = "\nDans {} :\n".format(nom_fonction)
509 if self._verbose_max:
511 texte += "face : {}\n".format(caract_face)
514 # Détermination des arêtes pour chaque face
515 face = caract_face[0]
516 l_aretes = geompy.ExtractShapes(face, geompy.ShapeType["EDGE"], True)
517 caract_arete_face = list()
518 for arete in l_aretes:
519 caract_arete_face.append(geompy.KindOfShape(arete))
521 if self._verbose_max:
522 print ("Aretes de la face : {}".format(caract_arete_face))
524 return caract_arete_face
526 #=========================== Fin de la méthode ==================================
528 #=========================== Début de la méthode =================================
530 def _cree_face_mediane ( self, geompy, solide, caract_face_1, caract_face_2 ):
531 """Crée la face médiane entre deux autres
534 :geompy: environnement de GEOM
535 :solide: l'objet solide à traiter
536 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
539 :face: la face médiane
545 nom_fonction = __name__ + "/_cree_face_mediane"
546 blabla = "\nDans {} :\n".format(nom_fonction)
548 if self._verbose_max:
550 texte += "face_1 : {}\n".format(caract_face_1)
551 texte += "face_2 : {}".format(caract_face_2)
556 # 1. Forme de la face
557 forme = caract_face_1[2][0]
558 if self._verbose_max:
559 print ("forme = {}".format(forme) )
561 # 2. Traitement selon la forme de la face
563 if forme in ( geompy.kind.DISK_CIRCLE, geompy.kind.DISK_ELLIPSE, geompy.kind.POLYGON, geompy.kind.PLANE, geompy.kind.PLANAR):
564 erreur, message, face = self._cree_face_mediane_polygone ( geompy, caract_face_1, caract_face_2 )
566 # 2.2. Face cylindrique
567 elif forme == geompy.kind.CYLINDER2D:
568 face = self._cree_face_mediane_cylindre ( geompy, solide, caract_face_1, caract_face_2 )
570 # 2.3. Face sphérique
571 elif forme == geompy.kind.SPHERE2D:
572 face = self._cree_face_mediane_sphere ( geompy, solide, caract_face_1, caract_face_2 )
575 elif forme == geompy.kind.TORUS2D:
576 face = self._cree_face_mediane_tore ( geompy, solide, caract_face_1, caract_face_2 )
579 elif forme == geompy.kind.CONE2D:
580 face = self._cree_face_mediane_cone ( geompy, solide, caract_face_1, caract_face_2 )
582 # 2.N. Face de forme inconnue
584 self.faces_pb_msg += "Impossible de créer la face médiane pour le solide '{}' ".format(self.nom_solide)
585 self.faces_pb_msg += "car sa face la plus grande est de forme : {}\n".format(forme)
586 self.faces_pb_nb += 1
588 # 3. Gestion de la face produite
591 erreur, message = self._cree_face_mediane_0 ( geompy, face )
595 return erreur, message, face
597 #=========================== Fin de la méthode ==================================
599 #=========================== Début de la méthode =================================
601 def _cree_face_mediane_0 ( self, geompy, face ):
602 """Gestion de la face médiane créée entre deux autres
605 :geompy: environnement de GEOM
606 :face: la face médiane créée
611 nom_fonction = __name__ + "/_cree_face_mediane_0"
612 blabla = "\nDans {} :\n".format(nom_fonction)
614 if self._verbose_max:
620 # 3.1. Insertion dans l'étude
621 nom_face = self.nom_solide+"_M"
622 geompy.addToStudy (face,nom_face)
624 # 3.2. Transfert éventuel de GEOM vers SHAPER
625 if self._retour_shaper:
627 # 3.2.1. Le fichier doit être différent à chaque fois
628 #print ("l_faces_trans = {}".format(self.l_faces_trans))
632 if nom_fic in self.l_faces_trans:
633 nom_fic = "{}_{}".format(nom_face,iaux)
637 self.l_faces_trans.append(nom_fic)
638 fichier = os.path.join(self.rep_trav, "{}.stp".format(nom_fic))
640 # 3.2.2. Exportation depuis GEOM
641 if self._verbose_max:
642 texte = "Exportation depuis GEOM de la face médiane '{}' dans le fichier {}".format(nom_face,fichier)
645 geompy.ExportSTEP (face, fichier)
646 except OSError as err:
648 message += "Impossible d'exporter la face médiane '{}' dans le fichier {}".format(nom_face,fichier)
652 # 3.2.3. Importation dans SHAPER
653 if self._verbose_max:
654 texte = "Importation dans SHAPER de la face médiane '{}' depuis le fichier {}".format(nom_face,fichier)
656 face_mediane = model.addImportSTEP(self.part_doc, fichier, False, False, False)
657 face_mediane.execute(True)
661 face_mediane.setName(nom_face)
662 face_mediane.result().setName(nom_face)
664 # La couleur. Attention aux conventions différents entr GEOM et SHAPER
666 tbaux = np.array(face.GetColor()._tuple())
667 np_aux = (tbaux<0.).nonzero()
670 np_aux = (tbaux>1.).nonzero()
674 face_mediane.result().setColor(int(tbaux[0]), int(tbaux[1]), int(tbaux[2]))
679 return erreur, message
681 #=========================== Fin de la méthode ==================================
683 #=========================== Début de la méthode =================================
685 def _cree_face_mediane_polygone ( self, geompy, caract_face_1, caract_face_2 ):
686 """Crée la face médiane entre deux autres - cas des polygones
689 :geompy: environnement de GEOM
690 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
693 :face: la face médiane
699 nom_fonction = __name__ + "/_cree_face_mediane_polygone"
700 blabla = "\nDans {} :\n".format(nom_fonction)
705 face_1 = caract_face_1[0]
706 face_2 = caract_face_2[0]
707 if self._verbose_max:
709 texte += "face_1 : {}\n".format(caract_face_1)
710 texte += "face_2 : {}".format(caract_face_2)
713 # Les 2 surfaces doivent être les mêmes, sinon c'est qu'elles ne sont pas similaires
714 ecart = np.abs((caract_face_1[1]-caract_face_2[1])/caract_face_1[1])
715 if ( ecart > self.epsilon ):
717 message += ". Surface de la plus grande face : {}\n".format(caract_face_1[1])
718 message += ". Surface de la face suivante : {}\n".format(caract_face_2[1])
720 # Distance entre les deux faces
721 d_face_1_2 = geompy.MinDistance(face_1, face_2)
723 print ("\tDistance entre les deux faces = {}".format(d_face_1_2))
725 # Copie de la plus grande face
726 face_1_copie= geompy.MakeCopy(face_1)
727 if self._verbose_max:
728 geompy.addToStudy(face_1_copie, face_1.GetName()+"_copie" )
730 # On la translate d'une demi épaisseur
731 # Attention : les normales des faces issues de l'explosion du solide sont dirigées vers l'extérieur.
732 # Comme il faut translater la face vers l'intérieur, on le fait avec une distance négative.
733 vnorm_face_1_copie = geompy.GetNormal(face_1_copie)
734 face = geompy.TranslateVectorDistance (face_1_copie, vnorm_face_1_copie, -0.5*d_face_1_2)
736 # Si les 2 surfaces ne sont pas similaires, on a quand même tenté la création mais on le signale
737 if ( ecart > self.epsilon ):
738 face.SetColor(SALOMEDS.Color(0,0,1))
739 message += "Problème pour créer la face médiane pour le solide '{}' : ".format(self.nom_solide)
740 message += "ce n'est pas un véritable polyèdre."
742 message += "\nL'écart de surface entre les 2 plus grandes faces est trop grand : {:5.2f}%.\n".format(ecart*100.)
743 message += "Tentative de création à partir de la plus grande des faces du solide."
746 face.SetColor(SALOMEDS.Color(0,1,0))
750 return erreur, message, face
752 #=========================== Fin de la méthode ==================================
754 #=========================== Début de la méthode =================================
756 def _cree_face_mediane_cylindre ( self, geompy, solide, caract_face_1, caract_face_2 ):
757 """Crée la face médiane entre deux autres - cas des cylindres
760 :geompy: environnement de GEOM
761 :solide: l'objet solide à traiter
762 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
765 :face: la face médiane
769 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
770 blabla = "\nDans {} :\n".format(nom_fonction)
773 if self._verbose_max:
775 texte += "face_1 : {}\n".format(caract_face_1)
776 texte += "face_2 : {}".format(caract_face_2)
779 # Caractéristiques des cylindres
780 coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur = self._cree_face_mediane_cylindre_0 ( geompy, solide, caract_face_1, caract_face_2 )
782 # Création de la face
783 centre, axe, cylindre = self._cree_face_mediane_cylindre_1 ( geompy, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur )
785 # Gestion de l'intersection avec le solide initial
786 face = self._cree_face_mediane_cylindre_2 ( geompy, solide, centre, axe, cylindre )
789 face.SetColor(SALOMEDS.Color(0,1,0))
793 #=========================== Fin de la méthode ==================================
795 #=========================== Début de la méthode =================================
797 def _cree_face_mediane_cylindre_0 ( self, geompy, solide, caract_face_1, caract_face_2 ):
798 """Crée la face médiane entre deux autres - cas des cylindres
800 Décodage des caractéristiques
803 :geompy: environnement de GEOM
804 :solide: l'objet solide à traiter
805 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
808 :coo_x, coo_y, coo_z: coordonnées du centre de la base
809 :axe_x, axe_y, axe_z: coordonnées de l'axe
810 :rayon: rayon moyen entre les deux faces
811 :hauteur: hauteur du cylindre
814 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
815 blabla = "\nDans {} :\n".format(nom_fonction)
818 if self._verbose_max:
820 texte += "face_1 : {}\n".format(caract_face_1)
821 texte += "face_2 : {}".format(caract_face_2)
824 # Coordonnées du centre de la base
825 coo_x = caract_face_1[2][1]
826 coo_y = caract_face_1[2][2]
827 coo_z = caract_face_1[2][3]
828 # Coordonnées de l'axe
829 axe_x = caract_face_1[2][4]
830 axe_y = caract_face_1[2][5]
831 axe_z = caract_face_1[2][6]
833 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
834 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
835 hauteur = self._calcul_hauteur_englobante ( geompy, solide )
837 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur
839 #=========================== Fin de la méthode ==================================
841 #=========================== Début de la méthode =================================
843 def _cree_face_mediane_cylindre_1 ( self, geompy, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur ):
844 """Crée la face médiane entre deux autres - cas des cylindres
846 Création des objets temporaires et de la face externe du cylindre support
849 :geompy: environnement de GEOM
850 :coo_x, coo_y, coo_z: coordonnées du centre de la base
851 :axe_x, axe_y, axe_z: coordonnées de l'axe
852 :rayon: rayon moyen entre les deux faces
853 :hauteur: hauteur du cylindre
856 :centre: le centre de la base du cylindre médian
857 :axe: l'axe des cylindres
858 :cylindre: le cylindre support
860 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
861 blabla = "\nDans {} :\n".format(nom_fonction)
864 if self._verbose_max:
866 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
867 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
868 texte += "Rayon : {}\n".format(rayon)
869 texte += "Hauteur : {}".format(hauteur)
872 # Création du point central
873 centre = geompy.MakeVertex(coo_x, coo_y, coo_z)
874 #geompy.addToStudy( centre, "centre" )
877 axe = geompy.MakeVectorDXDYDZ(axe_x, axe_y, axe_z)
878 #geompy.addToStudy( axe, "axe" )
880 # Création d'un cylindre
881 cylindre = geompy.MakeCylinder(centre, axe, rayon, hauteur)
882 if self._verbose_max:
883 geompy.addToStudy( cylindre, "cylindre médian" )
885 return centre, axe, cylindre
887 #=========================== Fin de la méthode ==================================
889 #=========================== Début de la méthode =================================
891 def _cree_face_mediane_cylindre_2 ( self, geompy, solide, centre, axe, cylindre ):
892 """Crée la face médiane entre deux autres - cas des cylindres
894 Intersection de la face cylindrique avec le solide initial
897 :geompy: environnement de GEOM
898 :solide: l'objet solide à traiter
899 :centre: le centre de la base du cylindre médian
900 :axe: l'axe des cylindres
901 :cylindre: le cylindre support
904 :face: la face médiane
908 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_2"
909 blabla = "\nDans {} :\n".format(nom_fonction)
911 if self._verbose_max:
914 # Récupération de la bonne face après intersection du cylindre avec le solide initial
915 face = self._creation_face_inter ( geompy, solide, cylindre, 1 )
917 # Pour des raisons inconnues de moi, il arrive que l'axe donné par les caractéristiques soit dans le mauvais sens.
918 # Dans ce cas l'intersection est vide, et il faut retourner la face créée précédemment et recalculer l'intersection.
919 tb_caract = geompy.KindOfShape(face)
920 if ( tb_caract[1] == 0 ):
921 if self._verbose_max:
922 print ("On opère un retournement du cylindre.")
923 plan_de_base = geompy.MakePlane(centre, axe, 100)
924 #geompy.addToStudy( plan_de_base, "plan_de_base" )
925 geompy.MirrorByPlane(cylindre, plan_de_base)
926 # Récupération de la bonne face après intersection du cylindre retourné avec le solide initial
927 face = self._creation_face_inter ( geompy, solide, cylindre, 1 )
931 #=========================== Fin de la méthode ==================================
933 #=========================== Début de la méthode =================================
935 def _cree_face_mediane_sphere ( self, geompy, solide, caract_face_1, caract_face_2 ):
936 """Crée la face médiane entre deux autres - cas des sphères
939 :geompy: environnement de GEOM
940 :solide: l'objet solide à traiter
941 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
944 :face: la face médiane
948 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
949 blabla = "\nDans {} :\n".format(nom_fonction)
952 if self._verbose_max:
954 texte += "face_1 : {}\n".format(caract_face_1)
955 texte += "face_2 : {}".format(caract_face_2)
958 # Caractéristiques des sphères
959 coo_x, coo_y, coo_z, rayon = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2 )
961 # Création de la face
962 face = self._cree_face_mediane_sphere_1 ( geompy, solide, coo_x, coo_y, coo_z, rayon )
965 face.SetColor(SALOMEDS.Color(0,1,0))
969 #=========================== Fin de la méthode ==================================
971 #=========================== Début de la méthode =================================
973 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2 ):
974 """Crée la face médiane entre deux autres - cas des sphères
976 Décodage des caractéristiques
979 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
982 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
983 :rayon: rayon moyen entre les deux faces
986 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
987 blabla = "\nDans {} :\n".format(nom_fonction)
990 if self._verbose_max:
992 texte += "face_1 : {}\n".format(caract_face_1)
993 texte += "face_2 : {}".format(caract_face_2)
996 # Coordonnées du centre de la sphère
997 coo_x = caract_face_1[2][1]
998 coo_y = caract_face_1[2][2]
999 coo_z = caract_face_1[2][3]
1001 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1003 return coo_x, coo_y, coo_z, rayon
1005 #=========================== Fin de la méthode ==================================
1007 #=========================== Début de la méthode =================================
1009 def _cree_face_mediane_sphere_1 ( self, geompy, solide, coo_x, coo_y, coo_z, rayon ):
1010 """Crée la face médiane entre deux autres - cas des sphères
1012 Création des objets temporaires et de la face externe de la sphère support
1015 :geompy: environnement de GEOM
1016 :solide: l'objet solide à traiter
1017 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1018 :rayon: rayon moyen entre les deux faces
1021 :face: la face externe de la sphère support
1025 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1026 blabla = "\nDans {} :\n".format(nom_fonction)
1029 if self._verbose_max:
1031 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1032 texte += "Rayon : {}".format(rayon)
1035 # Création du point central
1036 centre = geompy.MakeVertex(coo_x, coo_y, coo_z)
1037 #geompy.addToStudy( centre, "centre" )
1039 # Création d'une sphère médiane
1040 sphere = geompy.MakeSpherePntR(centre, rayon)
1041 if self._verbose_max:
1042 geompy.addToStudy( sphere, "sphère médiane" )
1044 # Récupération de la bonne face après intersection avec le solide initial
1045 face = self._creation_face_inter ( geompy, solide, sphere, 0 )
1049 #=========================== Fin de la méthode ==================================
1051 #=========================== Début de la méthode =================================
1053 def _cree_face_mediane_tore ( self, geompy, solide, caract_face_1, caract_face_2 ):
1054 """Crée la face médiane entre deux autres - cas des tores
1057 :geompy: environnement de GEOM
1058 :solide: l'objet solide à traiter
1059 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1062 :face: la face médiane
1066 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1067 blabla = "\nDans {} :\n".format(nom_fonction)
1070 if self._verbose_max:
1072 texte += "face_1 : {}\n".format(caract_face_1)
1073 texte += "face_2 : {}".format(caract_face_2)
1076 # Caractéristiques des tores
1077 coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 = self._cree_face_mediane_tore_0 ( caract_face_1, caract_face_2 )
1079 # Création de la face
1080 face = self._cree_face_mediane_tore_1 ( geompy, solide, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1083 face.SetColor(SALOMEDS.Color(0,1,0))
1087 #=========================== Fin de la méthode ==================================
1089 #=========================== Début de la méthode =================================
1091 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2 ):
1092 """Crée la face médiane entre deux autres - cas des tores
1094 Décodage des caractéristiques
1097 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1100 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1101 :axe_x, axe_y, axe_z: coordonnées de l'axe
1102 :rayon_1 : rayon principal
1103 :rayon_2 : rayon secondaire
1106 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1107 blabla = "\nDans {} :\n".format(nom_fonction)
1110 if self._verbose_max:
1112 texte += "face_1 : {}\n".format(caract_face_1)
1113 texte += "face_2 : {}".format(caract_face_2)
1116 # Coordonnées du centre du tore
1117 coo_x = caract_face_1[2][1]
1118 coo_y = caract_face_1[2][2]
1119 coo_z = caract_face_1[2][3]
1120 # Coordonnées de l'axe
1121 axe_x = caract_face_1[2][4]
1122 axe_y = caract_face_1[2][5]
1123 axe_z = caract_face_1[2][6]
1125 rayon_1 = caract_face_2[2][7]
1126 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1128 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1130 #=========================== Fin de la méthode ==================================
1132 #=========================== Début de la méthode =================================
1134 def _cree_face_mediane_tore_1 ( self, geompy, solide, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1135 """Crée la face médiane entre deux autres - cas des tores
1137 Création des objets temporaires et de la face externe du tore support
1140 :geompy: environnement de GEOM
1141 :solide: l'objet solide à traiter
1142 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1143 :axe_x, axe_y, axe_z: coordonnées de l'axe
1144 :rayon_1 : rayon principal
1145 :rayon_2 : rayon secondaire
1148 :face: la face externe du tore support
1152 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1153 blabla = "\nDans {} :\n".format(nom_fonction)
1156 if self._verbose_max:
1158 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1159 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1160 texte += "Rayon principal : {}\n".format(rayon_1)
1161 texte += "Rayon secondaire : {}".format(rayon_2)
1164 # Création du point central
1165 centre = geompy.MakeVertex(coo_x, coo_y, coo_z)
1166 #geompy.addToStudy( centre, "centre" )
1169 axe = geompy.MakeVectorDXDYDZ(axe_x, axe_y, axe_z)
1170 #geompy.addToStudy( axe, "axe" )
1172 # Création d'un tore médian
1173 tore = geompy.MakeTorus(centre, axe, rayon_1, rayon_2)
1174 if self._verbose_max:
1175 geompy.addToStudy( tore, "tore médian" )
1177 # Récupération de la bonne face après intersection avec le solide initial
1178 face = self._creation_face_inter ( geompy, solide, tore, 0 )
1182 #=========================== Fin de la méthode ==================================
1184 #=========================== Début de la méthode =================================
1186 def _cree_face_mediane_cone ( self, geompy, solide, caract_face_1, caract_face_2 ):
1187 """Crée la face médiane entre deux autres - cas des cones
1190 :geompy: environnement de GEOM
1191 :solide: l'objet solide à traiter
1192 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1195 :face: la face médiane
1199 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1200 blabla = "\nDans {} :\n".format(nom_fonction)
1203 if self._verbose_max:
1205 texte += "face_1 : {}\n".format(caract_face_1)
1206 texte += "face_2 : {}".format(caract_face_2)
1209 # Caractéristiques des cones
1210 coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur = self._cree_face_mediane_cone_0 ( geompy, caract_face_1, caract_face_2 )
1212 # Création de la face
1213 centre, axe, cone = self._cree_face_mediane_cone_1 ( geompy, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1215 # Gestion de l'intersection avec le solide initial
1216 face = self._cree_face_mediane_cone_2 ( geompy, solide, centre, axe, cone )
1219 face.SetColor(SALOMEDS.Color(0,1,0))
1223 #=========================== Fin de la méthode ==================================
1225 #=========================== Début de la méthode =================================
1227 def _cree_face_mediane_cone_0 ( self, geompy, caract_face_1, caract_face_2 ):
1228 """Crée la face médiane entre deux autres - cas des cones
1230 Décodage des caractéristiques
1233 :geompy: environnement de GEOM
1234 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1237 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1238 :axe_x, axe_y, axe_z: coordonnées de l'axe
1239 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1240 :hauteur: hauteur du cone
1243 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1244 blabla = "\nDans {} :\n".format(nom_fonction)
1247 if self._verbose_max:
1249 texte += "face_1 : {}\n".format(caract_face_1)
1250 texte += "face_2 : {}".format(caract_face_2)
1253 # Coordonnées du centre de la base
1254 coo_x = caract_face_1[2][1]
1255 coo_y = caract_face_1[2][2]
1256 coo_z = caract_face_1[2][3]
1257 # Coordonnées de l'axe
1258 axe_x = caract_face_1[2][4]
1259 axe_y = caract_face_1[2][5]
1260 axe_z = caract_face_1[2][6]
1262 # Pour un cone complet, les caractéristiques forunies par GEOM sont correctes
1263 # Mais s'il est découpé, malheureusement,bug dans GEOM et caract_face_2[2][8] est toujours nul !
1264 # Alors on passe par le décodage des arêtes
1265 #rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1266 #rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1267 caract_arete_face_1 = self._calcul_caract_aretes_face ( geompy, caract_face_1 )
1268 caract_arete_face_2 = self._calcul_caract_aretes_face ( geompy, caract_face_2 )
1271 for caract_aretes_face in [caract_arete_face_1,caract_arete_face_2]:
1273 for l_aux in caract_aretes_face:
1274 if ( l_aux[0] in ( geompy.kind.CIRCLE, geompy.kind.ARC_CIRCLE ) ):
1275 #print ("R =",l_aux[7])
1284 hauteur = caract_face_1[2][9]
1286 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1288 #=========================== Fin de la méthode ==================================
1290 #=========================== Début de la méthode =================================
1292 def _cree_face_mediane_cone_1 ( self, geompy, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1293 """Crée la face médiane entre deux autres - cas des cones
1295 Création des objets temporaires et de la face externe du cone support
1298 :geompy: environnement de GEOM
1299 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1300 :axe_x, axe_y, axe_z: coordonnées de l'axe
1301 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1302 :hauteur: hauteur du cone
1305 :centre: le centre de la base du cone médian
1306 :axe: l'axe des cones
1307 :cone: le cone support
1309 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1310 blabla = "\nDans {} :\n".format(nom_fonction)
1313 if self._verbose_max:
1315 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1316 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1317 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1318 texte += "Hauteur : {}".format(hauteur)
1321 # Création du point central
1322 centre = geompy.MakeVertex(coo_x, coo_y, coo_z)
1323 #geompy.addToStudy( centre, "centre" )
1326 axe = geompy.MakeVectorDXDYDZ(axe_x, axe_y, axe_z)
1327 #geompy.addToStudy( axe, "axe" )
1329 # Création d'un cone
1330 cone = geompy.MakeCone(centre, axe, rayon_1, rayon_2, hauteur)
1331 if self._verbose_max:
1332 geompy.addToStudy( cone, "cone médian" )
1334 return centre, axe, cone
1336 #=========================== Fin de la méthode ==================================
1338 #=========================== Début de la méthode =================================
1340 def _cree_face_mediane_cone_2 ( self, geompy, solide, centre, axe, cone ):
1341 """Crée la face médiane entre deux autres - cas des cones
1343 Intersection de la face cylindrique avec le solide initial
1346 :geompy: environnement de GEOM
1347 :solide: l'objet solide à traiter
1348 :centre: le centre de la base du cone médian
1349 :axe: l'axe des cones
1350 :cone: le cone support
1353 :face: la face médiane
1357 nom_fonction = __name__ + "/_cree_face_mediane_cone_2"
1358 blabla = "\nDans {} :\n".format(nom_fonction)
1360 if self._verbose_max:
1363 # Récupération de la bonne face après intersection du cone avec le solide initial
1364 face = self._creation_face_inter ( geompy, solide, cone, 1 )
1366 # Pour des raisons inconnues de moi, il arrive que l'axe donné par les caractéristiques soit dans le mauvais sens.
1367 # Dans ce cas l'intersection est vide, et il faut retourner la face créée précédemment et recalculer l'intersection.
1368 tb_caract = geompy.KindOfShape(face)
1369 if ( tb_caract[1] == 0 ):
1370 if self._verbose_max:
1371 print ("On opère un retournement du cone.")
1372 plan_de_base = geompy.MakePlane(centre, axe, 100)
1373 #geompy.addToStudy( plan_de_base, "plan_de_base" )
1374 geompy.MirrorByPlane(cone, plan_de_base)
1375 # Récupération de la bonne face après intersection du cone retourné avec le solide initial
1376 face = self._creation_face_inter ( geompy, solide, cone, 1 )
1380 #=========================== Fin de la méthode ==================================
1382 #=========================== Début de la méthode =================================
1384 def _calcul_hauteur_englobante ( self, geompy, solide ):
1385 """Crée la hauteur englobant à coup sûr le solide
1387 Décodage des caractéristiques
1390 :geompy: environnement de GEOM
1391 :solide: l'objet solide à traiter
1394 :hauteur: hauteur englobante
1397 nom_fonction = __name__ + "/_calcul_hauteur_englobante"
1398 blabla = "\nDans {} :\n".format(nom_fonction)
1401 if self._verbose_max:
1404 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
1405 bounding_box = geompy.BoundingBox(solide)
1406 if self._verbose_max:
1407 texte = "Boîte englobante du solide '{}'\n".format(self.nom_solide)
1408 texte += "\tXmin = {}, Xmax = {}\n".format(bounding_box[0],bounding_box[1])
1409 texte += "\tYmin = {}, Ymax = {}\n".format(bounding_box[2],bounding_box[3])
1410 texte += "\tZmin = {}, Zmax = {}".format(bounding_box[4],bounding_box[5])
1413 coo_1 = np.array([bounding_box[0],bounding_box[2],bounding_box[4]])
1414 coo_2 = np.array([bounding_box[1],bounding_box[3],bounding_box[5]])
1415 longueur = np.linalg.norm(coo_2-coo_1)
1416 if self._verbose_max:
1417 print ("Longueur de la diagonale {}".format(longueur))
1418 hauteur = 1.2*longueur
1422 #=========================== Fin de la méthode ==================================
1424 #=========================== Début de la méthode =================================
1426 def _creation_face_inter ( self, geompy, solide, objet, numero ):
1429 . Repère la face principale de l'objet support
1430 . Réalise l'intersection avec le solide initial
1433 :geompy: environnement de GEOM
1434 :solide: l'objet solide à traiter
1435 :objet: l'objet support de la face
1436 :numero: numero de la face dans l'explosion de l'objet support
1439 :face: la face externe de l'objet support intersecté avec le solide initial
1442 nom_fonction = __name__ + "/_creation_face_inter"
1443 blabla = "\nDans {} :\n".format(nom_fonction)
1446 if self._verbose_max:
1449 # Récupération de la bonne face
1450 l_aux = geompy.ExtractShapes(objet, geompy.ShapeType["FACE"], True)
1451 face_1 = geompy.MakeShell([l_aux[numero]])
1452 #geompy.addToStudy( face_1, "face externe" )
1454 # Intersection entre la face externe du solide médian et le solide initial
1455 face = geompy.MakeCommonList([solide, face_1], True)
1456 #geompy.addToStudy( face, "face" )
1460 #=========================== Fin de la méthode ==================================
1462 #=========================== Début de la méthode =================================
1464 def _menage_faces ( self, gst, l_faces ):
1465 """Fait le ménage des faces dans l'étude
1468 :gst: environnement de GeomStudyTools
1469 :l_faces: liste des faces du solide
1472 nom_fonction = __name__ + "/_menage_faces"
1473 blabla = "\nDans {} :\n".format(nom_fonction)
1475 if self._verbose_max:
1477 texte += "Nombre de faces à supprimer : {}\n".format(len(l_faces))
1480 # Suppression des faces incluses dans l'étude
1482 for face in l_faces:
1483 if self._verbose_max:
1484 print ("\tSuppression de {}".format(face.GetName()))
1485 gst.deleteShape(face.GetStudyEntry())
1487 # Rafraichissement de l'affichage
1488 salome.sg.updateObjBrowser()
1492 #=========================== Fin de la méthode ==================================
1494 #=========================== Début de la méthode =================================
1496 def face_mediane_solide (self, geompy, gst, solide):
1498 """Calcul de la face médiane pour un solide
1501 :geompy: environnement de GEOM
1502 :gst: environnement de GeomStudyTools
1503 :solide: l'objet solide à traiter
1506 :erreur: code d'erreur
1507 :message: message d'erreur
1510 nom_fonction = __name__ + "/face_mediane_solide"
1511 blabla = "\nDans {} :\n".format(nom_fonction)
1513 if self._verbose_max:
1516 print ("Traitement du solide '{}'".format(solide.GetName()))
1525 # 2. Explosion du solide en faces
1527 erreur, message, l_faces = self._faces_du_solide ( geompy, solide )
1531 # 3. Calcul des caractéristiques géométriques des faces
1533 tb_caract = self._calcul_caract_faces ( geompy, l_faces )
1535 # 4. Tri des faces en fonction de leurs caractéristiques géométriques
1537 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract )
1541 # 5. Création de la face médiane
1543 erreur, message, face = self._cree_face_mediane ( geompy, solide, caract_face_1, caract_face_2 )
1547 # 6. Ménage des faces
1549 if salome.sg.hasDesktop():
1550 if self._retour_shaper:
1551 l_faces.append(face)
1552 self._menage_faces ( gst, l_faces )
1558 if ( erreur and self._verbose_max ):
1559 print (blabla, message)
1561 return erreur, message
1563 #=========================== Fin de la méthode ==================================
1565 #=========================== Début de la méthode =================================
1567 def _menage_solides ( self, gst, l_solides, l_solides_m, type_selection, objet ):
1568 """Fait le ménage des solides dans l'étude
1571 :gst: environnement de GeomStudyTools
1572 :l_solides: liste des solides de l'objet
1573 :l_solides_m: liste des solides de l'objet dont on veut le ménage
1574 :type_selection: type de sélection de l'objet à traiter (0: graphique, 1: GEOM, 2;SHAPER)
1575 :objet: l'objet à traiter
1578 nom_fonction = __name__ + "/_menage_solides"
1579 blabla = "\nDans {} :\n".format(nom_fonction)
1581 if self._verbose_max:
1583 texte += "Nombre de solides de l'objet : {}\n".format(len(l_solides))
1584 texte += "Nombre de solides à supprimer : {}".format(len(l_solides_m))
1589 # Suppression des solides inclus dans l'étude dans le cas d'un assemblage explosé
1590 if ( len(l_solides) > 1 ):
1591 for solide in l_solides_m:
1592 if self._verbose_max:
1593 print ("\tSuppression de {}".format(solide.GetName()))
1594 gst.deleteShape(solide.GetStudyEntry())
1596 # Suppression de l'objet initial quand il vient d'une exportation depuis SHAPER si ça s'est mal passé
1597 if ( type_selection == 2 ):
1598 if ( len(l_solides) != len(l_solides_m) ):
1601 if self._verbose_max:
1602 print ("\tSuppression de {}".format(objet.GetName()))
1603 gst.deleteShape(objet.GetStudyEntry())
1605 # Mise en évidence des solides non détruits
1606 for solide in l_solides:
1607 if solide not in l_solides_m:
1608 solide.SetColor(SALOMEDS.Color(1,0,0))
1610 # Rafraichissement de l'affichage
1611 salome.sg.updateObjBrowser()
1615 #=========================== Fin de la méthode ==================================
1617 #=========================== Début de la méthode =================================
1619 def _traitement_objet (self, type_selection=0, objet=None ):
1620 """Traitement d'un objet
1623 :type_selection: type de sélection de l'objet à traiter (0: graphique, 1: GEOM, 2;SHAPER)
1624 :objet: l'objet à traiter quand il passe par argument
1627 :erreur: code d'erreur
1628 :message: message d'erreur
1631 nom_fonction = __name__ + "/_traitement_objet"
1632 blabla = "\nDans {} :\n".format(nom_fonction)
1634 if self._verbose_max:
1636 texte += "type_selection = {}".format(type_selection)
1648 if self.affiche_aide_globale :
1651 # 3. Les imports pour salomé
1652 geompy = geomBuilder.New()
1653 gst = geomtools.GeomStudyTools(getStudyEditor())
1655 # 4. Sélection de l'objet
1656 if ( type_selection == 0 ):
1657 erreur, message, objet = self._selection_objet_graphique ( geompy )
1658 elif ( type_selection in (1,2) ):
1661 message = "Le type d'objet {} est inconnu.".format(type_selection)
1666 # 5. En cas de retour vers shaper, répertoire de travail associé à l'éventuel fichier de départ
1667 if self._retour_shaper:
1668 if self.ficcao is None:
1669 self.rep_trav = tempfile.mkdtemp(prefix="{}_".format(objet.GetName()))
1671 self.rep_trav = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(objet.GetName()))
1672 if not os.path.isdir(self.rep_trav):
1673 os.mkdir(self.rep_trav)
1674 if self._verbose_max:
1675 print ("Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_trav))
1677 # 6. Liste des solides qui composent l'objet
1678 erreur, message, l_solides = self._les_solides ( geompy, objet )
1682 # 7. Calcul des surfaces médianes pour chaque solide
1683 l_solides_m = list()
1684 for solide in l_solides:
1685 erreur, message = self.face_mediane_solide (geompy, gst, solide)
1688 l_solides_m.append(solide)
1692 # 8. Ménage des solides
1694 if salome.sg.hasDesktop():
1695 self._menage_solides ( gst, l_solides, l_solides_m, type_selection, objet )
1697 # 9. Informations sur les faces à problème
1698 if self.faces_pb_nb:
1699 if ( self.faces_pb_nb == 1 ):
1700 texte = "1 face pose"
1702 texte = "{} faces posent".format(self.faces_pb_nb)
1703 print ("{} problème.\n{}".format(texte,self.faces_pb_msg))
1706 print ("Les fichiers CAO des surfaces sont dans le répertoire {}".format(self.rep_trav))
1710 return erreur, message
1712 #=========================== Fin de la méthode ==================================
1714 #=========================== Début de la méthode =================================
1716 def surf_fic_cao (self, ficcao):
1717 """Calcule la surface médiane pour un objet dans un fichier passé en argument
1720 :ficcao: fichier de l'objet à traiter
1723 :erreur: code d'erreur
1724 :message: message d'erreur
1727 nom_fonction = __name__ + "/surf_fic_cao"
1728 blabla = "\nDans {} :\n".format(nom_fonction)
1730 if self._verbose_max:
1738 # 1. Définition de la pièce
1740 self.part_doc = model.activeDocument()
1742 # 2. Import de la CAO
1744 self.ficcao = ficcao
1745 print ("Traitement du fichier {}".format(self.ficcao))
1747 erreur, message, objet = import_cao (self.part_doc, self.ficcao, self._verbose_max)
1751 # 3. Calcul des surfaces
1753 erreur, message = self.surf_objet_shaper ( objet.result().name(), objet.result().shapeType() )
1755 if ( erreur and self._verbose_max ):
1756 print (blabla, message)
1760 return erreur, message
1762 #=========================== Fin de la méthode ==================================
1764 #=========================== Début de la méthode =================================
1766 def surf_objet_shaper (self, nom_objet, type_objet):
1767 """Calcule la surface médiane pour un objet SHAPER passé en argument
1770 :nom_objet: nom de l'objet à traiter
1771 :type_objet: type de l'objet à traiter "SOLID"/"COMPOUND"
1774 :erreur: code d'erreur
1775 :message: message d'erreur
1778 nom_fonction = __name__ + "/surf_objet_shaper"
1779 blabla = "\nDans {} :\n".format(nom_fonction)
1781 if self._verbose_max:
1789 # 1. Transfert vers GEOM
1790 # 1.1. Le départ est-il un fichier au format step ?
1792 if self.ficcao is not None:
1793 laux = self.ficcao.split(".")
1794 fmt_cao_0 = decode_cao (laux[-1])
1795 if ( fmt_cao_0 == "stp" ):
1797 if self._verbose_max:
1798 print ("deja_step = {}".format(deja_step))
1800 # 1.1. Exportation si le fichier de départ n'est pas au format step
1802 fichier = self.ficcao
1804 fichier = tempfile.mkstemp(suffix=".stp")[1]
1805 if self._verbose_max:
1806 print ('fichier = {}'.format(fichier))
1807 print ('nom_objet = {}'.format(nom_objet))
1808 print ('type_objet = {}'.format(type_objet))
1809 export = model.exportToFile(self.part_doc, fichier, [model.selection(type_objet, nom_objet)])
1810 export.execute(True)
1812 taille = os.path.getsize(fichier)
1814 message = "Export de SHAPER vers GEOM impossible pour l'objet '{}' de type '{}'\n".format(nom_objet, type_objet)
1815 message += "Le fichier {} est de taille {}".format(fichier,taille)
1820 geompy = geomBuilder.New()
1821 objet = geompy.ImportSTEP(fichier, False, True)
1822 geompy.addToStudy( objet, nom_objet )
1826 # 2. Traitement de l'objet GEOM correspondant
1827 erreur, message = self._traitement_objet ( 2, objet )
1829 if ( erreur and self._verbose_max ):
1830 print (blabla, message)
1834 return erreur, message
1836 #=========================== Fin de la méthode ==================================
1838 #=========================== Début de la méthode =================================
1840 def surf_objet_geom (self, objet):
1841 """Calcule la surface médiane pour un objet GEOM passé en argument
1844 :objet: l'objet à traiter
1847 :erreur: code d'erreur
1848 :message: message d'erreur
1851 nom_fonction = __name__ + "/surf_objet_geom"
1852 blabla = "\nDans {} :\n".format(nom_fonction)
1854 if self._verbose_max:
1857 erreur, message = self._traitement_objet ( 1, objet )
1859 if ( erreur and self._verbose_max ):
1860 print (blabla, message)
1862 return erreur, message
1864 #=========================== Fin de la méthode ==================================
1866 #=========================== Début de la méthode =================================
1868 def lancement (self):
1873 :erreur: code d'erreur
1874 :message: message d'erreur
1877 nom_fonction = __name__ + "/lancement"
1878 blabla = "\nDans {} :\n".format(nom_fonction)
1880 if self._verbose_max:
1883 erreur, message = self._traitement_objet ( )
1885 if ( erreur and self._verbose_max ):
1886 print (blabla, message)
1888 return erreur, message
1890 #=========================== Fin de la méthode ==================================
1892 #========================== Fin de la classe ====================================
1894 #==================================================================================
1896 #==================================================================================
1898 if __name__ == "__main__" :
1903 #L_OPTIONS.append("-h")
1904 #L_OPTIONS.append("-v")
1905 #L_OPTIONS.append("-vmax")
1906 #L_OPTIONS.append("-no_menage")
1907 #L_OPTIONS.append("-retour_shaper")
1909 # 2. Lancement de la classe
1911 #print ("L_OPTIONS :", L_OPTIONS)
1912 SURFACE_MEDIANE = SurfaceMediane(L_OPTIONS)
1913 if SURFACE_MEDIANE.affiche_aide_globale:
1914 sys.stdout.write(SURFACE_MEDIANE.__doc__+"\n")
1916 ERREUR, MESSAGE_ERREUR = SURFACE_MEDIANE.lancement()
1918 MESSAGE_ERREUR += "\n Code d'erreur : %d\n" % ERREUR
1919 sys.stderr.write(MESSAGE_ERREUR)