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.54"
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
127 :nom_objet: nom à donner à l'objet lu, éventuellement
129 :objet: l'objet importé dans SHAPER
132 nom_fonction = __name__ + "/import_cao"
133 blabla = "\nDans {} :\n".format(nom_fonction)
134 message_0 = "Fichier : {}\n".format(ficcao)
136 message = blabla + message_0
137 message += "nom_objet : {}".format(nom_objet)
145 laux = ficcao.split(".")
146 fmt_cao_0 = decode_cao (laux[-1])
148 if ( fmt_cao_0 not in ("stp", "brep", "igs", "xao") ):
149 message += "Le format de CAO est inconnu"
153 message += "Le fichier de CAO n'a pas été décodé correctement."
156 elif not os.path.isfile(ficcao):
157 message += "Le fichier de CAO est inconnu."
163 objet = model.addImport(part_doc, ficcao)
167 if nom_objet is not None:
168 objet.result().setName(nom_objet)
171 texte = "Objet : '{}'\n".format(objet.result().name())
172 texte += "De type : '{}'".format(objet.result().shapeType())
175 return erreur, message, objet
177 #========================= Fin de la fonction ===================================
179 #========================= Début de la fonction ==================================
181 def print_tab (nb_tab, message, argu=None, saut_av=False, saut_ap=False):
182 """Imprime avec des tabulations
185 :nb_tab: nombre de tabulations à appliquer
186 :message: message principal
187 :argu: argument du format
188 :saut_av: saut de ligne avant le texte
189 :saut_ap: saut de ligne après le texte
197 for _ in range(nb_tab):
201 if ( argu is not None ):
202 texte += "{}".format(argu)
208 #========================= Fin de la fonction ===================================
211 #=================================== La classe ===================================
213 class SurfaceMediane (object):
215 """Calcul des surfaces médianes de solides minces
217 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
218 une structure qui est un solide ou un assemblage de solides (compound).
219 Pour réaliser l'opération, trois façons de faire :
221 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
223 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
224 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
226 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
227 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
230 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
231 de taille identique et supérieure aux tailles des autres faces du solide. \
232 Cela fonctionne pour des surfaces planes ou de forme canonique.
233 Il crée alors une surface au milieu de ces deux grandes faces. \
234 Cette face est coloriée en vert, le solide est en vert et transparent.
236 On sait traiter les faces :
243 Si la création n'a pas eu lieu, un message est émis et les solides sont mis en couleur :
244 . Rouge : le solide n'est pas assez mince.
245 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
246 . Orange : la forme de la face n'est pas reconnue.
254 . Exportation finale dans un fichier step. Par défaut, pas d'export.
255 -export_step/-no_export_step
258 surf_fic_cao --> import_cao
259 --> surf_objet_shaper (récursif) --> _nom_sous_objets
260 --> _surf_objet_shaper_0
261 --> surf_solide_shaper --> _isole_solide
262 --> _traitement_objet --> face_mediane_solide --> _faces_du_solide
264 --> _cree_face_mediane
266 _cree_face_mediane --> _cree_face_mediane_plane
267 --> _cree_face_mediane_cylindre
268 --> _cree_face_mediane_sphere
269 --> _cree_face_mediane_tore
270 --> _cree_face_mediane_cone
271 --> _cree_face_mediane_0
280 affiche_aide_globale = 0
287 nom_solide_aux = None
293 objet_principal = None
295 # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
297 # Statut de chaque sous-objet connu par son nom :
298 # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
300 # Liste des faces médianes créées et des fonctions initiales
302 # La fonction initiale
308 #=========================== Début de la méthode =================================
310 def __init__ ( self, liste_option ):
312 """Le constructeur de la classe SurfaceMediane
314 Décodage des arguments
315 On cherche ici les arguments généraux : aide, verbeux
318 for option in liste_option :
321 if isinstance(option,str):
322 saux = option.upper()
324 if saux in ( "-H", "-HELP" ):
325 self.affiche_aide_globale = 1
328 elif saux == "-VMAX" :
330 self._verbose_max = 1
331 elif saux == "-EXPORT_STEP":
332 self._export_step = True
333 elif saux == "-NO_EXPORT_STEP":
334 self._export_step = False
336 #=========================== Fin de la méthode ==================================
338 #=========================== Début de la méthode =================================
341 """A la suppression de l'instance de classe"""
342 if self._verbose_max:
343 print ("Suppression de l'instance de la classe.")
345 #=========================== Fin de la méthode ==================================
347 #=========================== Début de la méthode =================================
349 def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
350 """Gère les noms des sous_objets solides
353 :objet: objet à traiter
354 :lecture: vrai pour lire les noms, faux pour les attribuer
355 :n_recur: niveau de récursivité
356 :rang: rang du sous-objet
359 :rang: rang du sous-objet
362 nom_fonction = __name__ + "/_nom_sous_objets"
363 blabla = "Dans {} :\n".format(nom_fonction)
365 if self._verbose_max:
367 for _ in range(n_recur):
369 texte = "\n{}{}".format(prefixe,blabla)
370 texte += "{}n_recur = {}".format(prefixe,n_recur)
371 texte += "\n{}lecture = {}".format(prefixe,lecture)
374 # 1. Au premier passage, il faut garder la référence au résultat principal
377 objet_0 = objet.result()
378 if self._verbose_max:
379 print ("d_statut_so = {}".format(self.d_statut_so))
383 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
385 nb_sub_results = objet_0.numberOfSubs()
387 if self._verbose_max:
388 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
389 texte += "de type '{}'".format(objet_0.shapeType())
390 texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
393 for n_sobj in range(nb_sub_results):
395 # 2.1. Exploration récursive de l'arborescence
397 rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
399 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
401 if ( objet_0.shapeType() == "SOLID" ):
402 # A la lecture, on enregistre le nom
405 self.l_noms_so.append(nom)
406 self.d_statut_so[nom] = 0
407 # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
409 nom = self.l_noms_so[rang]
411 etat = self.d_statut_so[nom]
412 objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
414 objet_0.setTransparency (TRANSPARENCE)
419 #=========================== Fin de la méthode ==================================
421 #=========================== Début de la méthode =================================
423 def _couleur_objet (self, objet, n_recur=0, coul_r=1, coul_g=0, coul_b=0):
424 """Appliquer une couleur à un objet et à ses sous_objets
427 :objet: objet à traiter
428 :n_recur: niveau de récursivité
429 :coul_r,coul_g,coul_b: code RGB de la couleur à appliquer
432 :rang: rang du sous-objet
435 nom_fonction = __name__ + "/_couleur_objet"
436 blabla = "Dans {} :".format(nom_fonction)
438 if self._verbose_max:
440 print_tab(n_recur, "objet : ", objet.name())
441 print_tab(n_recur, "RGB = ({},{},{})".format(coul_r,coul_g,coul_b))
443 # 1. Au premier passage, il faut garder la référence au résultat principal
446 objet_0 = objet.result()
450 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
452 nb_sub_results = objet_0.numberOfSubs()
454 if self._verbose_max:
455 print_tab(n_recur, "Examen de l'objet ",objet_0.name())
456 texte = "de type '{}' ".format(objet_0.shapeType())
457 texte += "et de {} sous-objets".format(nb_sub_results)
458 print_tab(n_recur, texte)
460 for n_sobj in range(nb_sub_results):
462 # 2.1. Exploration récursive de l'arborescence
464 self._couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b )
466 # 2.2. Cet objet n'a pas de sous-objets : on le colore
467 if self._verbose_max:
468 print_tab(n_recur, "Couleur affectée à l'objet ",objet_0.name())
469 objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
471 #print ("sortie de {}".format(nom_fonction))
475 #=========================== Fin de la méthode ==================================
477 #=========================== Début de la méthode =================================
479 def _isole_solide ( self, solide, n_recur ):
480 """Isole le solide de son arboresence
483 :solide: le solide à traiter
484 :n_recur: numéro de la récurrence
487 :objet: le solide isolé
488 :recover: la fonction de récupération
491 nom_fonction = __name__ + "/_isole_solide"
492 blabla = "\nDans {} :".format(nom_fonction)
493 if self._verbose_max:
495 texte = "Pour le solide '{}' ".format(solide.name())
496 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
497 print_tab (n_recur, texte)
499 if ( solide.name() != self.objet_principal.name() ):
501 if self._verbose_max:
502 print_tab (n_recur, ". Extraction du solide")
504 # 1. Extraction du solide
505 remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
506 remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
508 self.nom_solide_aux = "{}_S".format(solide.name())
509 remove_subshapes.result().setName(self.nom_solide_aux)
511 self.fonction_0 = remove_subshapes
513 # 2. Récupération de l'objet principal
514 recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
515 recover.result().setName(self.objet_principal.name())
517 objet = remove_subshapes.result()
521 if self._verbose_max:
522 print_tab (n_recur, ". Mise en place du solide")
525 self.nom_solide_aux = self.objet_principal.name()
526 self.fonction_0 = None
529 if self._verbose_max:
530 print_tab (n_recur, "objet final : ", objet.name())
531 print_tab (n_recur, "fonction_0 : ", self.fonction_0)
532 print_tab (n_recur, "recover : ", recover)
534 return objet, recover
536 #=========================== Fin de la méthode ==================================
538 #=========================== Début de la méthode =================================
540 def _faces_du_solide ( self, geompy, objet_geom, solide, n_recur=0 ):
541 """Détermine les faces d'un solide
544 :geompy: environnement de GEOM
545 :objet_geom: l'objet solide à traiter au format GEOM
546 :solide: solide SHAPER à traiter
547 :n_recur: niveau de récursivité
550 :l_faces_geom: liste des faces du solide au format GEOM
551 :l_faces: liste des faces du solide
554 nom_fonction = __name__ + "/_faces_du_solide"
555 blabla = "\nDans {} :\n".format(nom_fonction)
556 if self._verbose_max:
561 l_faces_geom = list()
564 while ( not erreur ):
566 if self._verbose_max:
567 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
568 longueur, aire, volume = geompy.BasicProperties(objet_geom)
569 texte = "{}".format(geompy.WhatIs(objet_geom))
570 texte += ". longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume)
573 # Liste des faces qui composent le solide
574 l_faces_geom = geompy.ExtractShapes(objet_geom, geompy.ShapeType["FACE"], True)
575 #if self._verbose_max:
576 #print ("Liste des {} faces qui composent le solide :".format(len(l_faces_geom)))
577 #for iaux, face in enumerate(l_faces_geom):
578 #print ("Face n° {} :\n {}".format(iaux,geompy.WhatIs(face)))
580 print_tab (n_recur, "Type python : ", type(solide))
581 print_tab (n_recur, "Type ", solide.shapeType())
582 #print ("Type {}".format(solide.shapeTypeStr()))
583 #print ("volume = {}".format(GeomAlgoAPI_ShapeTools.volume(solide)))
585 #exp = GeomAPI_ShapeExplorer(solide, GeomAPI_Shape.FACE)
587 #l_faces.append(exp.current().face())
592 return erreur, message, l_faces_geom, l_faces
594 #=========================== Fin de la méthode ==================================
596 #=========================== Début de la méthode =================================
598 def _calcul_caract_faces ( self, geompy, l_faces ):
599 """Calcule les caractéristiques géométriques des faces
602 :geompy: environnement de GEOM
603 :l_faces: liste des faces du solide
606 :tb_caract: tableau des caractéristiques géométriques des faces
609 nom_fonction = __name__ + "/_calcul_caract_faces"
610 blabla = "\nDans {} :\n".format(nom_fonction)
612 nb_faces = len(l_faces)
613 if self._verbose_max:
614 print (blabla+"Nombre de faces : {}.".format(nb_faces))
616 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
617 for iaux, face in enumerate(l_faces):
618 _, aire, _ = geompy.BasicProperties(face)
619 #longueur, aire, volume = geompy.BasicProperties(face)
620 if self._verbose_max:
621 texte = "\t. Face numéro {}".format(iaux)
622 #texte += "\n\t. longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume)
623 texte += ", surface : {}".format(aire)
626 tb_caract [iaux][0] = face
627 tb_caract [iaux][1] = aire
628 tb_caract [iaux][2] = geompy.KindOfShape(face)
629 if self._verbose_max:
630 print ("\t. tb_caract : {} {}".format(aire,tb_caract[iaux][2]))
634 #=========================== Fin de la méthode ==================================
636 #=========================== Début de la méthode =================================
638 def _tri_faces ( self, tb_caract ):
639 """Trie les faces en fonction de leurs surfaces
642 :tb_caract: tableau des caractéristiques géométriques des faces
645 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
651 nom_fonction = __name__ + "/_tri_faces"
652 blabla = "\nDans {} :\n".format(nom_fonction)
654 # Tri du tableau en fonction des surfaces
655 if self._verbose_max:
656 print (blabla+"tb_caract brut : {}".format(tb_caract))
657 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
658 if self._verbose_max:
659 print ("tb_caract trié : {}".format(tb_caract_1))
661 if self._verbose_max:
662 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
663 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
664 if self._verbose_max:
665 texte += "\n\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
668 # La surface suivante doit être différente, sinon ce n'est pas un solide mince
669 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
670 if ( ecart < self._epsilon ):
671 message = "\nSolide '{}'\n".format(self.nom_solide)
672 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
673 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
674 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
675 if self._verbose_max:
676 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
677 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
678 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
680 self.d_statut_so[self.nom_solide] = -1
681 self.faces_pb_nb += 1
682 self.faces_pb_msg += message
684 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
686 #=========================== Fin de la méthode ==================================
688 #=========================== Début de la méthode =================================
690 def _calcul_caract_aretes_face ( self, geompy, caract_face ):
691 """Détermine les caractéristiques des arêtes d'une face
694 :geompy: environnement de GEOM
695 :caract_face: les caractéristiques de la face
698 :caract_arete_face: les caractéristiques des arêtes de la face
701 nom_fonction = __name__ + "/_calcul_caract_aretes_face"
702 blabla = "\nDans {} :\n".format(nom_fonction)
704 if self._verbose_max:
706 texte += "face : {}\n".format(caract_face)
709 # Détermination des arêtes pour chaque face
710 face = caract_face[0]
711 l_aretes = geompy.ExtractShapes(face, geompy.ShapeType["EDGE"], True)
712 caract_arete_face = list()
713 for arete in l_aretes:
714 caract_arete_face.append(geompy.KindOfShape(arete))
716 if self._verbose_max:
717 print ("Aretes de la face : {}".format(caract_arete_face))
719 return caract_arete_face
721 #=========================== Fin de la méthode ==================================
723 #=========================== Début de la méthode =================================
725 def _verif_epaisseur ( self, epaisseur ):
726 """Contrôle de la validité de l'épaisseur
729 :epaisseur: épaisseur du solide
732 nom_fonction = __name__ + "/_verif_epaisseur"
733 blabla = "\nDans {} :\n".format(nom_fonction)
735 if self._verbose_max:
737 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
738 texte += ". EP_MIN : {}".format(EP_MIN)
741 if ( epaisseur <= EP_MIN ):
742 message = "\nSolide '{}'\n".format(self.nom_solide)
743 message += ". Epaisseur : {}\n".format(epaisseur)
744 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
745 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
747 self.d_statut_so[self.nom_solide] = 2
748 self.faces_pb_nb += 1
749 self.faces_pb_msg += message
756 #=========================== Fin de la méthode ==================================
758 #=========================== Début de la méthode =================================
760 def _cree_face_mediane ( self, solide, geompy, caract_face_1, caract_face_2, n_recur ):
761 """Crée la face médiane entre deux autres
764 :solide: solide SHAPER à traiter
765 :geompy: environnement de GEOM
766 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
767 :n_recur: niveau de récursivité
770 :face: la face médiane créée
773 nom_fonction = __name__ + "/_cree_face_mediane"
774 blabla = "\nDans {} :\n".format(nom_fonction)
776 if self._verbose_max:
778 print_tab (n_recur, "face_1 : " ,caract_face_1)
779 print_tab (n_recur, "face_2 : " ,caract_face_2)
784 # 1. Forme de la face
785 forme = caract_face_1[2][0]
786 if self._verbose_max:
787 print ("forme = {}".format(forme) )
789 # 2. Traitement selon la forme de la face
791 if forme in ( geompy.kind.DISK_CIRCLE, geompy.kind.DISK_ELLIPSE, geompy.kind.POLYGON, geompy.kind.PLANE, geompy.kind.PLANAR ):
792 erreur, face = self._cree_face_mediane_plane ( geompy, solide, caract_face_1, caract_face_2, n_recur )
794 # 2.2. Face cylindrique
795 elif forme == geompy.kind.CYLINDER2D:
796 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
798 # 2.3. Face sphérique
799 elif forme == geompy.kind.SPHERE2D:
800 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
803 elif forme == geompy.kind.TORUS2D:
804 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
807 elif forme == geompy.kind.CONE2D:
808 erreur, face = self._cree_face_mediane_cone ( geompy, caract_face_1, caract_face_2, n_recur )
810 # 2.N. Face de forme inconnue
812 message = "\nSolide '{}'\n".format(self.nom_solide)
813 message += "sa face la plus grande est de forme : {}\n".format(forme)
814 message += "==> Impossible de créer la face médiane.\n"
816 self.d_statut_so[self.nom_solide] = -2
817 self.faces_pb_nb += 1
818 self.faces_pb_msg += message
820 # 3. Gestion de la face produite
823 self._cree_face_mediane_0 ( face, n_recur )
827 #=========================== Fin de la méthode ==================================
829 #=========================== Début de la méthode =================================
831 def _cree_face_mediane_0 ( self, face, n_recur ):
832 """Gestion de la face médiane créée entre deux autres
835 :face: la face médiane créée
836 :n_recur: niveau de récursivité
839 nom_fonction = __name__ + "/_cree_face_mediane_0"
840 blabla = "\nDans {} :".format(nom_fonction)
842 if self._verbose_max:
846 nom_face = self.nom_solide+"_M"
847 if self._verbose_max:
848 print_tab (n_recur,"Nom de la face créée : ", nom_face)
849 #if ( self.nom_solide_aux != self.objet_principal.name() ):
851 face.setName(nom_face)
852 face.result().setName(nom_face)
854 # 2. Mémorisation de la face et de la fonction initiale
855 self.l_faces_m.append((face, self.fonction_0))
857 # 3. Couleur verte pour la face
858 self._couleur_objet (face, coul_r=0, coul_g=170, coul_b=0)
860 # 4. Changement de statut pour le solide
861 self.d_statut_so[self.nom_solide] = 1
865 #=========================== Fin de la méthode ==================================
867 #=========================== Début de la méthode =================================
869 def _cree_face_mediane_plane ( self, geompy, solide, caract_face_1, caract_face_2, n_recur ):
870 """Crée la face médiane entre deux autres - cas des surfaces planes
873 :geompy: environnement de GEOM
874 :solide: l'objet solide à traiter
875 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
876 :n_recur: niveau de récursivité
879 :face: la face médiane
882 nom_fonction = __name__ + "/_cree_face_mediane_plane"
883 blabla = "\nDans {} :\n".format(nom_fonction)
884 if self._verbose_max:
887 # Caractéristiques des surfaces
888 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, n_recur )
890 # Contrôle de la validité de l'épaisseur
891 erreur = self._verif_epaisseur ( d_face_1_2 )
893 # Création de la face
895 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, n_recur )
901 #=========================== Fin de la méthode ==================================
903 #=========================== Début de la méthode =================================
905 def _cree_face_mediane_plane_0 ( self, geompy, solide, caract_face_1, caract_face_2, n_recur ):
906 """Crée la face médiane entre deux autres - cas des surfaces planes
908 Décodage des caractéristiques
911 :geompy: environnement de GEOM
912 :solide: l'objet solide à traiter
913 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
914 :n_recur: niveau de récursivité
917 :coo_x, coo_y, coo_z: coordonnées du centre de la base
918 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
919 :taille: estimation de la taille de la future face
920 :d_face_1_2: la distance entre les deux faces
923 nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
924 blabla = "\nDans {} :".format(nom_fonction)
926 if self._verbose_max:
928 print_tab (n_recur, "face_1 : ", caract_face_1)
929 print_tab (n_recur, "face_2 : ", caract_face_2)
931 # 1. Caractéristiques de la base
932 # Coordonnées du centre de la base
933 coo_x = caract_face_1[2][1]
934 coo_y = caract_face_1[2][2]
935 coo_z = caract_face_1[2][3]
936 # Coordonnées du vecteur normal
937 vnor_x = caract_face_1[2][4]
938 vnor_y = caract_face_1[2][5]
939 vnor_z = caract_face_1[2][6]
940 # taille : la diagonale de la boîte englobante permet d'être certain de tout prendre
941 l_diag = self._calcul_boite_englobante ( solide, n_recur )
943 if self._verbose_max:
944 print_tab (n_recur, "Taille englobante : ",taille)
946 # 2. Distance entre les deux faces
947 face_1 = caract_face_1[0]
948 face_2 = caract_face_2[0]
949 d_face_1_2 = geompy.MinDistance(face_1, face_2)
950 if self._verbose_max:
951 print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
953 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
955 #=========================== Fin de la méthode ==================================
957 #=========================== Début de la méthode =================================
959 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, n_recur ):
960 """Crée la face médiane entre deux autres - cas des surfaces planes
962 Création des objets temporaires et de la face médiane
965 :solide: l'objet solide à traiter
966 :coo_x, coo_y, coo_z: coordonnées du centre de la base
967 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
968 :taille: estimation de la taille de la future face
969 :d_face_1_2: la distance entre les deux faces
970 :n_recur: niveau de récursivité
973 :face: la face médiane
976 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
977 blabla = "\nDans {} :".format(nom_fonction)
978 if self._verbose_max:
980 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_x, coo_y, coo_z))
981 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor_x, vnor_y, vnor_z))
982 print_tab (n_recur, "Taille : ", taille)
983 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
985 # Création de paramètres
986 nom_par_1 = "{}_taille".format(self.nom_solide)
987 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(taille))
989 # Création du point central
990 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
991 nom_centre = "{}_centre".format(self.nom_solide)
992 centre.result().setName(nom_centre)
994 # Création du vecteur normal
995 v_norm = model.addAxis(self.part_doc, vnor_x, vnor_y, vnor_z)
996 nom_normal = "{}_normale".format(self.nom_solide)
997 v_norm.result().setName(nom_normal)
999 # Création du plan perpendiculaire au vecteur normal
1000 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_normal), model.selection("VERTEX", nom_centre), True)
1001 nom_plan = "{}_plan".format(self.nom_solide)
1002 plan.result().setName(nom_plan)
1004 # Création d'un sketch
1005 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1007 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1008 SketchPoint_1 = SketchProjection_1.createdFeature()
1010 ### Create SketchLine
1011 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1013 ### Create SketchLine
1014 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1016 ### Create SketchLine
1017 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1019 ### Create SketchLine
1020 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1021 sketch.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
1022 sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
1023 sketch.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
1024 sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
1026 ### Create SketchLine
1027 SketchLine_5 = sketch.addLine(-taille/2., taille/2., taille/2., -taille/2.)
1028 SketchLine_5.setAuxiliary(True)
1030 ### Create SketchLine
1031 SketchLine_6 = sketch.addLine(taille/2., taille/2., -taille/2., -taille/2.)
1032 SketchLine_6.setAuxiliary(True)
1033 sketch.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint())
1034 sketch.setCoincident(SketchLine_2.startPoint(), SketchLine_6.startPoint())
1035 sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_5.endPoint())
1036 sketch.setCoincident(SketchLine_4.startPoint(), SketchLine_6.endPoint())
1037 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_5.result())
1038 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_6.result())
1039 sketch.setHorizontal(SketchLine_1.result())
1040 sketch.setVertical(SketchLine_2.result())
1041 sketch.setHorizontal(SketchLine_3.result())
1042 sketch.setVertical(SketchLine_4.result())
1043 sketch.setLength(SketchLine_3.result(), nom_par_1)
1044 sketch.setEqual(SketchLine_3.result(), SketchLine_4.result())
1047 nom_sketch = "{}_esquisse".format(self.nom_solide)
1048 sketch.setName(nom_sketch)
1049 sketch.result().setName(nom_sketch)
1051 ### Create LinearCopy
1052 LinearCopy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1053 LinearCopy_1.result().subResult(0).setName("{}_0".format(self.nom_solide_aux))
1056 Recover_1 = model.addRecover(self.part_doc, LinearCopy_1, [solide])
1057 Recover_1.result().setName("{}_1".format(self.nom_solide_aux))
1059 # Création d'une face ; on la translate d'une demi-épaisseur.
1060 for iaux in range(2):
1062 distance = -0.5*d_face_1_2*float(2*iaux-1)
1063 nom_solide = "{}_{}".format(self.nom_solide_aux,iaux)
1064 face = self._cree_face_mediane_plane_2 ( nom_sketch, nom_normal, nom_solide, distance, iaux )
1067 face = self._cree_face_mediane_plane_11 ( face, Recover_1, n_recur )
1069 # Si l'intersection est vide, on la translate dans l'autre sens
1071 if self._verbose_max:
1072 print_tab (n_recur, "L'intersection est vide.")
1077 #=========================== Fin de la méthode ==================================
1079 #=========================== Début de la méthode =================================
1081 def _cree_face_mediane_plane_11 ( self, face, Recover_1, n_recur ):
1082 """Crée la face médiane entre deux autres - cas des surfaces planes
1084 Création des objets temporaires et de la face médiane
1087 :face: la face médiane
1088 :Recover_1: la récupératiuon du solide
1089 :n_recur: niveau de récursivité
1092 :face: la face médiane
1095 nom_fonction = __name__ + "/_cree_face_mediane_plane_11"
1096 blabla = "\nDans {} :".format(nom_fonction)
1097 if self._verbose_max:
1099 print_tab (n_recur, "face : ", face.name())
1101 # Si on traite un objet solide unique, on le récupère
1102 if ( self.nom_solide_aux == self.objet_principal.name() ):
1103 if self._verbose_max:
1104 print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1105 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1106 Recover_2.result().setName("{}_S".format(self.nom_solide_aux))
1108 nb_inter = face.result().numberOfSubs()
1109 if self._verbose_max:
1110 print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1113 face = self._cree_face_mediane_plane_3 ( face )
1117 #=========================== Fin de la méthode ==================================
1119 #=========================== Début de la méthode =================================
1121 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, distance, icpt=0 ):
1122 """Crée la face médiane entre deux autres - cas des surfaces planes
1124 Intersection de la face avec le solide
1127 :nom_sketch: nom du sketch
1128 :nom_normal: nom du vecteur normal
1129 :nom_solide: nom du solide à intersecter
1130 :distance: la distance de translation
1131 :icpt: numéro de la tentative
1134 :face: la face médiane
1137 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1138 blabla = "\nDans {} :\n".format(nom_fonction)
1139 if self._verbose_max:
1141 texte += "nom_sketch : {}\n".format(nom_sketch)
1142 texte += "nom_normal : {}\n".format(nom_normal)
1143 texte += "nom_solide : {}\n".format(nom_solide)
1144 texte += "distance : {}".format(distance)
1147 # Création d'une face
1148 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1149 nom_face_1 = "{}_face_1_{}".format(self.nom_solide_aux,icpt)
1150 Face_1.result().setName(nom_face_1)
1153 Translation_1 = model.addTranslation(self.part_doc, [model.selection("FACE", nom_face_1)], axis = model.selection("EDGE", nom_normal), distance = distance, keepSubResults = True)
1154 nom_trans = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1155 Translation_1.setName(nom_trans)
1156 Translation_1.result().setName(nom_trans)
1157 Translation_1.result().setColor(85, 0, 255)
1159 # Intersection de cette face avec le solide initial
1160 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_trans)], keepSubResults = True)
1164 #=========================== Fin de la méthode ==================================
1166 #=========================== Début de la méthode =================================
1168 def _cree_face_mediane_plane_3 ( self, face ):
1169 """Crée la face médiane entre deux autres - cas des surfaces planes
1171 Fusion des 2 intersections
1174 :face: la face médiane composée de plusieurs intersections
1177 :face_m: la face médiane
1180 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1181 blabla = "\nDans {} :\n".format(nom_fonction)
1182 if self._verbose_max:
1186 # Nommage des sous-objets
1188 for iaux in range(face.result().numberOfSubs()):
1189 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1190 face.result().subResult(iaux).setName(nom)
1191 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1194 if self._verbose_max:
1195 print ("Fusion de {} faces.".format(len(l_fuse)))
1196 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1200 #=========================== Fin de la méthode ==================================
1202 #=========================== Début de la méthode =================================
1204 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1205 """Crée la face médiane entre deux autres - cas des cylindres
1208 :solide: solide SHAPER à traiter
1209 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1210 :n_recur: niveau de récursivité
1213 :face: la face médiane
1216 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1217 blabla = "\nDans {} :\n".format(nom_fonction)
1220 if self._verbose_max:
1222 print_tab (n_recur, "face_1 : ", caract_face_1)
1223 print_tab (n_recur, "face_2 : ", caract_face_2)
1225 # Caractéristiques des cylindres
1226 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, n_recur )
1228 # Contrôle de la validité de l'épaisseur
1229 erreur = self._verif_epaisseur ( epaisseur )
1231 # Création de la face
1233 face = self._cree_face_mediane_cylindre_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur )
1235 self._couleur_objet (solide, n_recur, coul_r=0, coul_g=0, coul_b=255)
1240 #=========================== Fin de la méthode ==================================
1242 #=========================== Début de la méthode =================================
1244 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1245 """Crée la face médiane entre deux autres - cas des cylindres
1247 Décodage des caractéristiques
1250 :solide: l'objet solide à traiter
1251 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1252 :n_recur: niveau de récursivité
1255 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1256 :axe_x, axe_y, axe_z: coordonnées de l'axe
1257 :rayon: rayon moyen entre les deux faces
1258 :hauteur: hauteur du cylindre
1259 :epaisseur: épaisseur de l'interface entre les deux faces
1262 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1263 blabla = "\nDans {} :\n".format(nom_fonction)
1265 if self._verbose_max:
1267 print_tab (n_recur, "face_1 : ", caract_face_1)
1268 print_tab (n_recur, "face_2 : ", caract_face_2)
1270 # Coordonnées du centre de la base
1271 coo_x = caract_face_1[2][1]
1272 coo_y = caract_face_1[2][2]
1273 coo_z = caract_face_1[2][3]
1274 # Coordonnées de l'axe
1275 axe_x = caract_face_1[2][4]
1276 axe_y = caract_face_1[2][5]
1277 axe_z = caract_face_1[2][6]
1279 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1280 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
1281 l_diag = self._calcul_boite_englobante ( solide, n_recur )
1282 hauteur = 10.*l_diag
1283 if self._verbose_max:
1284 print_tab (n_recur, "Hauteur englobante : ", hauteur)
1286 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1288 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1290 #=========================== Fin de la méthode ==================================
1292 #=========================== Début de la méthode =================================
1294 def _cree_face_mediane_cylindre_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur ):
1295 """Crée la face médiane entre deux autres - cas des cylindres
1297 Création des objets temporaires et de la face externe du cylindre support
1300 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1301 :axe_x, axe_y, axe_z: coordonnées de l'axe
1302 :rayon: rayon moyen entre les deux faces
1303 :hauteur: hauteur du cylindre
1306 :face: la face médiane
1308 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1309 blabla = "\nDans {} :\n".format(nom_fonction)
1311 # Les caractéristiques du cylindre à créer
1312 if self._verbose_max:
1314 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1315 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1316 texte += "Rayon : {}\n".format(rayon)
1317 texte += "Hauteur : {}".format(hauteur)
1320 # Création du point central
1321 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1322 nom_centre = "{}_centre".format(self.nom_solide)
1323 centre.result().setName(nom_centre)
1326 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1327 nom_axe = "{}_axe".format(self.nom_solide)
1328 axe.result().setName(nom_axe)
1330 # Création du plan perpendiculaire à l'axe
1331 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), True)
1332 nom_plan = "{}_plan".format(self.nom_solide)
1333 plan.result().setName(nom_plan)
1335 # Création d'un sketch
1336 nom_par_1 = "{}_R".format(self.nom_solide)
1337 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1338 nom_par_2 = "{}_H".format(self.nom_solide)
1339 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(hauteur))
1341 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1343 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1344 SketchPoint_1 = SketchProjection_1.createdFeature()
1346 SketchCircle_1 = sketch.addCircle(0., 0., rayon)
1347 sketch.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
1348 sketch.setRadius(SketchCircle_1.results()[1], nom_par_1)
1350 nom_sketch = "{}_esquisse".format(self.nom_solide)
1351 sketch.setName(nom_sketch)
1352 sketch.result().setName(nom_sketch)
1354 # Création du cylindre complet
1355 cylindre = model.addExtrusion(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))], model.selection(), nom_par_2, nom_par_2, "Edges")
1356 nom_cylindre = "{}_cylindre".format(self.nom_solide)
1357 cylindre.setName(nom_cylindre)
1358 cylindre.result().setName(nom_cylindre)
1359 cylindre.result().setColor(85, 0, 255)
1361 # Intersection de la face cylindrique avec le solide initial
1362 face = self._creation_face_inter ( nom_cylindre )
1366 #=========================== Fin de la méthode ==================================
1368 #=========================== Début de la méthode =================================
1370 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1371 """Crée la face médiane entre deux autres - cas des sphères
1374 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1375 :n_recur: niveau de récursivité
1378 :face: la face médiane
1381 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1382 blabla = "\nDans {} :".format(nom_fonction)
1385 if self._verbose_max:
1387 print_tab (n_recur, "face_1 : ", caract_face_1)
1388 print_tab (n_recur, "face_2 : ", caract_face_2)
1390 # Caractéristiques des sphères
1391 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1393 # Contrôle de la validité de l'épaisseur
1394 erreur = self._verif_epaisseur ( epaisseur )
1396 # Création de la face
1398 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1404 #=========================== Fin de la méthode ==================================
1406 #=========================== Début de la méthode =================================
1408 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1409 """Crée la face médiane entre deux autres - cas des sphères
1411 Décodage des caractéristiques
1414 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1415 :n_recur: niveau de récursivité
1418 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1419 :rayon: rayon moyen entre les deux faces
1420 :epaisseur: épaisseur de l'interface entre les deux faces
1423 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1424 blabla = "\nDans {} :".format(nom_fonction)
1427 if self._verbose_max:
1429 print_tab (n_recur, "face_1 : ", caract_face_1)
1430 print_tab (n_recur, "face_2 : ", caract_face_2)
1432 # Coordonnées du centre de la sphère
1433 coo_x = caract_face_1[2][1]
1434 coo_y = caract_face_1[2][2]
1435 coo_z = caract_face_1[2][3]
1437 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1439 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1441 return coo_x, coo_y, coo_z, rayon, epaisseur
1443 #=========================== Fin de la méthode ==================================
1445 #=========================== Début de la méthode =================================
1447 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1448 """Crée la face médiane entre deux autres - cas des sphères
1450 Création des objets temporaires et de la face externe de la sphère support
1453 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1454 :rayon: rayon moyen entre les deux faces
1457 :face: la face externe de la sphère support
1460 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1461 blabla = "\nDans {} :\n".format(nom_fonction)
1463 # Les caractéristiques de la sphère à créer
1464 if self._verbose_max:
1466 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1467 texte += "Rayon : {}".format(rayon)
1470 # Création du point central
1471 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1472 nom_centre = "{}_centre".format(self.nom_solide)
1473 centre.result().setName(nom_centre)
1475 # Création d'un plan passant par ce centre et cet axe
1476 plan = model.addPlane(self.part_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", nom_centre), False)
1477 nom_plan = "{}_plan".format(self.nom_solide)
1478 plan.result().setName(nom_plan)
1480 # Création d'un sketch
1481 nom_par_1 = "{}_R".format(self.nom_solide)
1482 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1484 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1486 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1487 SketchPoint_1 = SketchProjection_1.createdFeature()
1489 ### Create SketchArc
1490 SketchArc_1 = sketch.addArc(coo_x, coo_y, coo_x-rayon, coo_y, coo_x+rayon, coo_y, False)
1491 sketch.setRadius(SketchArc_1.results()[1], nom_par_1)
1492 sketch.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
1494 ### Create SketchLine
1495 SketchLine_1 = sketch.addLine(coo_x-rayon, coo_y, coo_x+rayon, coo_y)
1496 nom_ligne = "{}_ligne".format(self.nom_solide)
1497 SketchLine_1.setName(nom_ligne)
1498 SketchLine_1.result().setName(nom_ligne)
1499 SketchLine_1.setAuxiliary(True)
1500 sketch.setHorizontal(SketchLine_1.result())
1501 sketch.setCoincident(SketchArc_1.startPoint(), SketchLine_1.startPoint())
1502 sketch.setCoincident(SketchArc_1.endPoint(), SketchLine_1.endPoint())
1503 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result())
1506 nom_sketch = "{}_esquisse".format(self.nom_solide)
1507 sketch.setName(nom_sketch)
1508 sketch.result().setName(nom_sketch)
1510 # Création de la sphère complète
1511 sphere = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", "{}/{}".format(nom_sketch,nom_ligne)), 360, 0, "Edges")
1512 nom_sphere = "{}_sphere".format(self.nom_solide)
1513 sphere.setName(nom_sphere)
1514 sphere.result().setName(nom_sphere)
1515 sphere.result().setColor(85, 0, 255)
1517 # Intersection de la face sphérique avec le solide initial
1518 face = self._creation_face_inter ( nom_sphere )
1522 #=========================== Fin de la méthode ==================================
1524 #=========================== Début de la méthode =================================
1526 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1527 """Crée la face médiane entre deux autres - cas des tores
1530 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1531 :n_recur: niveau de récursivité
1534 :face: la face médiane
1537 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1538 blabla = "\nDans {} :".format(nom_fonction)
1541 if self._verbose_max:
1543 print_tab (n_recur, "face_1 : ", caract_face_1)
1544 print_tab (n_recur, "face_2 : ", caract_face_2)
1546 # Caractéristiques des tores
1547 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, n_recur )
1549 # Contrôle de la validité de l'épaisseur (bidon)
1550 erreur = self._verif_epaisseur ( EP_MIN*10. )
1552 # Création de la face
1554 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1560 #=========================== Fin de la méthode ==================================
1562 #=========================== Début de la méthode =================================
1564 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1565 """Crée la face médiane entre deux autres - cas des tores
1567 Décodage des caractéristiques
1570 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1571 :n_recur: niveau de récursivité
1574 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1575 :axe_x, axe_y, axe_z: coordonnées de l'axe
1576 :rayon_1 : rayon principal
1577 :rayon_2 : rayon secondaire
1580 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1581 blabla = "\nDans {} :".format(nom_fonction)
1584 if self._verbose_max:
1586 print_tab (n_recur, "face_1 : ", caract_face_1)
1587 print_tab (n_recur, "face_2 : ", caract_face_2)
1589 # Coordonnées du centre du tore
1590 coo_x = caract_face_1[2][1]
1591 coo_y = caract_face_1[2][2]
1592 coo_z = caract_face_1[2][3]
1593 # Coordonnées de l'axe
1594 axe_x = caract_face_1[2][4]
1595 axe_y = caract_face_1[2][5]
1596 axe_z = caract_face_1[2][6]
1598 rayon_1 = caract_face_2[2][7]
1599 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1601 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1603 #=========================== Fin de la méthode ==================================
1605 #=========================== Début de la méthode =================================
1607 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1608 """Crée la face médiane entre deux autres - cas des tores
1610 Création des objets temporaires et de la face externe du tore support
1613 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1614 :axe_x, axe_y, axe_z: coordonnées de l'axe
1615 :rayon_1 : rayon principal
1616 :rayon_2 : rayon secondaire
1619 :face: la face externe du tore support
1622 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1623 blabla = "\nDans {} :\n".format(nom_fonction)
1626 if self._verbose_max:
1628 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1629 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1630 texte += "Rayon principal : {}\n".format(rayon_1)
1631 texte += "Rayon secondaire : {}".format(rayon_2)
1634 # Création du point central
1635 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1636 nom_centre = "{}_centre".format(self.nom_solide)
1637 centre.result().setName(nom_centre)
1640 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1641 nom_axe = "{}_axe".format(self.nom_solide)
1642 axe.result().setName(nom_axe)
1644 # Création d'un plan passant par ce centre et cet axe
1645 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
1646 nom_plan = "{}_plan".format(self.nom_solide)
1647 plan.result().setName(nom_plan)
1649 # Création d'un sketch
1650 nom_par_1 = "{}_R_1".format(self.nom_solide)
1651 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1652 nom_par_2 = "{}_R_2".format(self.nom_solide)
1653 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1655 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1657 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1658 SketchPoint_1 = SketchProjection_1.createdFeature()
1660 SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1661 SketchLine_1 = SketchProjection_2.createdFeature()
1663 SketchPoint_2 = sketch.addPoint(rayon_1, 0.)
1664 sketch.setDistance(SketchPoint_1.result(), SketchPoint_2.coordinates(), nom_par_1, True)
1666 SketchLine_2 = sketch.addLine(0., 0., rayon_1, 0.)
1667 SketchLine_2.setAuxiliary(True)
1668 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1669 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_2.endPoint())
1670 sketch.setPerpendicular(SketchLine_1.result(), SketchLine_2.result())
1672 SketchCircle_1 = sketch.addCircle(0., 0., rayon_2)
1673 sketch.setCoincident(SketchPoint_2.result(), SketchCircle_1.center())
1674 sketch.setRadius(SketchCircle_1.results()[1], nom_par_2)
1677 nom_sketch = "{}_esquisse".format(self.nom_solide)
1678 sketch.setName(nom_sketch)
1679 sketch.result().setName(nom_sketch)
1681 # Création du tore complet
1682 nom_tore = "{}_tore".format(self.nom_solide)
1683 self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_tore )
1685 # Intersection de la face torique avec le solide initial
1686 face = self._creation_face_inter ( nom_tore )
1690 #=========================== Fin de la méthode ==================================
1692 #=========================== Début de la méthode =================================
1694 def _cree_face_mediane_cone ( self, geompy, caract_face_1, caract_face_2, n_recur ):
1695 """Crée la face médiane entre deux autres - cas des cones
1698 :geompy: environnement de GEOM
1699 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1700 :n_recur: niveau de récursivité
1703 :face: la face médiane
1706 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1707 blabla = "\nDans {} :".format(nom_fonction)
1710 if self._verbose_max:
1712 print_tab (n_recur, "face_1 : ", caract_face_1)
1713 print_tab (n_recur, "face_2 : ", caract_face_2)
1715 # Caractéristiques des cones
1716 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, n_recur )
1718 # Contrôle de la validité de l'épaisseur (bidon)
1719 erreur = self._verif_epaisseur ( EP_MIN*10. )
1721 # Création de la face
1723 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1729 #=========================== Fin de la méthode ==================================
1731 #=========================== Début de la méthode =================================
1733 def _cree_face_mediane_cone_0 ( self, geompy, caract_face_1, caract_face_2, n_recur ):
1734 """Crée la face médiane entre deux autres - cas des cones
1736 Décodage des caractéristiques
1739 :geompy: environnement de GEOM
1740 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1741 :n_recur: niveau de récursivité
1744 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1745 :axe_x, axe_y, axe_z: coordonnées de l'axe
1746 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1747 :hauteur: hauteur du cone
1750 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1751 blabla = "\nDans {} :".format(nom_fonction)
1754 if self._verbose_max:
1756 print_tab (n_recur, "face_1 : ", caract_face_1)
1757 print_tab (n_recur, "face_2 : ", caract_face_2)
1759 # Coordonnées du centre de la base
1760 coo_x = caract_face_1[2][1]
1761 coo_y = caract_face_1[2][2]
1762 coo_z = caract_face_1[2][3]
1763 # Coordonnées de l'axe
1764 axe_x = caract_face_1[2][4]
1765 axe_y = caract_face_1[2][5]
1766 axe_z = caract_face_1[2][6]
1768 # Pour un cone complet, les caractéristiques fournies par GEOM sont correctes
1769 # Mais s'il est découpé, malheureusement,bug dans GEOM et caract_face_2[2][8] est toujours nul !
1770 # Alors on passe par le décodage des arêtes
1771 #rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1772 #rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1773 caract_arete_face_1 = self._calcul_caract_aretes_face ( geompy, caract_face_1 )
1774 caract_arete_face_2 = self._calcul_caract_aretes_face ( geompy, caract_face_2 )
1777 for caract_aretes_face in [caract_arete_face_1,caract_arete_face_2]:
1779 for l_aux in caract_aretes_face:
1780 if ( l_aux[0] in ( geompy.kind.CIRCLE, geompy.kind.ARC_CIRCLE ) ):
1781 #print ("R =",l_aux[7])
1790 hauteur = caract_face_1[2][9]
1792 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1794 #=========================== Fin de la méthode ==================================
1796 #=========================== Début de la méthode =================================
1798 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1799 """Crée la face médiane entre deux autres - cas des cones
1801 Création des objets temporaires et de la face externe du cone support
1804 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1805 :axe_x, axe_y, axe_z: coordonnées de l'axe
1806 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1807 :hauteur: hauteur du cone
1810 :face: la face externe du cone support
1812 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1813 blabla = "\nDans {} :\n".format(nom_fonction)
1816 if self._verbose_max:
1818 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1819 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1820 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1821 texte += "Hauteur : {}".format(hauteur)
1824 # Création du point central
1825 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1826 nom_centre = "{}_centre".format(self.nom_solide)
1827 centre.result().setName(nom_centre)
1830 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1831 nom_axe = "{}_axe".format(self.nom_solide)
1832 axe.result().setName(nom_axe)
1834 # Création d'un plan passant par ce centre et cet axe
1835 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
1836 nom_plan = "{}_plan".format(self.nom_solide)
1837 plan.result().setName(nom_plan)
1839 # Création d'un sketch
1840 nom_par_1 = "{}_R_1".format(self.nom_solide)
1841 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1842 nom_par_2 = "{}_R_2".format(self.nom_solide)
1843 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1844 nom_par_3 = "{}_H".format(self.nom_solide)
1845 model.addParameter(self.part_doc, "{}".format(nom_par_3), "{}".format(hauteur))
1847 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1849 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1850 SketchPoint_1 = SketchProjection_1.createdFeature()
1852 SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1853 SketchLine_1 = SketchProjection_2.createdFeature()
1855 SketchLine_2 = sketch.addLine(coo_x, coo_y, coo_x+rayon_1, coo_y+hauteur)
1856 SketchLine_2.setAuxiliary(True)
1857 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1858 sketch.setParallel(SketchLine_1.result(), SketchLine_2.result())
1859 sketch.setLength(SketchLine_2.result(), nom_par_3)
1861 SketchLine_3 = sketch.addLine(coo_x+rayon_1, coo_y, coo_x+rayon_1, coo_y+hauteur)
1862 sketch.setDistance(SketchLine_2.startPoint(), SketchLine_3.result(), nom_par_1, True)
1863 sketch.setDistance(SketchLine_2.endPoint(), SketchLine_3.result(), nom_par_2, True)
1864 sketch.setLength(SketchLine_3.result(), "2.5*{}".format(nom_par_3))
1866 SketchPoint_2 = sketch.addPoint(coo_x, coo_y)
1867 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_3.result())
1868 sketch.setMiddlePoint(SketchPoint_2.coordinates(), SketchLine_3.result())
1870 SketchLine_4 = sketch.addLine(coo_x, coo_y, 1.2*coo_x, 1.2*coo_y)
1871 SketchLine_4.setAuxiliary(True)
1872 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.startPoint())
1873 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_4.endPoint())
1874 sketch.setHorizontal(SketchLine_4.result())
1877 nom_sketch = "{}_esquisse".format(self.nom_solide)
1878 sketch.setName(nom_sketch)
1879 sketch.result().setName(nom_sketch)
1881 # Création du cone complet
1882 nom_cone = "{}_cone".format(self.nom_solide)
1883 self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_cone )
1885 # Intersection de la face conique avec le solide initial
1886 face = self._creation_face_inter ( nom_cone )
1890 #=========================== Fin de la méthode ==================================
1892 #=========================== Début de la méthode =================================
1894 def _calcul_boite_englobante ( self, objet, n_recur ):
1895 """Crée la hauteur englobant à coup sûr l'objet
1898 :objet: l'objet à traiter
1899 :n_recur: niveau de récursivité
1902 :l_diag: longueur de la diagonale de la boîte englobante
1905 nom_fonction = __name__ + "/_calcul_boite_englobante"
1906 blabla = "\nDans {} :".format(nom_fonction)
1908 if self._verbose_max:
1911 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
1912 if self._verbose_max:
1913 print_tab (n_recur, "Création de la boite englobante pour l'objet ", objet.name())
1914 print_tab (n_recur, "de type ", objet.shapeType())
1915 #print ('bbox = model.getBoundingBox(self.part_doc, model.selection("{}", "{}"))'.format(objet.shapeType(),objet.name()))
1916 bbox = model.getBoundingBox(self.part_doc, model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
1918 bbox_nom = bbox.name()
1919 if self._verbose_max:
1920 print_tab (n_recur, "Boîte englobante : '{}' '{}'".format(bbox.name(), bbox.result().name()))
1922 if self._verbose_max:
1923 coo_min = model.getPointCoordinates(self.part_doc, \
1924 model.selection("VERTEX", "[{}_1/Back][{}_1/Left][{}_1/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)))
1925 coo_max = model.getPointCoordinates(self.part_doc, \
1926 model.selection("VERTEX", "[{}_1/Front][{}_1/Right][{}_1/Top]".format(bbox_nom,bbox_nom,bbox_nom)))
1927 texte = "Xmin = {}, Xmax = {}\n".format(coo_min[0],coo_max[0])
1928 texte += "\tYmin = {}, Ymax = {}\n".format(coo_min[1],coo_max[1])
1929 texte += "\tZmin = {}, Zmax = {}".format(coo_min[2],coo_max[2])
1930 print_tab (n_recur, texte)
1932 l_diag = model.measureDistance(self.part_doc, \
1933 model.selection("VERTEX", "[{}_1/Back][{}_1/Left][{}_1/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)), \
1934 model.selection("VERTEX", "[{}_1/Front][{}_1/Right][{}_1/Top]".format(bbox_nom,bbox_nom,bbox_nom)) )
1935 if self._verbose_max:
1936 print_tab (n_recur, "Longueur de la diagonale : ", l_diag)
1940 #=========================== Fin de la méthode ==================================
1942 #=========================== Début de la méthode =================================
1944 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
1945 """Crée un volume de révolution
1948 :nom_sketch: nom du sketch à révolutionner
1949 :nom_centre: nom du point associé au centre du volume de révolution
1950 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1951 :axe_x, axe_y, axe_z: coordonnées de l'axe
1952 :rayon_1 : rayon principal
1953 :rayon_2 : rayon secondaire
1954 :nom_objet: nom de l'objet 2D créé
1957 nom_fonction = __name__ + "/_cree_revolution"
1958 blabla = "\nDans {} :\n".format(nom_fonction)
1960 if self._verbose_max:
1962 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1963 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1966 # Création d'un point décalé par rapport au point central
1967 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
1968 nom_point = "{}_point".format(self.nom_solide)
1969 point.result().setName(nom_point)
1971 # Création de l'axe de la rotation
1972 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
1973 nom_axe_r = "{}_axe_r".format(self.nom_solide)
1974 axe_r.result().setName(nom_axe_r)
1976 # Création de l'objet complet
1977 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
1978 objet.setName(nom_objet)
1979 objet.result().setName(nom_objet)
1980 objet.result().setColor(85, 0, 255)
1984 #=========================== Fin de la méthode ==================================
1986 #=========================== Début de la méthode =================================
1988 def _creation_face_inter ( self, nom_objet ):
1989 """Crée la face par intersection entre l'objet initial et une face complète
1991 . Repère la face principale de l'objet support
1992 . Réalise l'intersection avec le solide initial
1995 :nom_objet: nom de l'objet 2D créé
1998 :face: la face externe de l'objet support intersecté avec le solide initial
2001 nom_fonction = __name__ + "/_creation_face_inter"
2002 blabla = "\nDans {} :\n".format(nom_fonction)
2004 if self._verbose_max:
2007 face = model.addCommon(self.part_doc, [model.selection("SOLID", self.nom_solide_aux), model.selection("FACE", nom_objet)], keepSubResults = True)
2011 #=========================== Fin de la méthode ==================================
2013 #=========================== Début de la méthode =================================
2015 def face_mediane_solide (self, solide, geompy, objet_geom, n_recur=0):
2016 """Calcul de la face médiane pour un solide
2019 :solide: solide SHAPER à traiter
2020 :geompy: environnement de GEOM
2021 :objet_geom: l'objet solide à traiter au format GEOM
2022 :n_recur: niveau de récursivité
2025 :erreur: code d'erreur
2026 :message: message d'erreur
2029 nom_fonction = __name__ + "/face_mediane_solide"
2030 blabla = "\nDans {} :\n".format(nom_fonction)
2032 if self._verbose_max:
2035 print_tab (n_recur, "Traitement du solide ", solide.name())
2044 # 2. Explosion du solide en faces
2046 erreur, message, l_faces_geom, l_faces = self._faces_du_solide ( geompy, objet_geom, solide, n_recur )
2050 # 3. Calcul des caractéristiques géométriques des faces
2052 tb_caract = self._calcul_caract_faces ( geompy, l_faces_geom )
2054 # 4. Tri des faces en fonction de leurs caractéristiques géométriques
2056 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract )
2060 # 5. Création de la face médiane
2062 erreur, face = self._cree_face_mediane ( solide, geompy, caract_face_1, caract_face_2, n_recur )
2066 # 6. Exportation step
2068 if self._export_step:
2069 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2070 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2071 export.execute(True)
2078 if ( erreur and self._verbose_max ):
2079 print (blabla, message)
2081 return erreur, message
2083 #=========================== Fin de la méthode ==================================
2085 #=========================== Début de la méthode =================================
2087 def _traitement_objet (self, solide=None, objet_geom=None, n_recur=0):
2088 """Traitement d'un objet
2091 :solide: solide SHAPER à traiter
2092 :objet_geom: l'objet GEOM équivalent
2093 :n_recur: niveau de récursivité
2096 :erreur: code d'erreur
2097 :message: message d'erreur
2100 nom_fonction = __name__ + "/_traitement_objet"
2101 blabla = "\nDans {} :".format(nom_fonction)
2103 if self._verbose_max:
2105 print_tab (n_recur, "solide = " , solide)
2106 print_tab (n_recur, "objet_geom = ", objet_geom)
2117 if self.affiche_aide_globale :
2120 # 3. Les imports pour salomé
2121 geompy = geomBuilder.New()
2123 # 4. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2124 # Attention à ne pas recréer le répertoire à chaque fois
2125 if self._export_step:
2127 if self._verbose_max:
2128 print_tab (n_recur, "Préparation de l'export STEP")
2130 if self.rep_step is None:
2131 if self.ficcao is None:
2132 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2134 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2135 if os.path.isdir(self.rep_step):
2136 l_aux = os.listdir(self.rep_step)
2137 for nomfic in l_aux:
2138 os.remove(os.path.join(self.rep_step,nomfic))
2140 os.mkdir(self.rep_step)
2141 if self._verbose_max:
2142 print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2144 # 5. Calcul réel de la face médiane
2147 self.nom_solide = objet_geom.GetName()
2149 erreur, message = self.face_mediane_solide (solide, geompy, objet_geom, n_recur)
2155 return erreur, message
2157 #=========================== Fin de la méthode ==================================
2159 #=========================== Début de la méthode =================================
2161 def surf_fic_cao (self, ficcao, nom_objet=None):
2162 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2165 :ficcao: fichier de l'objet à traiter
2166 :nom_objet: un nom à donner à l'objet à traiter
2169 :erreur: code d'erreur
2170 :message: message d'erreur
2173 nom_fonction = __name__ + "/surf_fic_cao"
2174 blabla = "\nDans {} :\n".format(nom_fonction)
2176 if self._verbose_max:
2186 # 1. Définition de la pièce
2188 self.part_doc = model.activeDocument()
2189 if ( self.part_doc.kind() == "PartSet" ):
2190 part = model.addPart(self.part_doc)
2191 self.part_doc = part.document()
2193 # 2. Import de la CAO
2195 self.ficcao = ficcao
2196 print ("Traitement du fichier {}".format(ficcao))
2198 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2202 # 3. Calcul des surfaces
2204 erreur, message = self.surf_objet_shaper ( objet )
2213 if ( erreur and self._verbose_max ):
2214 print (blabla, message)
2216 return erreur, message
2218 #=========================== Fin de la méthode ==================================
2220 #=========================== Début de la méthode =================================
2222 def surf_objet_shaper (self, objet):
2223 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2226 :objet: objet à traiter
2229 :erreur: code d'erreur
2230 :message: message d'erreur
2233 nom_fonction = __name__ + "/surf_objet_shaper"
2234 blabla = "Dans {} :".format(nom_fonction)
2236 if self._verbose_max:
2239 # 1. Acquisition de la liste des noms des sous-objets solides
2241 self.d_statut_so = dict()
2242 self.l_noms_so = list()
2243 self.l_faces_m = list()
2245 _ = self._nom_sous_objets (objet, True)
2246 if self._verbose_max:
2247 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2249 # 2. Les faces médianes
2251 erreur, message = self._surf_objet_shaper_0 ( objet )
2253 # 3. Gestion des faces créées
2255 self._surf_objet_shaper_1 ( )
2257 # 4. Futur message pour le résultat
2259 if ( self._export_step and not erreur ):
2260 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2262 return erreur, message
2264 #=========================== Fin de la méthode ==================================
2266 #=========================== Début de la méthode =================================
2268 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2269 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2272 :objet: objet à traiter
2273 :n_recur: niveau de récursivité
2276 :erreur: code d'erreur
2277 :message: message d'erreur
2280 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2281 blabla = "Dans {} :\n".format(nom_fonction)
2283 if self._verbose_max:
2285 for _ in range(n_recur):
2287 texte = "\n{}{}".format(prefixe,blabla)
2288 texte += "{}n_recur = {}".format(prefixe,n_recur)
2296 # 1. Au premier passage, il faut récupérer la pièce et garder la référence au résultat principal
2298 if ( n_recur == 0 ):
2299 self.part_doc = model.activeDocument()
2300 objet_0 = objet.result()
2301 self.objet_principal = objet_0
2302 objet_bis = objet.defaultResult().shape()
2303 print_tab (n_recur, "Examen de l'objet ", objet.result().name(), saut_av=True)
2304 print_tab (n_recur, "Type python : ", type(objet))
2305 print_tab (n_recur, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2307 exp = GeomAPI_ShapeExplorer(objet_bis, GeomAPI_Shape.SOLID)
2309 l_volumes.append(exp.current().solid())
2312 for ivolume, volume in enumerate(l_volumes):
2313 print_tab (n_recur+1, "Type python : ", type(volume))
2314 print_tab (n_recur+1, "Volume n°{} ; volume = ".format(ivolume), GeomAlgoAPI_ShapeTools.volume(volume))
2315 print_tab (n_recur+1, "Type {} / ".format(volume.shapeType()), volume.shapeTypeStr())
2316 #print ("\tInformations : {}".format(volume.shapeInfo()))
2319 exp = GeomAPI_ShapeExplorer(volume, GeomAPI_Shape.FACE)
2321 l_faces.append(exp.current().face())
2324 for iface, face in enumerate(l_faces):
2325 print_tab (n_recur+2, "Face n°{} ; surface = ".format(iface), GeomAlgoAPI_ShapeTools.area(face))
2328 print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2329 print_tab (n_recur, "Type python : ", type(objet))
2330 print_tab (n_recur, "Type ", objet.shapeType())
2332 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2334 nb_sub_results = objet_0.numberOfSubs()
2336 if self._verbose_max:
2337 print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType())
2338 print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2340 for n_sobj in range(nb_sub_results):
2342 # 2.1. Exploration récursive de l'arborescence
2344 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2348 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2350 if ( objet_0.shapeType() == "SOLID" ):
2351 erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2358 # 3. Futur message pour le résultat
2360 if self._export_step:
2361 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2365 return erreur, message
2367 #=========================== Fin de la méthode ==================================
2369 #=========================== Début de la méthode =================================
2371 def _surf_objet_shaper_1 (self, n_recur=0):
2372 """Gestion des surfaces médianes créées
2375 :n_recur: niveau de récursivité
2378 :erreur: code d'erreur
2379 :message: message d'erreur
2382 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2383 blabla = "Dans {} :\n".format(nom_fonction)
2385 if self._verbose_max:
2388 # 1. Informations sur les faces à problème
2390 if self.faces_pb_nb:
2391 if ( self.faces_pb_nb == 1 ):
2392 texte = "1 face pose"
2394 texte = "{} faces posent".format(self.faces_pb_nb)
2395 print_tab (n_recur, "{} problème.".format(texte), self.faces_pb_msg, saut_av=True)
2397 # 2. Si plus d'une face a été créée
2398 if ( len(self.l_faces_m) > 1 ):
2400 # 2.1. Partition du paquet de faces
2402 if self._verbose_max:
2403 print_tab (n_recur, "Partitionnnement des faces créées.")
2406 for (face,_) in self.l_faces_m:
2407 l_objets.append(model.selection("COMPOUND", "all-in-{}".format(face.name())))
2409 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2411 Partition_1.result().setName("{}_M".format(self.objet_principal.name()))
2412 for iaux, (face,_) in enumerate(self.l_faces_m):
2413 Partition_1.result().subResult(iaux).setName("{}".format(face.name()))
2414 self._couleur_objet (Partition_1, n_recur, coul_r=0, coul_g=170, coul_b=0)
2416 # 2.2. Récupération des faces individuelles
2418 if self._verbose_max:
2419 print_tab (n_recur, "Récupération des faces individuelles.")
2422 for iaux, (face,_) in enumerate(self.l_faces_m):
2423 l_objets.append(face.result())
2425 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2426 for iaux, (face,_) in enumerate(self.l_faces_m):
2427 Recover_1.results()[iaux].setName("{}".format(face.name()))
2428 Recover_1.results()[iaux].setColor(0, 170, 0)
2430 # 2.3. Mise en dossier
2432 if self._verbose_max:
2433 print_tab (n_recur, "Mise en dossier.")
2435 for (face,fonction_0) in self.l_faces_m:
2436 dossier = model.addFolder(self.part_doc, fonction_0, face)
2437 dossier.setName(face.name()[:-2])
2441 #=========================== Fin de la méthode ==================================
2443 #=========================== Début de la méthode =================================
2445 def surf_solide_shaper (self, solide, n_recur):
2446 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2449 :solide: solide SHAPER à traiter
2450 :n_recur: numéro de la récurrence
2453 :erreur: code d'erreur
2454 :message: message d'erreur
2457 nom_fonction = __name__ + "/surf_solide_shaper"
2458 blabla = "Dans {} :".format(nom_fonction)
2460 if self._verbose_max:
2468 self.nom_solide = solide.name()
2469 if self._verbose_max:
2470 print_tab (n_recur, "solide", self.nom_solide)
2472 # 1. Isolement du solide
2473 solide_aux, recover = self._isole_solide ( solide, n_recur )
2475 # 2. Exportation dans un fichier step pour traitement dans GEOM
2477 fichier = tempfile.mkstemp(suffix=".stp")[1]
2478 if self._verbose_max:
2479 print_tab (n_recur, "fichier = ", fichier)
2480 print_tab (n_recur, "solide = ", solide_aux.name())
2481 print_tab (n_recur, "de type = ", solide_aux.shapeType())
2482 export = model.exportToFile(self.part_doc, fichier, [model.selection(solide_aux.shapeType(), solide_aux.name())])
2483 export.execute(True)
2486 taille = os.path.getsize(fichier)
2488 message = "Export de SHAPER vers GEOM impossible pour le solide '{}' de type '{}'\n".format(solide_aux.name(), solide_aux.shapeType())
2489 message += "Le fichier {} est de taille {}".format(fichier,taille)
2493 # 3. Importation dans GEOM
2494 geompy = geomBuilder.New()
2495 objet_geom = geompy.ImportSTEP(fichier, False, True)
2498 # 4. Traitement de l'objet correspondant
2499 erreur, message = self._traitement_objet ( solide=solide_aux, objet_geom=objet_geom, n_recur=n_recur )
2501 if ( erreur and self._verbose_max ):
2502 print (blabla, message)
2504 # 5. Mise en forme de l'objet principal récupéré
2505 if ( recover is not None ):
2506 _ = self._nom_sous_objets (recover, False)
2508 # 6. Neutralisation des erreurs dues à l'épaisseur
2509 if ( erreur in (-2,-1,2) ):
2515 return erreur, message
2517 #=========================== Fin de la méthode ==================================
2519 #=========================== Début de la méthode =================================
2521 def surf_objet_geom (self, objet_geom):
2522 """Calcule la surface médiane pour un objet GEOM passé en argument
2525 :objet_geom: l'objet GEOM à traiter
2528 :erreur: code d'erreur
2529 :message: message d'erreur
2532 nom_fonction = __name__ + "/surf_objet_geom"
2533 blabla = "\nDans {} :\n".format(nom_fonction)
2535 if self._verbose_max:
2538 erreur, message = self._traitement_objet ( objet_geom=objet_geom )
2540 if ( erreur and self._verbose_max ):
2541 print (blabla, message)
2543 return erreur, message
2545 #=========================== Fin de la méthode ==================================
2547 #=========================== Début de la méthode =================================
2549 def lancement (self):
2554 :erreur: code d'erreur
2555 :message: message d'erreur
2558 nom_fonction = __name__ + "/lancement"
2559 blabla = "\nDans {} :\n".format(nom_fonction)
2561 if self._verbose_max:
2564 erreur, message = self._traitement_objet ( )
2566 if ( erreur and self._verbose_max ):
2567 print (blabla, message)
2569 return erreur, message
2571 #=========================== Fin de la méthode ==================================
2573 #========================== Fin de la classe ====================================
2575 #==================================================================================
2577 #==================================================================================
2579 if __name__ == "__main__" :
2581 HOME_SH_SM_EXCHANGE = os.environ["HOME_SH_SM_EXCHANGE"]
2583 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "Solid_7.step"))
2584 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Objet_1.stp"))
2585 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval_007.stp"))
2586 ##L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval.stp"))
2587 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2.step"))
2588 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_22.step"))
2589 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_5.step"))
2590 L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Observatoire.stp"))
2592 for FIC_CAO in L_FIC_CAO:
2597 #L_OPTIONS.append("-h")
2598 #L_OPTIONS.append("-v")
2599 L_OPTIONS.append("-vmax")
2600 L_OPTIONS.append("-export_step")
2602 # 2. Lancement de la classe
2604 #print ("L_OPTIONS :", L_OPTIONS)
2606 SURFACE_MEDIANE = SurfaceMediane(L_OPTIONS)
2607 if SURFACE_MEDIANE.affiche_aide_globale:
2608 sys.stdout.write(SURFACE_MEDIANE.__doc__+"\n")
2611 PARTSET = model.moduleDocument()
2612 _ = model.addPart(PARTSET)
2613 ERREUR, MESSAGE_ERREUR = SURFACE_MEDIANE.surf_fic_cao(FIC_CAO)
2615 MESSAGE_ERREUR += "\n Code d'erreur : %d\n" % ERREUR
2616 sys.stderr.write(MESSAGE_ERREUR)