1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2022 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 Pour un objet complexe, on crée l'objet final comme étant la partition de toutes
30 les surfaces médianes.
32 Version initiale par :
33 alexandre.prunie@blastsolutions.io
34 guillaume.schweitzer@blastsolutions.io
39 __revision__ = "V10.48"
41 #========================= Les imports - Début ===================================
53 from SketchAPI import *
54 from salome.shaper import model
56 from GeomAlgoAPI import *
58 from salome.geom import geomBuilder
62 #========================== Les imports - Fin ====================================
65 D_FMT["stp"] = ["stp", "step"]
66 D_FMT["igs"] = ["igs", "iges"]
67 for CLE in ("brep", "xao"):
70 # statut = 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
89 # Transparence des solides traités correctement
92 # Limite basse de l'épaisseur pour pouvoir faire les intersections
95 #========================= Début de la fonction ==================================
97 def decode_cao (fmt_cao):
98 """Décode le format de la cao
101 :fmt_cao: format du fichier, step, iges, etc.
103 :fmt_cao_0: format décodé
108 fmt_cao_low = fmt_cao.lower()
110 for cle, l_aux in D_FMT.items():
111 if ( fmt_cao_low in l_aux ):
117 #========================= Fin de la fonction ===================================
119 #========================= Début de la fonction ==================================
121 def import_cao (part_doc, ficcao, nom_objet=None, verbose=False):
122 """Importation d'une cao
126 :ficcao: le fichier de la CAO
128 :objet: l'objet importé dans SHAPER
133 message = "Fichier '{}'\n".format(ficcao)
139 laux = ficcao.split(".")
140 fmt_cao_0 = decode_cao (laux[-1])
142 if ( fmt_cao_0 not in ("stp", "brep", "igs", "xao") ):
143 message += "Le format de CAO est inconnu"
147 message += "Le fichier de CAO n'a pas été décodé correctement."
150 elif not os.path.isfile(ficcao):
151 message += "Le fichier de CAO est inconnu."
157 objet = model.addImport(part_doc, ficcao)
161 if nom_objet is not None:
162 objet.result().setName(nom_objet)
165 texte = "Objet : '{}'\n".format(objet.result().name())
166 texte += "De type : '{}'".format(objet.result().shapeType())
170 return erreur, message, objet
172 #========================= Fin de la fonction ===================================
174 #=================================== La classe ===================================
176 class SurfaceMediane (object):
178 """Calcul des surfaces médianes de solides minces
180 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
181 une structure qui est un solide ou un assemblage de solides (compound).
182 Pour réaliser l'opération, trois façons de faire :
184 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
186 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
187 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
189 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
190 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
193 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
194 de taille identique et supérieure aux tailles des autres faces du solide. \
195 Cela fonctionne pour des surfaces planes ou de forme canonique.
196 Il crée alors une surface au milieu de ces deux grandes faces. \
197 Cette face est coloriée en vert, le solide est en vert et transparent.
199 On sait traiter les faces :
206 Si la création n'a pas eu lieu, un message est émis et les solides sont mise en couleur :
207 . Rouge : le solide n'est pas assez mince.
208 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
209 . Orange : la forme de la face n'est pas reconnue.
217 . Exportation finale dans un fichier step. Par défaut, pas d'export.
218 -export_step/-no_export_step
227 affiche_aide_globale = 0
234 nom_solide_aux = None
240 objet_principal = None
242 # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
244 # Statut de chaque sous-objet connu par son nom :
245 # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
247 # Liste des faces médianes créées et des fonctions initiales
249 # La fonction initiale
255 #=========================== Début de la méthode =================================
257 def __init__ ( self, liste_option ):
259 """Le constructeur de la classe SurfaceMediane
261 Décodage des arguments
262 On cherche ici les arguments généraux : aide, verbeux
265 for option in liste_option :
268 if isinstance(option,str):
269 saux = option.upper()
271 if saux in ( "-H", "-HELP" ):
272 self.affiche_aide_globale = 1
275 elif saux == "-VMAX" :
277 self._verbose_max = 1
278 elif saux == "-EXPORT_STEP":
279 self._export_step = True
280 elif saux == "-NO_EXPORT_STEP":
281 self._export_step = False
283 #=========================== Fin de la méthode ==================================
285 #=========================== Début de la méthode =================================
288 """A la suppression de l'instance de classe"""
289 if self._verbose_max:
290 print ("Suppression de l'instance de la classe.")
292 #=========================== Fin de la méthode ==================================
294 #=========================== Début de la méthode =================================
296 def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
297 """Gère les noms des sous_objets solides
300 :objet: objet à traiter
301 :lecture: vrai pour lire les noms, faux pour les attribuer
302 :n_recur: niveau de récursivité
303 :rang: rang du sous-objet
306 :rang: rang du sous-objet
309 nom_fonction = __name__ + "/_nom_sous_objets"
310 blabla = "Dans {} :\n".format(nom_fonction)
312 if self._verbose_max:
314 for _ in range(n_recur):
316 texte = "\n{}{}".format(prefixe,blabla)
317 texte += "{}n_recur = {}".format(prefixe,n_recur)
318 texte += "\n{}lecture = {}".format(prefixe,lecture)
321 # 1. Au premier passage, il faut garder la référence au résultat principal
324 objet_0 = objet.result()
325 if self._verbose_max:
326 print ("d_statut_so = {}".format(self.d_statut_so))
330 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
332 nb_sub_results = objet_0.numberOfSubs()
334 if self._verbose_max:
335 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
336 texte += "de type '{}'".format(objet_0.shapeType())
337 texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
340 for n_sobj in range(nb_sub_results):
342 # 2.1. Exploration récursive de l'arborescence
344 rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
346 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
348 if ( objet_0.shapeType() == "SOLID" ):
349 # A la lecture, on enregistre le nom
352 self.l_noms_so.append(nom)
353 self.d_statut_so[nom] = 0
354 # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
356 nom = self.l_noms_so[rang]
358 etat = self.d_statut_so[nom]
359 objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
361 objet_0.setTransparency (TRANSPARENCE)
366 #=========================== Fin de la méthode ==================================
368 #=========================== Début de la méthode =================================
370 def _couleur_objet (self, objet, n_recur=0, coul_r=1, coul_g=0, coul_b=0):
371 """Appliquer une couleur à un objet et à ses sous_objets
374 :objet: objet à traiter
375 :n_recur: niveau de récursivité
376 :coul_r,coul_g,coul_b: code RGB de la couleur à appliquer
379 :rang: rang du sous-objet
382 nom_fonction = __name__ + "/_couleur_objet"
383 blabla = "Dans {} :\n".format(nom_fonction)
385 if self._verbose_max:
387 for _ in range(n_recur):
389 texte = "\n{}{}".format(prefixe,blabla)
390 texte += "{}n_recur = {}".format(prefixe,n_recur)
391 texte += "\n{}RGB = ({},{},{})".format(prefixe,coul_r,coul_g,coul_b)
394 # 1. Au premier passage, il faut garder la référence au résultat principal
397 objet_0 = objet.result()
401 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
403 nb_sub_results = objet_0.numberOfSubs()
405 if self._verbose_max:
406 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
407 texte += "de type '{}' ".format(objet_0.shapeType())
408 texte += "et de {} sous-objets".format(nb_sub_results)
411 for n_sobj in range(nb_sub_results):
413 # 2.1. Exploration récursive de l'arborescence
415 self._couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b )
417 # 2.2. Cet objet n'a pas de sous-objets : on le colore
418 if self._verbose_max:
419 texte = "{}Couleur affectée à l'objet '{}' ".format(prefixe,objet_0.name())
421 objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
423 #print ("sortie de {}".format(nom_fonction))
427 #=========================== Fin de la méthode ==================================
429 #=========================== Début de la méthode =================================
431 def _isole_solide ( self, solide ):
432 """Isole le solide de son arboresence
435 :solide: le solide à traiter
438 :objet: le solide isolé
439 :recover: la fonction de récupération
442 nom_fonction = __name__ + "/_isole_solide"
443 blabla = "\nDans {} :\n".format(nom_fonction)
444 if self._verbose_max:
446 texte += "Pour le solide '{}' ".format(solide.name())
447 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
450 if ( solide.name() != self.objet_principal.name() ):
452 if self._verbose_max:
453 print (". Extraction du solide")
455 # 1. Extraction du solide
456 remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
457 remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
459 self.nom_solide_aux = "{}_S".format(solide.name())
460 remove_subshapes.result().setName(self.nom_solide_aux)
462 self.fonction_0 = remove_subshapes
464 # 2. Récupération de l'objet principal
465 recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
466 recover.result().setName(self.objet_principal.name())
468 objet = remove_subshapes.result()
472 if self._verbose_max:
473 print (". Mise en place du solide")
476 self.nom_solide_aux = self.objet_principal.name()
477 self.fonction_0 = None
480 if self._verbose_max:
481 texte = "objet final : '{}'\n".format(objet.name())
482 texte += "fonction_0 : {}".format(self.fonction_0)
483 texte += "recover : {}".format(recover)
486 return objet, recover
488 #=========================== Fin de la méthode ==================================
490 #=========================== Début de la méthode =================================
492 def _faces_du_solide ( self, geompy, solide ):
493 """Détermine les faces d'un solide
496 :geompy: environnement de GEOM
497 :solide: le solide à traiter
500 :l_faces: liste des faces du solide
503 nom_fonction = __name__ + "/_faces_du_solide"
504 blabla = "\nDans {} :\n".format(nom_fonction)
505 if self._verbose_max:
512 while ( not erreur ):
514 if self._verbose_max:
515 print (".. Traitement du solide '{}'".format(self.nom_solide))
516 longueur, aire, volume = geompy.BasicProperties(solide)
517 texte = "{}".format(geompy.WhatIs(solide))
518 texte += ". longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume)
521 # Liste des faces qui composent le solide
522 l_faces = geompy.ExtractShapes(solide, geompy.ShapeType["FACE"], True)
523 #if self._verbose_max:
524 #print ("Liste des {} faces qui composent le solide :".format(len(l_faces)))
525 #for iaux, face in enumerate(l_faces):
526 #print ("Face n° {} :\n {}".format(iaux,geompy.WhatIs(face)))
530 return erreur, message, l_faces
532 #=========================== Fin de la méthode ==================================
534 #=========================== Début de la méthode =================================
536 def _calcul_caract_faces ( self, geompy, l_faces ):
537 """Calcule les caractéristiques géométriques des faces
540 :geompy: environnement de GEOM
541 :l_faces: liste des faces du solide
544 :tb_caract: tableau des caractéristiques géométriques des faces
547 nom_fonction = __name__ + "/_calcul_caract_faces"
548 blabla = "\nDans {} :\n".format(nom_fonction)
550 nb_faces = len(l_faces)
551 if self._verbose_max:
552 print (blabla+"Nombre de faces : {}.".format(nb_faces))
554 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
555 for iaux, face in enumerate(l_faces):
556 _, aire, _ = geompy.BasicProperties(face)
557 #longueur, aire, volume = geompy.BasicProperties(face)
558 if self._verbose_max:
559 texte = "\t. Face numéro {}".format(iaux)
560 #texte += "\n\t. longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume)
563 tb_caract [iaux][0] = face
564 tb_caract [iaux][1] = aire
565 tb_caract [iaux][2] = geompy.KindOfShape(face)
566 if self._verbose_max:
567 print ("\t. tb_caract : {} {}".format(aire,tb_caract[iaux][2]))
571 #=========================== Fin de la méthode ==================================
573 #=========================== Début de la méthode =================================
575 def _tri_faces ( self, tb_caract ):
576 """Trie les faces en fonction de leurs surfaces
579 :tb_caract: tableau des caractéristiques géométriques des faces
582 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
588 nom_fonction = __name__ + "/_tri_faces"
589 blabla = "\nDans {} :\n".format(nom_fonction)
591 # Tri du tableau en fonction des surfaces
592 if self._verbose_max:
593 print (blabla+"tb_caract brut : {}".format(tb_caract))
594 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
595 if self._verbose_max:
596 print ("tb_caract trié : {}".format(tb_caract_1))
598 if self._verbose_max:
599 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
600 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
601 if self._verbose_max:
602 texte += "\n\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
605 # La surface suivante doit être différente, sinon ce n'est pas un solide mince
606 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
607 if ( ecart < self._epsilon ):
608 message = "\nSolide '{}'\n".format(self.nom_solide)
609 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
610 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
611 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
612 if self._verbose_max:
613 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
614 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
615 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
617 self.d_statut_so[self.nom_solide] = -1
618 self.faces_pb_nb += 1
619 self.faces_pb_msg += message
621 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
623 #=========================== Fin de la méthode ==================================
625 #=========================== Début de la méthode =================================
627 def _calcul_caract_aretes_face ( self, geompy, caract_face ):
628 """Détermine les caractéristiques des arêtes d'une face
631 :geompy: environnement de GEOM
632 :caract_face: les caractéristiques de la face
635 :caract_arete_face: les caractéristiques des arêtes de la face
638 nom_fonction = __name__ + "/_calcul_caract_aretes_face"
639 blabla = "\nDans {} :\n".format(nom_fonction)
641 if self._verbose_max:
643 texte += "face : {}\n".format(caract_face)
646 # Détermination des arêtes pour chaque face
647 face = caract_face[0]
648 l_aretes = geompy.ExtractShapes(face, geompy.ShapeType["EDGE"], True)
649 caract_arete_face = list()
650 for arete in l_aretes:
651 caract_arete_face.append(geompy.KindOfShape(arete))
653 if self._verbose_max:
654 print ("Aretes de la face : {}".format(caract_arete_face))
656 return caract_arete_face
658 #=========================== Fin de la méthode ==================================
660 #=========================== Début de la méthode =================================
662 def _verif_epaisseur ( self, epaisseur ):
663 """Contrôle de la validité de l'épaisseur
666 :epaisseur: épaisseur du solide
669 nom_fonction = __name__ + "/_verif_epaisseur"
670 blabla = "\nDans {} :\n".format(nom_fonction)
672 if self._verbose_max:
674 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
675 texte += ". EP_MIN : {}".format(EP_MIN)
678 if ( epaisseur <= EP_MIN ):
679 message = "\nSolide '{}'\n".format(self.nom_solide)
680 message += ". Epaisseur : {}\n".format(epaisseur)
681 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
682 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
684 self.d_statut_so[self.nom_solide] = 2
685 self.faces_pb_nb += 1
686 self.faces_pb_msg += message
693 #=========================== Fin de la méthode ==================================
695 #=========================== Début de la méthode =================================
697 def _cree_face_mediane ( self, solide, geompy, caract_face_1, caract_face_2 ):
698 """Crée la face médiane entre deux autres
701 :solide: solide SHAPER à traiter
702 :geompy: environnement de GEOM
703 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
706 :face: la face médiane créée
709 nom_fonction = __name__ + "/_cree_face_mediane"
710 blabla = "\nDans {} :\n".format(nom_fonction)
712 if self._verbose_max:
714 texte += "face_1 : {}\n".format(caract_face_1)
715 texte += "face_2 : {}".format(caract_face_2)
721 # 1. Forme de la face
722 forme = caract_face_1[2][0]
723 if self._verbose_max:
724 print ("forme = {}".format(forme) )
726 # 2. Traitement selon la forme de la face
728 if forme in ( geompy.kind.DISK_CIRCLE, geompy.kind.DISK_ELLIPSE, geompy.kind.POLYGON, geompy.kind.PLANE, geompy.kind.PLANAR):
729 erreur, face = self._cree_face_mediane_plane ( geompy, solide, caract_face_1, caract_face_2 )
731 # 2.2. Face cylindrique
732 elif forme == geompy.kind.CYLINDER2D:
733 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2 )
735 # 2.3. Face sphérique
736 elif forme == geompy.kind.SPHERE2D:
737 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2 )
740 elif forme == geompy.kind.TORUS2D:
741 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2 )
744 elif forme == geompy.kind.CONE2D:
745 erreur, face = self._cree_face_mediane_cone ( geompy, caract_face_1, caract_face_2 )
747 # 2.N. Face de forme inconnue
749 message = "\nSolide '{}'\n".format(self.nom_solide)
750 message += "sa face la plus grande est de forme : {}\n".format(forme)
751 message += "==> Impossible de créer la face médiane.\n"
753 self.d_statut_so[self.nom_solide] = -2
754 self.faces_pb_nb += 1
755 self.faces_pb_msg += message
757 # 3. Gestion de la face produite
760 self._cree_face_mediane_0 ( face )
764 #=========================== Fin de la méthode ==================================
766 #=========================== Début de la méthode =================================
768 def _cree_face_mediane_0 ( self, face ):
769 """Gestion de la face médiane créée entre deux autres
772 :face: la face médiane créée
775 nom_fonction = __name__ + "/_cree_face_mediane_0"
776 blabla = "\nDans {} :\n".format(nom_fonction)
778 if self._verbose_max:
783 nom_face = self.nom_solide+"_M"
784 #if ( self.nom_solide_aux != self.objet_principal.name() ):
786 face.setName(nom_face)
787 face.result().setName(nom_face)
789 # 2. Mémorisation de la face et de la fonction initiale
790 self.l_faces_m.append((face, self.fonction_0))
792 # 3. Couleur verte pour la face
793 self._couleur_objet (face, coul_r=0, coul_g=170, coul_b=0)
795 # 4. Changement de statut pour le solide
796 self.d_statut_so[self.nom_solide] = 1
800 #=========================== Fin de la méthode ==================================
802 #=========================== Début de la méthode =================================
804 def _cree_face_mediane_plane ( self, geompy, solide, caract_face_1, caract_face_2 ):
805 """Crée la face médiane entre deux autres - cas des surfaces planes
808 :geompy: environnement de GEOM
809 :solide: l'objet solide à traiter
810 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
813 :face: la face médiane
816 nom_fonction = __name__ + "/_cree_face_mediane_plane"
817 blabla = "\nDans {} :\n".format(nom_fonction)
818 if self._verbose_max:
821 # Caractéristiques des surfaces
822 coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2 = self._cree_face_mediane_plane_0 ( geompy, solide, caract_face_1, caract_face_2 )
824 # Contrôle de la validité de l'épaisseur
825 erreur = self._verif_epaisseur ( d_face_1_2 )
827 # Création de la face
829 face = self._cree_face_mediane_plane_1 ( solide, coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2 )
835 #=========================== Fin de la méthode ==================================
837 #=========================== Début de la méthode =================================
839 def _cree_face_mediane_plane_0 ( self, geompy, solide, caract_face_1, caract_face_2 ):
840 """Crée la face médiane entre deux autres - cas des surfaces planes
842 Décodage des caractéristiques
845 :geompy: environnement de GEOM
846 :solide: l'objet solide à traiter
847 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
850 :coo_x, coo_y, coo_z: coordonnées du centre de la base
851 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
852 :taille: estimation de la taille de la future face
853 :d_face_1_2: la distance entre les deux faces
856 nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
857 blabla = "\nDans {} :\n".format(nom_fonction)
859 if self._verbose_max:
861 texte += "face_1 : {}\n".format(caract_face_1)
862 texte += "face_2 : {}".format(caract_face_2)
865 # 1. Caractéristiques de la base
866 # Coordonnées du centre de la base
867 coo_x = caract_face_1[2][1]
868 coo_y = caract_face_1[2][2]
869 coo_z = caract_face_1[2][3]
870 # Coordonnées du vecteur normal
871 vnor_x = caract_face_1[2][4]
872 vnor_y = caract_face_1[2][5]
873 vnor_z = caract_face_1[2][6]
874 # taille : la diagonale de la boîte englobante permet d'être certain de tout prendre
875 l_diag = self._calcul_boite_englobante ( solide )
877 if self._verbose_max:
878 print ("Taille englobante : {}".format(taille))
880 # 2. Distance entre les deux faces
881 face_1 = caract_face_1[0]
882 face_2 = caract_face_2[0]
883 d_face_1_2 = geompy.MinDistance(face_1, face_2)
884 if self._verbose_max:
885 print ("Distance entre les deux faces = {}".format(d_face_1_2))
887 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
889 #=========================== Fin de la méthode ==================================
891 #=========================== Début de la méthode =================================
893 def _cree_face_mediane_plane_1 ( self, solide, coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2 ):
894 """Crée la face médiane entre deux autres - cas des surfaces planes
896 Création des objets temporaires et de la face médiane
899 :solide: l'objet solide à traiter
900 :coo_x, coo_y, coo_z: coordonnées du centre de la base
901 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
902 :taille: estimation de la taille de la future face
903 :d_face_1_2: la distance entre les deux faces
906 :face: la face médiane
909 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
910 blabla = "\nDans {} :\n".format(nom_fonction)
911 if self._verbose_max:
913 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
914 texte += "Normale : ({}, {}, {})\n".format(vnor_x, vnor_y, vnor_z)
915 texte += "Taille : {}\n".format(taille)
916 texte += "Distance entre les deux faces : {}".format(d_face_1_2)
919 # Création de paramètres
920 nom_par_1 = "{}_taille".format(self.nom_solide)
921 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(taille))
923 # Création du point central
924 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
925 nom_centre = "{}_centre".format(self.nom_solide)
926 centre.result().setName(nom_centre)
928 # Création du vecteur normal
929 v_norm = model.addAxis(self.part_doc, vnor_x, vnor_y, vnor_z)
930 nom_normal = "{}_normale".format(self.nom_solide)
931 v_norm.result().setName(nom_normal)
933 # Création du plan perpendiculaire au vecteur normal
934 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_normal), model.selection("VERTEX", nom_centre), True)
935 nom_plan = "{}_plan".format(self.nom_solide)
936 plan.result().setName(nom_plan)
938 # Création d'un sketch
939 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
941 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
942 SketchPoint_1 = SketchProjection_1.createdFeature()
944 ### Create SketchLine
945 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
947 ### Create SketchLine
948 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
950 ### Create SketchLine
951 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
953 ### Create SketchLine
954 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
955 sketch.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
956 sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
957 sketch.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
958 sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
960 ### Create SketchLine
961 SketchLine_5 = sketch.addLine(-taille/2., taille/2., taille/2., -taille/2.)
962 SketchLine_5.setAuxiliary(True)
964 ### Create SketchLine
965 SketchLine_6 = sketch.addLine(taille/2., taille/2., -taille/2., -taille/2.)
966 SketchLine_6.setAuxiliary(True)
967 sketch.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint())
968 sketch.setCoincident(SketchLine_2.startPoint(), SketchLine_6.startPoint())
969 sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_5.endPoint())
970 sketch.setCoincident(SketchLine_4.startPoint(), SketchLine_6.endPoint())
971 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_5.result())
972 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_6.result())
973 sketch.setHorizontal(SketchLine_1.result())
974 sketch.setVertical(SketchLine_2.result())
975 sketch.setHorizontal(SketchLine_3.result())
976 sketch.setVertical(SketchLine_4.result())
977 sketch.setLength(SketchLine_3.result(), nom_par_1)
978 sketch.setEqual(SketchLine_3.result(), SketchLine_4.result())
981 nom_sketch = "{}_esquisse".format(self.nom_solide)
982 sketch.setName(nom_sketch)
983 sketch.result().setName(nom_sketch)
985 ### Create LinearCopy
986 LinearCopy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
987 LinearCopy_1.result().subResult(0).setName("{}_0".format(self.nom_solide_aux))
990 Recover_1 = model.addRecover(self.part_doc, LinearCopy_1, [solide])
991 Recover_1.result().setName("{}_1".format(self.nom_solide_aux))
993 # Création d'une face ; on la translate d'une demi-épaisseur.
994 for iaux in range(2):
996 distance = -0.5*d_face_1_2*float(2*iaux-1)
997 nom_solide = "{}_{}".format(self.nom_solide_aux,iaux)
998 face = self._cree_face_mediane_plane_2 ( nom_sketch, nom_normal, nom_solide, distance, iaux )
1001 # Si on traite un objet solide unique, on le récupère
1002 if ( self.nom_solide_aux == self.objet_principal.name() ):
1003 if self._verbose_max:
1004 print ("On traite un objet solide unique ==> on le récupère.")
1005 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1006 Recover_2.result().setName("{}_S".format(self.nom_solide_aux))
1007 nb_inter = face.result().numberOfSubs()
1008 if self._verbose_max:
1009 print ("Nombre d'intersections : {}".format(nb_inter))
1010 # Une seule intersection : c'est la bonne
1011 # Sinon, c'est que le solide est trop mince. On fusionnerait les faces.
1013 face = self._cree_face_mediane_plane_3 ( face )
1015 # Si l'intersection est vide, on la translate dans l'autre sens
1017 if self._verbose_max:
1018 print ("L'intersection est vide.")
1023 #=========================== Fin de la méthode ==================================
1025 #=========================== Début de la méthode =================================
1027 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, distance, icpt=0 ):
1028 """Crée la face médiane entre deux autres - cas des surfaces planes
1030 Intersection de la face avec le solide
1033 :nom_sketch: nom du sketch
1034 :nom_normal: nom du vecteur normal
1035 :nom_solide: nom du solide à intersecter
1036 :distance: la distance de translation
1037 :icpt: numéro de la tentative
1040 :face: la face médiane
1043 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1044 blabla = "\nDans {} :\n".format(nom_fonction)
1045 if self._verbose_max:
1047 texte += "nom_sketch : {}\n".format(nom_sketch)
1048 texte += "nom_normal : {}\n".format(nom_normal)
1049 texte += "nom_solide : {}\n".format(nom_solide)
1050 texte += "distance : {}".format(distance)
1053 # Création d'une face
1054 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1055 nom_face_1 = "{}_face_1_{}".format(self.nom_solide_aux,icpt)
1056 Face_1.result().setName(nom_face_1)
1059 Translation_1 = model.addTranslation(self.part_doc, [model.selection("FACE", nom_face_1)], axis = model.selection("EDGE", nom_normal), distance = distance, keepSubResults = True)
1060 nom_trans = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1061 Translation_1.setName(nom_trans)
1062 Translation_1.result().setName(nom_trans)
1063 Translation_1.result().setColor(85, 0, 255)
1065 # Intersection de cette face avec le solide initial
1066 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_trans)], keepSubResults = True)
1070 #=========================== Fin de la méthode ==================================
1072 #=========================== Début de la méthode =================================
1074 def _cree_face_mediane_plane_3 ( self, face ):
1075 """Crée la face médiane entre deux autres - cas des surfaces planes
1077 Fusion des 2 intersections
1080 :face: la face médiane composée de plusieurs intersections
1083 :face_m: la face médiane
1086 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1087 blabla = "\nDans {} :\n".format(nom_fonction)
1088 if self._verbose_max:
1092 # Nommage des sous-objets
1094 for iaux in range(face.result().numberOfSubs()):
1095 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1096 face.result().subResult(iaux).setName(nom)
1097 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1100 if self._verbose_max:
1101 print ("Fusion de {} faces.".format(len(l_fuse)))
1102 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1106 #=========================== Fin de la méthode ==================================
1108 #=========================== Début de la méthode =================================
1110 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2 ):
1111 """Crée la face médiane entre deux autres - cas des cylindres
1114 :solide: solide SHAPER à traiter
1115 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1118 :face: la face médiane
1121 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1122 blabla = "\nDans {} :\n".format(nom_fonction)
1125 if self._verbose_max:
1127 texte += "face_1 : {}\n".format(caract_face_1)
1128 texte += "face_2 : {}".format(caract_face_2)
1131 # Caractéristiques des cylindres
1132 coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur = self._cree_face_mediane_cylindre_0 ( solide, caract_face_1, caract_face_2 )
1134 # Contrôle de la validité de l'épaisseur
1135 erreur = self._verif_epaisseur ( epaisseur )
1137 # Création de la face
1139 face = self._cree_face_mediane_cylindre_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur )
1141 self._couleur_objet (solide, coul_r=0, coul_g=0, coul_b=255)
1146 #=========================== Fin de la méthode ==================================
1148 #=========================== Début de la méthode =================================
1150 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2 ):
1151 """Crée la face médiane entre deux autres - cas des cylindres
1153 Décodage des caractéristiques
1156 :solide: l'objet solide à traiter
1157 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1160 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1161 :axe_x, axe_y, axe_z: coordonnées de l'axe
1162 :rayon: rayon moyen entre les deux faces
1163 :hauteur: hauteur du cylindre
1164 :epaisseur: épaisseur de l'interface entre les deux faces
1167 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1168 blabla = "\nDans {} :\n".format(nom_fonction)
1170 if self._verbose_max:
1172 texte += "face_1 : {}\n".format(caract_face_1)
1173 texte += "face_2 : {}".format(caract_face_2)
1176 # Coordonnées du centre de la base
1177 coo_x = caract_face_1[2][1]
1178 coo_y = caract_face_1[2][2]
1179 coo_z = caract_face_1[2][3]
1180 # Coordonnées de l'axe
1181 axe_x = caract_face_1[2][4]
1182 axe_y = caract_face_1[2][5]
1183 axe_z = caract_face_1[2][6]
1185 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1186 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
1187 l_diag = self._calcul_boite_englobante ( solide )
1188 hauteur = 10.*l_diag
1189 if self._verbose_max:
1190 print ("Hauteur englobante : {}".format(hauteur))
1192 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1194 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1196 #=========================== Fin de la méthode ==================================
1198 #=========================== Début de la méthode =================================
1200 def _cree_face_mediane_cylindre_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur ):
1201 """Crée la face médiane entre deux autres - cas des cylindres
1203 Création des objets temporaires et de la face externe du cylindre support
1206 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1207 :axe_x, axe_y, axe_z: coordonnées de l'axe
1208 :rayon: rayon moyen entre les deux faces
1209 :hauteur: hauteur du cylindre
1212 :face: la face médiane
1214 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1215 blabla = "\nDans {} :\n".format(nom_fonction)
1217 # Les caractéristiques du cylindre à créer
1218 if self._verbose_max:
1220 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1221 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1222 texte += "Rayon : {}\n".format(rayon)
1223 texte += "Hauteur : {}".format(hauteur)
1226 # Création du point central
1227 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1228 nom_centre = "{}_centre".format(self.nom_solide)
1229 centre.result().setName(nom_centre)
1232 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1233 nom_axe = "{}_axe".format(self.nom_solide)
1234 axe.result().setName(nom_axe)
1236 # Création du plan perpendiculaire à l'axe
1237 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), True)
1238 nom_plan = "{}_plan".format(self.nom_solide)
1239 plan.result().setName(nom_plan)
1241 # Création d'un sketch
1242 nom_par_1 = "{}_R".format(self.nom_solide)
1243 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1244 nom_par_2 = "{}_H".format(self.nom_solide)
1245 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(hauteur))
1247 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1249 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1250 SketchPoint_1 = SketchProjection_1.createdFeature()
1252 SketchCircle_1 = sketch.addCircle(0., 0., rayon)
1253 sketch.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
1254 sketch.setRadius(SketchCircle_1.results()[1], nom_par_1)
1256 nom_sketch = "{}_esquisse".format(self.nom_solide)
1257 sketch.setName(nom_sketch)
1258 sketch.result().setName(nom_sketch)
1260 # Création du cylindre complet
1261 cylindre = model.addExtrusion(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))], model.selection(), nom_par_2, nom_par_2, "Edges")
1262 nom_cylindre = "{}_cylindre".format(self.nom_solide)
1263 cylindre.setName(nom_cylindre)
1264 cylindre.result().setName(nom_cylindre)
1265 cylindre.result().setColor(85, 0, 255)
1267 # Intersection de la face cylindrique avec le solide initial
1268 face = self._creation_face_inter ( nom_cylindre )
1272 #=========================== Fin de la méthode ==================================
1274 #=========================== Début de la méthode =================================
1276 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2 ):
1277 """Crée la face médiane entre deux autres - cas des sphères
1280 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1283 :face: la face médiane
1286 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1287 blabla = "\nDans {} :\n".format(nom_fonction)
1290 if self._verbose_max:
1292 texte += "face_1 : {}\n".format(caract_face_1)
1293 texte += "face_2 : {}".format(caract_face_2)
1296 # Caractéristiques des sphères
1297 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2 )
1299 # Contrôle de la validité de l'épaisseur
1300 erreur = self._verif_epaisseur ( epaisseur )
1302 # Création de la face
1304 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1310 #=========================== Fin de la méthode ==================================
1312 #=========================== Début de la méthode =================================
1314 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2 ):
1315 """Crée la face médiane entre deux autres - cas des sphères
1317 Décodage des caractéristiques
1320 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1323 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1324 :rayon: rayon moyen entre les deux faces
1325 :epaisseur: épaisseur de l'interface entre les deux faces
1328 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1329 blabla = "\nDans {} :\n".format(nom_fonction)
1332 if self._verbose_max:
1334 texte += "face_1 : {}\n".format(caract_face_1)
1335 texte += "face_2 : {}".format(caract_face_2)
1338 # Coordonnées du centre de la sphère
1339 coo_x = caract_face_1[2][1]
1340 coo_y = caract_face_1[2][2]
1341 coo_z = caract_face_1[2][3]
1343 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1345 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1347 return coo_x, coo_y, coo_z, rayon, epaisseur
1349 #=========================== Fin de la méthode ==================================
1351 #=========================== Début de la méthode =================================
1353 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1354 """Crée la face médiane entre deux autres - cas des sphères
1356 Création des objets temporaires et de la face externe de la sphère support
1359 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1360 :rayon: rayon moyen entre les deux faces
1363 :face: la face externe de la sphère support
1366 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1367 blabla = "\nDans {} :\n".format(nom_fonction)
1369 # Les caractéristiques de la sphère à créer
1370 if self._verbose_max:
1372 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1373 texte += "Rayon : {}".format(rayon)
1376 # Création du point central
1377 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1378 nom_centre = "{}_centre".format(self.nom_solide)
1379 centre.result().setName(nom_centre)
1381 # Création d'un plan passant par ce centre et cet axe
1382 plan = model.addPlane(self.part_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", nom_centre), False)
1383 nom_plan = "{}_plan".format(self.nom_solide)
1384 plan.result().setName(nom_plan)
1386 # Création d'un sketch
1387 nom_par_1 = "{}_R".format(self.nom_solide)
1388 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1390 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1392 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1393 SketchPoint_1 = SketchProjection_1.createdFeature()
1395 ### Create SketchArc
1396 SketchArc_1 = sketch.addArc(coo_x, coo_y, coo_x-rayon, coo_y, coo_x+rayon, coo_y, False)
1397 sketch.setRadius(SketchArc_1.results()[1], nom_par_1)
1398 sketch.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
1400 ### Create SketchLine
1401 SketchLine_1 = sketch.addLine(coo_x-rayon, coo_y, coo_x+rayon, coo_y)
1402 nom_ligne = "{}_ligne".format(self.nom_solide)
1403 SketchLine_1.setName(nom_ligne)
1404 SketchLine_1.result().setName(nom_ligne)
1405 SketchLine_1.setAuxiliary(True)
1406 sketch.setHorizontal(SketchLine_1.result())
1407 sketch.setCoincident(SketchArc_1.startPoint(), SketchLine_1.startPoint())
1408 sketch.setCoincident(SketchArc_1.endPoint(), SketchLine_1.endPoint())
1409 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result())
1412 nom_sketch = "{}_esquisse".format(self.nom_solide)
1413 sketch.setName(nom_sketch)
1414 sketch.result().setName(nom_sketch)
1416 # Création de la sphère complète
1417 sphere = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", "{}/{}".format(nom_sketch,nom_ligne)), 360, 0, "Edges")
1418 nom_sphere = "{}_sphere".format(self.nom_solide)
1419 sphere.setName(nom_sphere)
1420 sphere.result().setName(nom_sphere)
1421 sphere.result().setColor(85, 0, 255)
1423 # Intersection de la face sphérique avec le solide initial
1424 face = self._creation_face_inter ( nom_sphere )
1428 #=========================== Fin de la méthode ==================================
1430 #=========================== Début de la méthode =================================
1432 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2 ):
1433 """Crée la face médiane entre deux autres - cas des tores
1436 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1439 :face: la face médiane
1442 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1443 blabla = "\nDans {} :\n".format(nom_fonction)
1446 if self._verbose_max:
1448 texte += "face_1 : {}\n".format(caract_face_1)
1449 texte += "face_2 : {}".format(caract_face_2)
1452 # Caractéristiques des tores
1453 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 )
1455 # Contrôle de la validité de l'épaisseur (bidon)
1456 erreur = self._verif_epaisseur ( EP_MIN*10. )
1458 # Création de la face
1460 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1466 #=========================== Fin de la méthode ==================================
1468 #=========================== Début de la méthode =================================
1470 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2 ):
1471 """Crée la face médiane entre deux autres - cas des tores
1473 Décodage des caractéristiques
1476 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1479 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1480 :axe_x, axe_y, axe_z: coordonnées de l'axe
1481 :rayon_1 : rayon principal
1482 :rayon_2 : rayon secondaire
1485 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1486 blabla = "\nDans {} :\n".format(nom_fonction)
1489 if self._verbose_max:
1491 texte += "face_1 : {}\n".format(caract_face_1)
1492 texte += "face_2 : {}".format(caract_face_2)
1495 # Coordonnées du centre du tore
1496 coo_x = caract_face_1[2][1]
1497 coo_y = caract_face_1[2][2]
1498 coo_z = caract_face_1[2][3]
1499 # Coordonnées de l'axe
1500 axe_x = caract_face_1[2][4]
1501 axe_y = caract_face_1[2][5]
1502 axe_z = caract_face_1[2][6]
1504 rayon_1 = caract_face_2[2][7]
1505 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1507 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1509 #=========================== Fin de la méthode ==================================
1511 #=========================== Début de la méthode =================================
1513 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1514 """Crée la face médiane entre deux autres - cas des tores
1516 Création des objets temporaires et de la face externe du tore support
1519 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1520 :axe_x, axe_y, axe_z: coordonnées de l'axe
1521 :rayon_1 : rayon principal
1522 :rayon_2 : rayon secondaire
1525 :face: la face externe du tore support
1528 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1529 blabla = "\nDans {} :\n".format(nom_fonction)
1532 if self._verbose_max:
1534 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1535 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1536 texte += "Rayon principal : {}\n".format(rayon_1)
1537 texte += "Rayon secondaire : {}".format(rayon_2)
1540 # Création du point central
1541 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1542 nom_centre = "{}_centre".format(self.nom_solide)
1543 centre.result().setName(nom_centre)
1546 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1547 nom_axe = "{}_axe".format(self.nom_solide)
1548 axe.result().setName(nom_axe)
1550 # Création d'un plan passant par ce centre et cet axe
1551 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
1552 nom_plan = "{}_plan".format(self.nom_solide)
1553 plan.result().setName(nom_plan)
1555 # Création d'un sketch
1556 nom_par_1 = "{}_R_1".format(self.nom_solide)
1557 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1558 nom_par_2 = "{}_R_2".format(self.nom_solide)
1559 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1561 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1563 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1564 SketchPoint_1 = SketchProjection_1.createdFeature()
1566 SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1567 SketchLine_1 = SketchProjection_2.createdFeature()
1569 SketchPoint_2 = sketch.addPoint(rayon_1, 0.)
1570 sketch.setDistance(SketchPoint_1.result(), SketchPoint_2.coordinates(), nom_par_1, True)
1572 SketchLine_2 = sketch.addLine(0., 0., rayon_1, 0.)
1573 SketchLine_2.setAuxiliary(True)
1574 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1575 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_2.endPoint())
1576 sketch.setPerpendicular(SketchLine_1.result(), SketchLine_2.result())
1578 SketchCircle_1 = sketch.addCircle(0., 0., rayon_2)
1579 sketch.setCoincident(SketchPoint_2.result(), SketchCircle_1.center())
1580 sketch.setRadius(SketchCircle_1.results()[1], nom_par_2)
1583 nom_sketch = "{}_esquisse".format(self.nom_solide)
1584 sketch.setName(nom_sketch)
1585 sketch.result().setName(nom_sketch)
1587 # Création du tore complet
1588 nom_tore = "{}_tore".format(self.nom_solide)
1589 self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_tore )
1591 # Intersection de la face torique avec le solide initial
1592 face = self._creation_face_inter ( nom_tore )
1596 #=========================== Fin de la méthode ==================================
1598 #=========================== Début de la méthode =================================
1600 def _cree_face_mediane_cone ( self, geompy, caract_face_1, caract_face_2 ):
1601 """Crée la face médiane entre deux autres - cas des cones
1604 :geompy: environnement de GEOM
1605 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1608 :face: la face médiane
1611 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1612 blabla = "\nDans {} :\n".format(nom_fonction)
1615 if self._verbose_max:
1617 texte += "face_1 : {}\n".format(caract_face_1)
1618 texte += "face_2 : {}".format(caract_face_2)
1621 # Caractéristiques des cones
1622 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 )
1624 # Contrôle de la validité de l'épaisseur (bidon)
1625 erreur = self._verif_epaisseur ( EP_MIN*10. )
1627 # Création de la face
1629 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1635 #=========================== Fin de la méthode ==================================
1637 #=========================== Début de la méthode =================================
1639 def _cree_face_mediane_cone_0 ( self, geompy, caract_face_1, caract_face_2 ):
1640 """Crée la face médiane entre deux autres - cas des cones
1642 Décodage des caractéristiques
1645 :geompy: environnement de GEOM
1646 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1649 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1650 :axe_x, axe_y, axe_z: coordonnées de l'axe
1651 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1652 :hauteur: hauteur du cone
1655 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1656 blabla = "\nDans {} :\n".format(nom_fonction)
1659 if self._verbose_max:
1661 texte += "face_1 : {}\n".format(caract_face_1)
1662 texte += "face_2 : {}".format(caract_face_2)
1665 # Coordonnées du centre de la base
1666 coo_x = caract_face_1[2][1]
1667 coo_y = caract_face_1[2][2]
1668 coo_z = caract_face_1[2][3]
1669 # Coordonnées de l'axe
1670 axe_x = caract_face_1[2][4]
1671 axe_y = caract_face_1[2][5]
1672 axe_z = caract_face_1[2][6]
1674 # Pour un cone complet, les caractéristiques fournies par GEOM sont correctes
1675 # Mais s'il est découpé, malheureusement,bug dans GEOM et caract_face_2[2][8] est toujours nul !
1676 # Alors on passe par le décodage des arêtes
1677 #rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1678 #rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1679 caract_arete_face_1 = self._calcul_caract_aretes_face ( geompy, caract_face_1 )
1680 caract_arete_face_2 = self._calcul_caract_aretes_face ( geompy, caract_face_2 )
1683 for caract_aretes_face in [caract_arete_face_1,caract_arete_face_2]:
1685 for l_aux in caract_aretes_face:
1686 if ( l_aux[0] in ( geompy.kind.CIRCLE, geompy.kind.ARC_CIRCLE ) ):
1687 #print ("R =",l_aux[7])
1696 hauteur = caract_face_1[2][9]
1698 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1700 #=========================== Fin de la méthode ==================================
1702 #=========================== Début de la méthode =================================
1704 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1705 """Crée la face médiane entre deux autres - cas des cones
1707 Création des objets temporaires et de la face externe du cone support
1710 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1711 :axe_x, axe_y, axe_z: coordonnées de l'axe
1712 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1713 :hauteur: hauteur du cone
1716 :face: la face externe du cone support
1718 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1719 blabla = "\nDans {} :\n".format(nom_fonction)
1722 if self._verbose_max:
1724 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1725 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1726 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1727 texte += "Hauteur : {}".format(hauteur)
1730 # Création du point central
1731 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1732 nom_centre = "{}_centre".format(self.nom_solide)
1733 centre.result().setName(nom_centre)
1736 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1737 nom_axe = "{}_axe".format(self.nom_solide)
1738 axe.result().setName(nom_axe)
1740 # Création d'un plan passant par ce centre et cet axe
1741 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
1742 nom_plan = "{}_plan".format(self.nom_solide)
1743 plan.result().setName(nom_plan)
1745 # Création d'un sketch
1746 nom_par_1 = "{}_R_1".format(self.nom_solide)
1747 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1748 nom_par_2 = "{}_R_2".format(self.nom_solide)
1749 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1750 nom_par_3 = "{}_H".format(self.nom_solide)
1751 model.addParameter(self.part_doc, "{}".format(nom_par_3), "{}".format(hauteur))
1753 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1755 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1756 SketchPoint_1 = SketchProjection_1.createdFeature()
1758 SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1759 SketchLine_1 = SketchProjection_2.createdFeature()
1761 SketchLine_2 = sketch.addLine(coo_x, coo_y, coo_x+rayon_1, coo_y+hauteur)
1762 SketchLine_2.setAuxiliary(True)
1763 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1764 sketch.setParallel(SketchLine_1.result(), SketchLine_2.result())
1765 sketch.setLength(SketchLine_2.result(), nom_par_3)
1767 SketchLine_3 = sketch.addLine(coo_x+rayon_1, coo_y, coo_x+rayon_1, coo_y+hauteur)
1768 sketch.setDistance(SketchLine_2.startPoint(), SketchLine_3.result(), nom_par_1, True)
1769 sketch.setDistance(SketchLine_2.endPoint(), SketchLine_3.result(), nom_par_2, True)
1770 sketch.setLength(SketchLine_3.result(), "2.5*{}".format(nom_par_3))
1772 SketchPoint_2 = sketch.addPoint(coo_x, coo_y)
1773 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_3.result())
1774 sketch.setMiddlePoint(SketchPoint_2.coordinates(), SketchLine_3.result())
1776 SketchLine_4 = sketch.addLine(coo_x, coo_y, 1.2*coo_x, 1.2*coo_y)
1777 SketchLine_4.setAuxiliary(True)
1778 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.startPoint())
1779 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_4.endPoint())
1780 sketch.setHorizontal(SketchLine_4.result())
1783 nom_sketch = "{}_esquisse".format(self.nom_solide)
1784 sketch.setName(nom_sketch)
1785 sketch.result().setName(nom_sketch)
1787 # Création du cone complet
1788 nom_cone = "{}_cone".format(self.nom_solide)
1789 self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_cone )
1791 # Intersection de la face conique avec le solide initial
1792 face = self._creation_face_inter ( nom_cone )
1796 #=========================== Fin de la méthode ==================================
1798 #=========================== Début de la méthode =================================
1800 def _calcul_boite_englobante ( self, objet ):
1801 """Crée la hauteur englobant à coup sûr l'objet
1804 :objet: l'objet à traiter
1807 :l_diag: longueur de la diagonale de la boîte englobante
1810 nom_fonction = __name__ + "/_calcul_boite_englobante"
1811 blabla = "\nDans {} :\n".format(nom_fonction)
1813 if self._verbose_max:
1817 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
1818 if self._verbose_max:
1819 texte = "Création de la boite englobante pour l'objet '{}' ".format(objet.name())
1820 texte += "de type '{}'".format(objet.shapeType())
1822 bbox = model.getBoundingBox(self.part_doc, model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
1824 bbox_nom = bbox.name()
1825 if self._verbose_max:
1826 print ("Boîte englobante : '{}' '{}'".format(bbox.name(), bbox.result().name()))
1828 if self._verbose_max:
1829 coo_min = model.getPointCoordinates(self.part_doc, \
1830 model.selection("VERTEX", "[{}_1/Back][{}_1/Left][{}_1/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)))
1831 coo_max = model.getPointCoordinates(self.part_doc, \
1832 model.selection("VERTEX", "[{}_1/Front][{}_1/Right][{}_1/Top]".format(bbox_nom,bbox_nom,bbox_nom)))
1833 texte = "\tXmin = {}, Xmax = {}\n".format(coo_min[0],coo_max[0])
1834 texte += "\tYmin = {}, Ymax = {}\n".format(coo_min[1],coo_max[1])
1835 texte += "\tZmin = {}, Zmax = {}".format(coo_min[2],coo_max[2])
1838 l_diag = model.measureDistance(self.part_doc, \
1839 model.selection("VERTEX", "[{}_1/Back][{}_1/Left][{}_1/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)), \
1840 model.selection("VERTEX", "[{}_1/Front][{}_1/Right][{}_1/Top]".format(bbox_nom,bbox_nom,bbox_nom)) )
1841 if self._verbose_max:
1842 print ("Longueur de la diagonale : {}".format(l_diag))
1846 #=========================== Fin de la méthode ==================================
1848 #=========================== Début de la méthode =================================
1850 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
1851 """Crée un volume de révolution
1854 :nom_sketch: nom du sketch à révolutionner
1855 :nom_centre: nom du point associé au centre du volume de révolution
1856 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1857 :axe_x, axe_y, axe_z: coordonnées de l'axe
1858 :rayon_1 : rayon principal
1859 :rayon_2 : rayon secondaire
1860 :nom_objet: nom de l'objet 2D créé
1863 nom_fonction = __name__ + "/_cree_revolution"
1864 blabla = "\nDans {} :\n".format(nom_fonction)
1866 if self._verbose_max:
1868 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1869 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1872 # Création d'un point décalé par rapport au point central
1873 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
1874 nom_point = "{}_point".format(self.nom_solide)
1875 point.result().setName(nom_point)
1877 # Création de l'axe de la rotation
1878 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
1879 nom_axe_r = "{}_axe_r".format(self.nom_solide)
1880 axe_r.result().setName(nom_axe_r)
1882 # Création de l'objet complet
1883 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
1884 objet.setName(nom_objet)
1885 objet.result().setName(nom_objet)
1886 objet.result().setColor(85, 0, 255)
1890 #=========================== Fin de la méthode ==================================
1892 #=========================== Début de la méthode =================================
1894 def _creation_face_inter ( self, nom_objet ):
1895 """Crée la face par intersection entre l'objet initial et une face complète
1897 . Repère la face principale de l'objet support
1898 . Réalise l'intersection avec le solide initial
1901 :nom_objet: nom de l'objet 2D créé
1904 :face: la face externe de l'objet support intersecté avec le solide initial
1907 nom_fonction = __name__ + "/_creation_face_inter"
1908 blabla = "\nDans {} :\n".format(nom_fonction)
1910 if self._verbose_max:
1913 face = model.addCommon(self.part_doc, [model.selection("SOLID", self.nom_solide_aux), model.selection("FACE", nom_objet)], keepSubResults = True)
1917 #=========================== Fin de la méthode ==================================
1919 #=========================== Début de la méthode =================================
1921 def face_mediane_solide (self, solide, geompy, objet_geom):
1922 """Calcul de la face médiane pour un solide
1925 :solide: solide SHAPER à traiter
1926 :geompy: environnement de GEOM
1927 :objet_geom: l'objet solide au format GEOM à traiter
1930 :erreur: code d'erreur
1931 :message: message d'erreur
1934 nom_fonction = __name__ + "/face_mediane_solide"
1935 blabla = "\nDans {} :\n".format(nom_fonction)
1937 if self._verbose_max:
1940 print ("Traitement du solide '{}'".format(solide.name()))
1949 # 2. Explosion du solide en faces
1951 erreur, message, l_faces = self._faces_du_solide ( geompy, objet_geom )
1955 # 3. Calcul des caractéristiques géométriques des faces
1957 tb_caract = self._calcul_caract_faces ( geompy, l_faces )
1959 # 4. Tri des faces en fonction de leurs caractéristiques géométriques
1961 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract )
1965 # 5. Création de la face médiane
1967 erreur, face = self._cree_face_mediane ( solide, geompy, caract_face_1, caract_face_2 )
1971 # 6. Exportation step
1973 if self._export_step:
1974 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
1975 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
1976 export.execute(True)
1983 if ( erreur and self._verbose_max ):
1984 print (blabla, message)
1986 return erreur, message
1988 #=========================== Fin de la méthode ==================================
1990 #=========================== Début de la méthode =================================
1992 def _traitement_objet (self, solide=None, objet_geom=None):
1993 """Traitement d'un objet
1996 :solide: solide SHAPER à traiter
1997 :objet_geom: l'objet GEOM équivalent
2000 :erreur: code d'erreur
2001 :message: message d'erreur
2004 nom_fonction = __name__ + "/_traitement_objet"
2005 blabla = "\nDans {} :\n".format(nom_fonction)
2007 if self._verbose_max:
2019 if self.affiche_aide_globale :
2022 # 3. Les imports pour salomé
2023 geompy = geomBuilder.New()
2025 # 4. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2026 # Attention à ne pas recréer le répertoire à chaque fois
2027 if self._export_step:
2029 if self._verbose_max:
2030 print ("Préparation de l'export STEP")
2032 if self.rep_step is None:
2033 if self.ficcao is None:
2034 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2036 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2037 if os.path.isdir(self.rep_step):
2038 l_aux = os.listdir(self.rep_step)
2039 for nomfic in l_aux:
2040 os.remove(os.path.join(self.rep_step,nomfic))
2042 os.mkdir(self.rep_step)
2043 if self._verbose_max:
2044 print ("Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2046 # 5. Calcul réel de la face médiane
2049 self.nom_solide = objet_geom.GetName()
2051 erreur, message = self.face_mediane_solide (solide, geompy, objet_geom)
2057 return erreur, message
2059 #=========================== Fin de la méthode ==================================
2061 #=========================== Début de la méthode =================================
2063 def surf_fic_cao (self, ficcao, nom_objet=None):
2064 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2067 :ficcao: fichier de l'objet à traiter
2068 :nom_objet: un nom à donner à l'objet à traiter
2071 :erreur: code d'erreur
2072 :message: message d'erreur
2075 nom_fonction = __name__ + "/surf_fic_cao"
2076 blabla = "\nDans {} :\n".format(nom_fonction)
2078 if self._verbose_max:
2088 # 1. Définition de la pièce
2090 self.part_doc = model.activeDocument()
2092 # 2. Import de la CAO
2094 self.ficcao = ficcao
2095 print ("Traitement du fichier {}".format(ficcao))
2097 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2101 # 3. Calcul des surfaces
2103 erreur, message = self.surf_objet_shaper ( objet )
2112 if ( erreur and self._verbose_max ):
2113 print (blabla, message)
2115 return erreur, message
2117 #=========================== Fin de la méthode ==================================
2119 #=========================== Début de la méthode =================================
2121 def surf_objet_shaper (self, objet):
2122 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2125 :objet: objet à traiter
2128 :erreur: code d'erreur
2129 :message: message d'erreur
2132 nom_fonction = __name__ + "/surf_objet_shaper"
2133 blabla = "Dans {} :\n".format(nom_fonction)
2135 if self._verbose_max:
2138 # 1. Acquisition de la liste des noms des sous-objets solides
2140 self.d_statut_so = dict()
2141 self.l_noms_so = list()
2142 self.l_faces_m = list()
2144 _ = self._nom_sous_objets (objet, True)
2145 if self._verbose_max:
2146 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2148 # 2. Les faces médianes
2150 erreur, message = self._surf_objet_shaper_0 ( objet )
2152 # 3. Gestion des faces créées
2154 self._surf_objet_shaper_1 ( )
2156 # 4. Futur message pour le résultat
2158 if ( self._export_step and not erreur ):
2159 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2161 return erreur, message
2163 #=========================== Fin de la méthode ==================================
2165 #=========================== Début de la méthode =================================
2167 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2168 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2171 :objet: objet à traiter
2172 :n_recur: niveau de récursivité
2175 :erreur: code d'erreur
2176 :message: message d'erreur
2179 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2180 blabla = "Dans {} :\n".format(nom_fonction)
2182 if self._verbose_max:
2184 for _ in range(n_recur):
2186 texte = "\n{}{}".format(prefixe,blabla)
2187 texte += "{}n_recur = {}".format(prefixe,n_recur)
2195 # 1. Au premier passage, il faut récupérer la pièce et garder la référence au résultat principal
2197 if ( n_recur == 0 ):
2198 self.part_doc = model.activeDocument()
2199 objet_0 = objet.result()
2200 self.objet_principal = objet_0
2204 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2206 nb_sub_results = objet_0.numberOfSubs()
2208 if self._verbose_max:
2209 texte = "Examen de l'objet '{}' ".format(objet_0.name())
2210 texte += "de type '{}'".format(objet_0.shapeType())
2211 texte += "\nobjet.result().numberOfSubs() : {}".format(nb_sub_results)
2214 for n_sobj in range(nb_sub_results):
2216 # 2.1. Exploration récursive de l'arborescence
2218 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2222 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2224 if ( objet_0.shapeType() == "SOLID" ):
2225 erreur, message = self.surf_solide_shaper ( objet_0 )
2232 # 3. Futur message pour le résultat
2234 if self._export_step:
2235 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2239 return erreur, message
2241 #=========================== Fin de la méthode ==================================
2243 #=========================== Début de la méthode =================================
2245 def _surf_objet_shaper_1 (self):
2246 """Gestion des surfaces médianes créées
2249 :erreur: code d'erreur
2250 :message: message d'erreur
2253 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2254 blabla = "Dans {} :\n".format(nom_fonction)
2256 if self._verbose_max:
2259 # 1. Informations sur les faces à problème
2261 if self.faces_pb_nb:
2262 if ( self.faces_pb_nb == 1 ):
2263 texte = "1 face pose"
2265 texte = "{} faces posent".format(self.faces_pb_nb)
2266 print ("\n{} problème.\n{}".format(texte,self.faces_pb_msg))
2268 # 2. Si plus d'une face a été créée
2269 if ( len(self.l_faces_m) > 1 ):
2271 # 2.1. Partition du paquet de faces
2273 if self._verbose_max:
2274 print ("Partitionnnement des faces créées.")
2277 for (face,_) in self.l_faces_m:
2278 l_objets.append(model.selection("COMPOUND", "all-in-{}".format(face.name())))
2280 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2282 Partition_1.result().setName("{}_M".format(self.objet_principal.name()))
2283 for iaux, (face,_) in enumerate(self.l_faces_m):
2284 Partition_1.result().subResult(iaux).setName("{}".format(face.name()))
2285 self._couleur_objet (Partition_1, coul_r=0, coul_g=170, coul_b=0)
2287 # 2.2. Récupération des faces individuelles
2289 if self._verbose_max:
2290 print ("Récupération des faces individuelles.")
2293 for iaux, (face,_) in enumerate(self.l_faces_m):
2294 l_objets.append(face.result())
2296 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2297 for iaux, (face,_) in enumerate(self.l_faces_m):
2298 Recover_1.results()[iaux].setName("{}".format(face.name()))
2299 Recover_1.results()[iaux].setColor(0, 170, 0)
2301 # 2.3. Mise en dossier
2303 if self._verbose_max:
2304 print ("Mise en dossier.")
2306 for (face,fonction_0) in self.l_faces_m:
2307 dossier = model.addFolder(self.part_doc, fonction_0, face)
2308 dossier.setName(face.name()[:-2])
2312 #=========================== Fin de la méthode ==================================
2314 #=========================== Début de la méthode =================================
2316 def surf_solide_shaper (self, solide):
2317 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2320 :solide: solide SHAPER à traiter
2323 :erreur: code d'erreur
2324 :message: message d'erreur
2327 nom_fonction = __name__ + "/surf_solide_shaper"
2328 blabla = "Dans {} :".format(nom_fonction)
2330 if self._verbose_max:
2338 self.nom_solide = solide.name()
2339 if self._verbose_max:
2340 print ("solide '{}'".format(self.nom_solide))
2342 # 1. Isolement du solide
2343 solide_aux, recover = self._isole_solide ( solide )
2345 # 2. Exportation dans un fichier step pour traitement dans GEOM
2347 fichier = tempfile.mkstemp(suffix=".stp")[1]
2348 if self._verbose_max:
2349 print ("fichier = {}".format(fichier))
2350 print ("solide = {}".format(solide_aux.name()))
2351 print ("de type = {}".format(solide_aux.shapeType()))
2352 export = model.exportToFile(self.part_doc, fichier, [model.selection(solide_aux.shapeType(), solide_aux.name())])
2353 export.execute(True)
2356 taille = os.path.getsize(fichier)
2358 message = "Export de SHAPER vers GEOM impossible pour le solide '{}' de type '{}'\n".format(solide_aux.name(), solide_aux.shapeType())
2359 message += "Le fichier {} est de taille {}".format(fichier,taille)
2363 # 3. Importation dans GEOM
2364 geompy = geomBuilder.New()
2365 objet_geom = geompy.ImportSTEP(fichier, False, True)
2368 # 4. Traitement de l'objet correspondant
2369 erreur, message = self._traitement_objet ( solide=solide_aux, objet_geom=objet_geom )
2371 if ( erreur and self._verbose_max ):
2372 print (blabla, message)
2374 # 5. Mise en forme de l'objet principal récupéré
2375 if ( recover is not None ):
2376 _ = self._nom_sous_objets (recover, False)
2378 # 6. Neutralisation des erreurs dues à l'épaisseur
2379 if ( erreur in (-2,-1,2) ):
2385 return erreur, message
2387 #=========================== Fin de la méthode ==================================
2389 #=========================== Début de la méthode =================================
2391 def surf_objet_geom (self, objet_geom):
2392 """Calcule la surface médiane pour un objet GEOM passé en argument
2395 :objet_geom: l'objet GEOM à traiter
2398 :erreur: code d'erreur
2399 :message: message d'erreur
2402 nom_fonction = __name__ + "/surf_objet_geom"
2403 blabla = "\nDans {} :\n".format(nom_fonction)
2405 if self._verbose_max:
2408 erreur, message = self._traitement_objet ( objet_geom=objet_geom )
2410 if ( erreur and self._verbose_max ):
2411 print (blabla, message)
2413 return erreur, message
2415 #=========================== Fin de la méthode ==================================
2417 #=========================== Début de la méthode =================================
2419 def lancement (self):
2424 :erreur: code d'erreur
2425 :message: message d'erreur
2428 nom_fonction = __name__ + "/lancement"
2429 blabla = "\nDans {} :\n".format(nom_fonction)
2431 if self._verbose_max:
2434 erreur, message = self._traitement_objet ( )
2436 if ( erreur and self._verbose_max ):
2437 print (blabla, message)
2439 return erreur, message
2441 #=========================== Fin de la méthode ==================================
2443 #========================== Fin de la classe ====================================
2445 #==================================================================================
2447 #==================================================================================
2449 if __name__ == "__main__" :
2454 L_OPTIONS.append("-vmax")
2455 #L_OPTIONS.append("-export_step")
2456 FIC_CAO = os.path.join(os.getenv("SHAPER_ROOT_DIR"), "bin", "salome", "macros", "midSurface", "midSurface.stp")
2457 #FIC_CAO = os.path.join(os.getenv("HOME"), "salome-dev", "DEV_package", "modules", "src", "SHAPER", "src", "PythonAddons", "macros", "midSurface", "Objet_1.stp")
2459 # 2. Lancement de la classe
2461 #print ("L_OPTIONS :", L_OPTIONS)
2463 SURFACE_MEDIANE = SurfaceMediane(L_OPTIONS)
2464 if SURFACE_MEDIANE.affiche_aide_globale:
2465 sys.stdout.write(SURFACE_MEDIANE.__doc__+"\n")
2468 PARTSET = model.moduleDocument()
2469 _ = model.addPart(PARTSET)
2470 ERREUR, MESSAGE_ERREUR = SURFACE_MEDIANE.surf_fic_cao(FIC_CAO)
2472 MESSAGE_ERREUR += "\n Code d'erreur : %d\n" % ERREUR
2473 sys.stderr.write(MESSAGE_ERREUR)