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__ = "V11.26"
41 #========================= Les imports - Début ===================================
51 from SketchAPI import *
52 from salome.shaper import model
53 from salome.shaper import geom
55 from GeomAlgoAPI import *
59 #========================== Les imports - Fin ====================================
62 D_FMT["stp"] = ["stp", "step"]
63 D_FMT["igs"] = ["igs", "iges"]
64 for CLE in ("brep", "xao"):
67 # statut = 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
86 # Transparence des solides traités correctement
89 # Limite basse de l'épaisseur pour pouvoir faire les intersections
92 #========================= Début de la fonction ==================================
94 def decode_cao (fmt_cao):
95 """Décode le format de la cao
98 :fmt_cao: format du fichier, step, iges, etc.
100 :fmt_cao_0: format décodé
105 fmt_cao_low = fmt_cao.lower()
107 for cle, l_aux in D_FMT.items():
108 if ( fmt_cao_low in l_aux ):
114 #========================= Fin de la fonction ===================================
116 #========================= Début de la fonction ==================================
118 def import_cao (part_doc, ficcao, nom_objet=None, verbose=False):
119 """Importation d'une cao
123 :ficcao: le fichier de la CAO
124 :nom_objet: nom à donner à l'objet lu, éventuellement
126 :objet: l'objet importé dans SHAPER
129 nom_fonction = __name__ + "/import_cao"
130 blabla = "Dans {} :\n".format(nom_fonction)
131 message_0 = "Fichier : {}\n".format(ficcao)
133 message = blabla + message_0
134 message += "nom_objet : {}".format(nom_objet)
142 laux = ficcao.split(".")
143 fmt_cao_0 = decode_cao (laux[-1])
145 if ( fmt_cao_0 not in ("stp", "brep", "igs", "xao") ):
146 message += "Le format de CAO est inconnu"
150 message += "Le fichier de CAO n'a pas été décodé correctement."
153 elif not os.path.isfile(ficcao):
154 message += "Le fichier de CAO est inconnu."
160 objet = model.addImport(part_doc, ficcao)
161 exec_nom (objet, nom_objet)
165 texte = "Objet : '{}'\n".format(objet.result().name())
166 texte += "De type : '{}'".format(objet.result().shapeType())
169 return erreur, message, objet
171 #========================= Fin de la fonction ===================================
173 #========================= Début de la fonction ==================================
175 def couleur_objet (objet, n_recur=0, coul_r=1, coul_g=0, coul_b=0, verbose=False):
176 """Appliquer une couleur à un objet et à ses sous_objets
179 :objet: objet à traiter
180 :n_recur: niveau de récursivité
181 :coul_r,coul_g,coul_b: code RGB de la couleur à appliquer
184 :rang: rang du sous-objet
187 nom_fonction = __name__ + "/couleur_objet"
188 blabla = "Dans {} :".format(nom_fonction)
192 print_tab(n_recur, "objet : ", objet.name())
193 print_tab(n_recur, "RGB = ({},{},{})".format(coul_r,coul_g,coul_b))
195 # 1. Au premier passage, il faut garder la référence au résultat principal
198 objet_0 = objet.result()
202 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
204 nb_sub_results = objet_0.numberOfSubs()
207 texte = "formé de {} sous-objets".format(nb_sub_results)
208 print_tab(n_recur, "Examen de l'objet '{}' ".format(objet_0.name()), texte)
210 for n_sobj in range(nb_sub_results):
212 # 2.1. Exploration récursive de l'arborescence
214 couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b, verbose )
216 # 2.2. Cet objet n'a pas de sous-objets : on le colore
218 print_tab(n_recur, "Couleur affectée à l'objet ",objet_0.name())
219 objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
221 #print ("sortie de {}".format(nom_fonction))
223 #========================= Fin de la fonction ===================================
225 #========================= Début de la fonction ==================================
227 def print_tab (nb_tab, message, argu=None, saut_av=False, saut_ap=False):
228 """Imprime avec des tabulations
231 :nb_tab: nombre de tabulations à appliquer
232 :message: message principal
233 :argu: argument du format
234 :saut_av: saut de ligne avant le texte
235 :saut_ap: saut de ligne après le texte
243 for _ in range(nb_tab):
247 if ( argu is not None ):
248 texte += "{}".format(argu)
255 #========================= Fin de la fonction ===================================
257 #========================= Début de la fonction ==================================
259 def nommage (objet, nom, couleur=None):
260 """Nomme un objet et son résultat
263 :objet: objet à traiter
264 :nom: nom à attribuer
265 :couleur: éventuellement couleur
269 objet.result().setName(nom)
271 if ( couleur is not None ):
272 objet.result().setColor(couleur[0], couleur[1], couleur[2])
274 #========================= Fin de la fonction ===================================
276 #========================= Début de la fonction ==================================
278 def exec_nom (fonction, nom=None, couleur=None):
279 """Exécute la fonction puis éventuellement la nomme et nomme son résultat ; Couleur éventuelle
281 Attention : il faut commencer par exécuter la fonction sinon l enommage n'est pas cohérent en mode macro. Mystère...
284 :fonction: fonction à traiter
285 :nom: nom à attribuer éventuellement
286 :couleur: éventuellement couleur
289 fonction.execute(True)
291 if ( nom is not None ):
292 nommage (fonction, nom, couleur)
294 #========================= Fin de la fonction ===================================
297 #=================================== La classe ===================================
299 class SurfaceMediane (object):
301 """Calcul des surfaces médianes de solides minces
303 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
304 une structure qui est un solide ou un assemblage de solides (compound).
305 Pour réaliser l'opération, trois façons de faire :
307 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
309 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
310 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
312 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
313 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
316 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
317 de taille identique et supérieure aux tailles des autres faces du solide. \
318 Cela fonctionne pour des surfaces planes ou de forme canonique.
319 Il crée alors une surface au milieu de ces deux grandes faces. \
320 Cette face est coloriée en vert, le solide est en vert et transparent.
322 On sait traiter les faces :
329 Si la création n'a pas eu lieu, un message est émis et les solides sont mis en couleur :
330 . Rouge : le solide n'est pas assez mince.
331 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
332 . Orange : la forme de la face n'est pas reconnue.
340 . Exportation finale dans un fichier step. Par défaut, pas d'export.
341 -export_step/-no_export_step
344 surf_fic_cao --> import_cao
345 --> surf_objet_shaper (récursif) --> _nom_sous_objets
346 --> _surf_objet_shaper_0
347 --> surf_solide_shaper --> _isole_solide --> _isole_solide_a
349 --> _traitement_objet --> face_mediane_solide --> _faces_du_solide
351 --> _cree_face_mediane
353 _cree_face_mediane --> _cree_face_mediane_plane
354 --> _cree_face_mediane_cylindre
355 --> _cree_face_mediane_sphere
356 --> _cree_face_mediane_tore
357 --> _cree_face_mediane_cone
358 --> _cree_face_mediane_0
367 affiche_aide_globale = 0
374 nom_solide_aux = None
380 objet_principal = None
381 # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
383 # Statut de chaque sous-objet connu par son nom :
384 # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
386 # Liste des faces médianes créées et des fonctions initiales
388 # La fonction initiale
394 #=========================== Début de la méthode =================================
396 def __init__ ( self, liste_option ):
398 """Le constructeur de la classe SurfaceMediane
400 Décodage des arguments
401 On cherche ici les arguments généraux : aide, verbeux
404 for option in liste_option :
407 if isinstance(option,str):
408 saux = option.upper()
410 if saux in ( "-H", "-HELP" ):
411 self.affiche_aide_globale = 1
414 elif saux == "-VMAX" :
416 self._verbose_max = 1
417 elif saux == "-EXPORT_STEP":
418 self._export_step = True
419 elif saux == "-NO_EXPORT_STEP":
420 self._export_step = False
422 #=========================== Fin de la méthode ==================================
424 #=========================== Début de la méthode =================================
427 """A la suppression de l'instance de classe"""
428 if self._verbose_max:
429 print ("Suppression de l'instance de la classe.")
431 #=========================== Fin de la méthode ==================================
433 #=========================== Début de la méthode =================================
435 def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
436 """Gère les noms des sous_objets solides
439 :objet: objet à traiter
440 :lecture: vrai pour lire les noms, faux pour les attribuer
441 :n_recur: niveau de récursivité
442 :rang: rang du sous-objet
445 :rang: rang du sous-objet
448 nom_fonction = __name__ + "/_nom_sous_objets"
449 blabla = "Dans {} :\n".format(nom_fonction)
451 if self._verbose_max:
453 for _ in range(n_recur):
455 texte = "\n{}{}".format(prefixe,blabla)
456 texte += "{}n_recur = {}".format(prefixe,n_recur)
457 texte += "\n{}lecture = {}".format(prefixe,lecture)
460 # 1. Au premier passage, il faut garder la référence au résultat principal
463 objet_0 = objet.result()
464 if self._verbose_max:
465 print ("d_statut_so = {}".format(self.d_statut_so))
469 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
471 nb_sub_results = objet_0.numberOfSubs()
473 if self._verbose_max:
474 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
475 texte += "de type '{}'".format(objet_0.shapeType())
476 texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
479 for n_sobj in range(nb_sub_results):
481 # 2.1. Exploration récursive de l'arborescence
483 rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
485 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
487 if ( objet_0.shapeType() == "SOLID" ):
488 # A la lecture, on enregistre le nom
491 self.l_noms_so.append(nom)
492 self.d_statut_so[nom] = 0
493 # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
495 nom = self.l_noms_so[rang]
497 etat = self.d_statut_so[nom]
498 objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
500 objet_0.setTransparency (TRANSPARENCE)
505 #=========================== Fin de la méthode ==================================
507 #=========================== Début de la méthode =================================
509 def _isole_solide ( self, solide, n_recur ):
510 """Isole le solide de son arboresence
513 :solide: le solide à traiter
514 :n_recur: numéro de la récurrence
517 :objet: le solide isolé
518 :recover: la fonction de récupération
521 nom_fonction = __name__ + "/_isole_solide"
522 blabla = "Dans {} :".format(nom_fonction)
523 if self._verbose_max:
524 print_tab (n_recur, blabla)
525 texte = "Pour le solide '{}' ".format(solide.name())
526 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
527 print_tab (n_recur, texte)
529 if ( solide.name() != self.objet_principal.name() ):
530 objet, recover = self._isole_solide_a ( solide, n_recur )
533 objet, recover = self._isole_solide_b ( solide, n_recur )
535 if self._verbose_max:
536 print_tab (n_recur, "objet final : ", objet.name())
537 print_tab (n_recur, "fonction_0 : {}".format(self.fonction_0))
538 print_tab (n_recur, "recover : {}".format(recover))
540 return objet, recover
542 #=========================== Fin de la méthode ==================================
544 #=========================== Début de la méthode =================================
546 def _isole_solide_a ( self, solide, n_recur ):
547 """Isole le solide de son arboresence
550 :solide: le solide à traiter
551 :n_recur: numéro de la récurrence
554 :objet: le solide isolé
555 :recover: la fonction de récupération
558 nom_fonction = __name__ + "/_isole_solide_a"
559 blabla = "Dans {} :".format(nom_fonction)
560 if self._verbose_max:
561 print_tab (n_recur, blabla)
562 texte = "Pour le solide '{}' ".format(solide.name())
563 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
564 print_tab (n_recur, texte)
566 if self._verbose_max:
567 print_tab (n_recur, ". Extraction du solide '{}'".format(self.objet_principal.name()))
569 # 1. Extraction du solide
570 remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
571 remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
573 self.nom_solide_aux = "{}_S".format(solide.name())
574 if self._verbose_max:
575 print_tab (n_recur, "\tAttribution à remove_subshapes.result() du nom '{}'".format(self.nom_solide_aux))
576 exec_nom (remove_subshapes,self.nom_solide_aux)
578 self.fonction_0 = remove_subshapes
580 # 2. Récupération de l'objet principal
581 recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
582 if self._verbose_max:
583 print_tab (n_recur, "\tAttribution à recover du nom '{}'".format(self.objet_principal.name()))
584 exec_nom (recover,self.objet_principal.name())
586 return remove_subshapes.result(), recover
588 #=========================== Fin de la méthode ==================================
590 #=========================== Début de la méthode =================================
592 def _isole_solide_b ( self, solide, n_recur ):
593 """Isole le solide de son arboresence
596 :solide: le solide à traiter
597 :n_recur: numéro de la récurrence
600 :objet: le solide isolé
601 :recover: la fonction de récupération
604 nom_fonction = __name__ + "/_isole_solide_b"
605 blabla = "Dans {} :".format(nom_fonction)
606 if self._verbose_max:
607 print_tab (n_recur, blabla)
608 texte = "Pour le solide '{}' ".format(solide.name())
609 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
610 print_tab (n_recur, texte)
612 if self._verbose_max:
613 print_tab (n_recur, ". Mise en place du solide")
615 self.nom_solide_aux = self.objet_principal.name()
616 self.fonction_0 = None
620 #=========================== Fin de la méthode ==================================
622 #=========================== Début de la méthode =================================
624 def _faces_du_solide ( self, solide, n_recur=0 ):
625 """Détermine les faces d'un solide
628 :solide: solide SHAPER à traiter
629 :n_recur: niveau de récursivité
632 :l_faces_car: pour chaque face du solide (surface,caractéristiques)
635 nom_fonction = __name__ + "/_faces_du_solide"
636 blabla = "Dans {} :".format(nom_fonction)
637 if self._verbose_max:
638 print_tab (n_recur, blabla, saut_av=True)
642 if self._verbose_max:
643 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
644 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
647 #print_tab (n_recur, "volume = ", GeomAlgoAPI_ShapeTools.volume(solide.shape()))
648 # 1. Repérage des faces
649 objResult = solide.resultSubShapePair()[0]
651 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
653 l_faces.append(exp.current().face())
658 for iface, face in enumerate(l_faces):
659 surf = GeomAlgoAPI_ShapeTools.area(face)
660 caract = geom.shapeInfo(face)
661 if self._verbose_max:
662 print_tab (n_recur, "\tFace n°{} ; ".format(iface), "surface = {}, caractéristiques = {}".format(surf,caract))
663 l_faces_car.append((surf,caract))
667 #=========================== Fin de la méthode ==================================
669 #=========================== Début de la méthode =================================
671 def _calcul_caract_faces ( self, solide, n_recur ):
672 """Calcule les caractéristiques géométriques des faces du solide
675 :solide: solide SHAPER à traiter
676 :n_recur: niveau de récursivité
679 :tb_caract: tableau des caractéristiques géométriques des faces
682 nom_fonction = __name__ + "/_calcul_caract_faces"
683 blabla = "Dans {} :".format(nom_fonction)
684 if self._verbose_max:
685 print_tab (n_recur, blabla, saut_av=True)
686 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
687 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
689 # 1. Repérage des faces
690 objResult = solide.resultSubShapePair()[0]
692 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
694 l_faces.append(exp.current().face())
697 # 2. Caractéristiques
698 nb_faces = len(l_faces)
699 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
700 for iaux, face in enumerate(l_faces):
701 surf = GeomAlgoAPI_ShapeTools.area(face)
702 caract = geom.shapeInfo(face)
703 if self._verbose_max:
704 print_tab (n_recur, "\tFace n°{} ; ".format(iaux), "surface = {}, caractéristiques = {}".format(surf,caract))
706 tb_caract [iaux][0] = face
707 tb_caract [iaux][1] = surf
708 tb_caract [iaux][2] = caract
710 #if self._verbose_max:
711 #for iaux in range(nb_faces):
712 #print ("\t. tb_caract : {} {}".format(surf,tb_caract[iaux][2]))
716 #=========================== Fin de la méthode ==================================
718 #=========================== Début de la méthode =================================
720 def _tri_faces ( self, tb_caract, n_recur ):
721 """Trie les faces en fonction de leurs surfaces
724 :tb_caract: tableau des caractéristiques géométriques des faces
725 :n_recur: niveau de récursivité
728 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
734 nom_fonction = __name__ + "/_tri_faces"
735 blabla = "Dans {} :".format(nom_fonction)
737 # 1. Tri du tableau en fonction des surfaces
738 if self._verbose_max:
739 print_tab (n_recur, blabla)
740 print_tab (n_recur, "tb_caract brut : ", tb_caract)
741 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
742 if self._verbose_max:
743 print_tab (n_recur, "tb_caract trié :", tb_caract_1)
745 if self._verbose_max:
746 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
747 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
750 # 2. La surface suivante doit être différente, sinon ce n'est pas un solide mince
751 if ( len(tb_caract) > 2 ):
753 if self._verbose_max:
754 texte += "\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
756 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
757 if ( ecart < self._epsilon ):
758 message = "\nSolide '{}'\n".format(self.nom_solide)
759 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
760 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
761 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
762 if self._verbose_max:
763 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
764 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
765 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
767 self.d_statut_so[self.nom_solide] = -1
768 self.faces_pb_nb += 1
769 self.faces_pb_msg += message
771 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
773 #=========================== Fin de la méthode ==================================
775 #=========================== Début de la méthode =================================
777 def _verif_epaisseur ( self, epaisseur ):
778 """Contrôle de la validité de l'épaisseur
781 :epaisseur: épaisseur du solide
784 nom_fonction = __name__ + "/_verif_epaisseur"
785 blabla = "Dans {} :\n".format(nom_fonction)
787 if self._verbose_max:
789 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
790 texte += ". EP_MIN : {}".format(EP_MIN)
793 if ( epaisseur <= EP_MIN ):
794 message = "\nSolide '{}'\n".format(self.nom_solide)
795 message += ". Epaisseur : {}\n".format(epaisseur)
796 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
797 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
799 self.d_statut_so[self.nom_solide] = 2
800 self.faces_pb_nb += 1
801 self.faces_pb_msg += message
805 #print ("erreur = {}".format(erreur))
809 #=========================== Fin de la méthode ==================================
811 #=========================== Début de la méthode =================================
813 def _cree_face_mediane ( self, solide, caract_face_1, caract_face_2, n_recur ):
814 """Crée la face médiane entre deux autres
817 :solide: solide SHAPER à traiter
818 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
819 :n_recur: niveau de récursivité
822 :face: la face médiane créée
825 nom_fonction = __name__ + "/_cree_face_mediane"
826 blabla = "Dans {} :".format(nom_fonction)
828 if self._verbose_max:
829 print_tab (n_recur, blabla)
830 print_tab (n_recur, "face_1 : " ,caract_face_1)
831 print_tab (n_recur, "face_2 : " ,caract_face_2)
836 # 1. Forme de la face
837 forme = caract_face_1[2][0]
839 # 2. Traitement selon la forme de la face
841 if forme in ( "Disk" , "Plane", "Rectangle"):
842 erreur, face = self._cree_face_mediane_plane ( solide, caract_face_1, caract_face_2, n_recur )
844 # 2.2. Face cylindrique
845 elif ( forme == "Cylinder" ):
846 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
848 # 2.3. Face sphérique
849 elif ( forme == "Sphere" ):
850 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
853 elif ( forme == "Torus" ):
854 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
857 elif ( forme == "Cone" ):
858 erreur, face = self._cree_face_mediane_cone ( caract_face_1, caract_face_2, n_recur )
860 # 2.N. Face de forme inconnue
862 message = "\nSolide '{}'\n".format(self.nom_solide)
863 message += "sa face la plus grande est de forme : {}\n".format(forme)
864 message += "==> Impossible de créer la face médiane.\n"
866 self.d_statut_so[self.nom_solide] = -2
867 self.faces_pb_nb += 1
868 self.faces_pb_msg += message
870 # 3. Gestion de la face produite
873 self._cree_face_mediane_0 ( face, n_recur )
877 #=========================== Fin de la méthode ==================================
879 #=========================== Début de la méthode =================================
881 def _cree_face_mediane_0 ( self, face, n_recur ):
882 """Gestion de la face médiane créée entre deux autres
885 :face: la face médiane créée
886 :n_recur: niveau de récursivité
889 nom_fonction = __name__ + "/_cree_face_mediane_0"
890 blabla = "Dans {} :".format(nom_fonction)
892 if self._verbose_max:
893 print_tab (n_recur, blabla)
896 nom_face = self.nom_solide+"_M"
897 if self._verbose_max:
898 print_tab (n_recur,"Nom de la face créée : ", nom_face)
899 #if ( self.nom_solide_aux != self.objet_principal.name() ):
901 nommage (face, nom_face)
903 # 2. Mémorisation de la face et de la fonction initiale
904 self.l_faces_m.append((face, self.fonction_0))
906 # 3. Couleur verte pour la face
907 couleur_objet (face, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
909 # 4. Changement de statut pour le solide
910 self.d_statut_so[self.nom_solide] = 1
912 #=========================== Fin de la méthode ==================================
914 #=========================== Début de la méthode =================================
916 def _cree_face_mediane_plane ( self, solide, caract_face_1, caract_face_2, n_recur ):
917 """Crée la face médiane entre deux autres - cas des surfaces planes
920 :solide: l'objet solide à traiter
921 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
922 :n_recur: niveau de récursivité
925 :face: la face médiane
928 nom_fonction = __name__ + "/_cree_face_mediane_plane"
929 blabla = "Dans {} :".format(nom_fonction)
930 if self._verbose_max:
931 print_tab (n_recur, blabla)
933 # Caractéristiques des surfaces
934 coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2 = self._cree_face_mediane_plane_0 ( solide, caract_face_1, caract_face_2, n_recur )
936 # Contrôle de la validité de l'épaisseur
937 erreur = self._verif_epaisseur ( d_face_1_2 )
939 # Création de la face
941 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 )
947 #=========================== Fin de la méthode ==================================
949 #=========================== Début de la méthode =================================
951 def _cree_face_mediane_plane_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
952 """Crée la face médiane entre deux autres - cas des surfaces planes
954 Décodage des caractéristiques
957 :solide: l'objet solide à traiter
958 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
959 :n_recur: niveau de récursivité
962 :coo_x, coo_y, coo_z: coordonnées du centre de la base
963 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
964 :taille: estimation de la taille de la future face
965 :d_face_1_2: la distance entre les deux faces
968 nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
969 blabla = "Dans {} :".format(nom_fonction)
971 if self._verbose_max:
972 print_tab (n_recur, blabla)
973 print_tab (n_recur, "caract_face_1 : ", caract_face_1)
974 print_tab (n_recur, "caract_face_2 : ", caract_face_2)
976 # 1. Caractéristiques de la base
977 # Coordonnées du centre de la base
978 coo_x = caract_face_1[2][1]
979 coo_y = caract_face_1[2][2]
980 coo_z = caract_face_1[2][3]
981 # Coordonnées du vecteur normal
982 vnor_x = caract_face_1[2][4]
983 vnor_y = caract_face_1[2][5]
984 vnor_z = caract_face_1[2][6]
985 # taille : une longueur caractéristique pour être certain de tout prendre
986 l_diag = self._calcul_lg_caract ( solide, n_recur )
988 if self._verbose_max:
989 print_tab (n_recur, "Taille englobante : ",taille)
991 # 2. Distance entre les deux faces
992 face_1 = caract_face_1[0]
993 face_2 = caract_face_2[0]
994 d_face_1_2 = GeomAlgoAPI_ShapeTools.minimalDistance(face_1, face_2)
995 if self._verbose_max:
996 print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
998 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
1000 #=========================== Fin de la méthode ==================================
1002 #=========================== Début de la méthode =================================
1004 def _cree_face_mediane_plane_1 ( self, solide, coo_c, vnor, taille, d_face_1_2, n_recur ):
1005 """Crée la face médiane entre deux autres - cas des surfaces planes
1007 Création des objets de construction et de la face médiane
1010 :solide: l'objet solide à traiter
1011 :coo_c: coordonnées du centre de la base
1012 :vnor: coordonnées du vecteur normal
1013 :taille: estimation de la taille de la future face
1014 :d_face_1_2: la distance entre les deux faces
1015 :n_recur: niveau de récursivité
1018 :face: la face médiane
1021 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
1022 blabla = "Dans {} :".format(nom_fonction)
1023 if self._verbose_max:
1024 print_tab (n_recur, blabla)
1025 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1026 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
1027 print_tab (n_recur, "Taille : ", taille)
1028 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1031 _, v_norm, plan = self._cree_centre_axe_plan ( coo_c, vnor, self.nom_solide, n_recur )
1033 # 2. Création de l'esquisse
1034 sketch = self._cree_face_mediane_plane_1_a ( plan, taille, n_recur )
1037 face = self._cree_face_mediane_plane_1_b ( solide, sketch, v_norm, d_face_1_2, n_recur )
1039 #print ("fin de {}".format(nom_fonction))
1043 #=========================== Fin de la méthode ==================================
1045 #=========================== Début de la méthode =================================
1047 def _cree_face_mediane_plane_1_a ( self, plan, taille, n_recur ):
1048 """Crée la face médiane entre deux autres - cas des surfaces planes - l'esquisse
1052 :taille: estimation de la taille de la future face
1053 :n_recur: niveau de récursivité
1059 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_a"
1060 blabla = "Dans {} :".format(nom_fonction)
1061 if self._verbose_max:
1062 print_tab (n_recur, blabla)
1063 print_tab (n_recur, "Plan : {}".format(plan.name()))
1064 print_tab (n_recur, "taille : {}".format(taille))
1066 sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1067 sketch.execute(True)
1069 ### Create SketchLine
1070 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1071 SketchLine_1.execute(True)
1073 ### Create SketchLine
1074 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1075 SketchLine_2.execute(True)
1077 ### Create SketchLine
1078 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1079 SketchLine_3.execute(True)
1081 ### Create SketchLine
1082 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1083 SketchLine_4.execute(True)
1087 nom_sketch = "{}_esquisse".format(self.nom_solide)
1088 exec_nom (sketch,nom_sketch)
1090 #print ("fin de {}".format(nom_fonction))
1094 #=========================== Fin de la méthode ==================================
1096 #=========================== Début de la méthode =================================
1098 def _cree_face_mediane_plane_1_b ( self, solide, sketch, v_norm, d_face_1_2, n_recur ):
1099 """Crée la face médiane entre deux autres - cas des surfaces planes
1101 Création de la face médiane
1104 :solide: l'objet solide à traiter
1106 :v_norm: vecteur normal
1107 :d_face_1_2: la distance entre les deux faces
1108 :n_recur: niveau de récursivité
1111 :face: la face médiane
1114 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_b"
1115 blabla = "Dans {} :".format(nom_fonction)
1116 if self._verbose_max:
1117 print_tab (n_recur, blabla)
1118 print_tab (n_recur, "Esquisse : ", sketch.name())
1119 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1121 # 1. Copie du solide pour gérer les intersections
1122 #Copy_1 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1123 Copy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1124 nom = "{}_Copy_1".format(self.nom_solide_aux)
1125 exec_nom (Copy_1,nom)
1126 if self._verbose_max:
1127 print_tab (n_recur, "Après addMultiTranslation Copy_1 de nom ", nom)
1128 nom_solide = Copy_1.result().name()
1131 Recover_1 = model.addRecover(self.part_doc, Copy_1, [solide])
1132 nom = "{}_Recover_1".format(self.nom_solide_aux)
1133 exec_nom (Recover_1,nom)
1134 if self._verbose_max:
1135 print_tab (n_recur, "Après addRecover Recover_1 de nom ", nom)
1137 # 2. Création d'une face ; on la translate d'une demi-épaisseur.
1138 for iaux in range(2):
1140 # 2.1. Création d'une face à partir du sketch et translation perpendiculaire au plan de la face
1141 # On essaie les 2 côtés alternativement car on ne sait pas lequel sera le bon
1143 d_trans = -0.5*d_face_1_2*float(2*iaux-1)
1145 face = self._cree_face_mediane_plane_2 ( sketch.name(), v_norm.name(), nom_solide, d_trans, iaux, n_recur )
1147 # 2.2. Si on est du bon côté, alors on intersecte la face avec le solide et c'est bon
1149 face = self._cree_face_mediane_plane_11 ( face, Recover_1, n_recur )
1152 # 2.3. Si l'intersection est vide, on crée une nouvelle copie du solide avant de tester l'autre côté
1154 if self._verbose_max:
1155 print_tab (n_recur, "L'intersection est vide. On essaie l'autre côté")
1157 ### Create LinearCopy
1158 #Copy_2 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1159 Copy_2 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", Recover_1.result().name())], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1160 nom = "{}_Copy_2".format(self.nom_solide_aux)
1161 exec_nom (Copy_2,nom)
1162 if self._verbose_max:
1163 print_tab (n_recur, "Après addMultiTranslation Copy_2 de nom ", nom)
1164 nom_solide = Copy_2.result().name()
1166 #print ("fin de {}".format(nom_fonction))
1170 #=========================== Fin de la méthode ==================================
1172 #=========================== Début de la méthode =================================
1174 def _cree_face_mediane_plane_11 ( self, face, Recover_1, n_recur ):
1175 """Crée la face médiane entre deux autres - cas des surfaces planes
1177 Création des objets de construction et de la face médiane
1180 :face: la face médiane
1181 :Recover_1: la récupératiuon du solide
1182 :n_recur: niveau de récursivité
1185 :face: la face médiane
1188 nom_fonction = __name__ + "/_cree_face_mediane_plane_11"
1189 blabla = "Dans {} :".format(nom_fonction)
1190 if self._verbose_max:
1191 print_tab (n_recur, blabla)
1192 print_tab (n_recur, "face : ", face.name())
1194 # Si on traite un objet solide unique, on le récupère
1195 if ( self.nom_solide_aux == self.objet_principal.name() ):
1196 if self._verbose_max:
1197 print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1198 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1199 nom = "{}_Recover_2".format(self.nom_solide_aux)
1200 exec_nom (Recover_2,nom)
1202 nb_inter = face.result().numberOfSubs()
1203 if self._verbose_max:
1204 print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1207 face = self._cree_face_mediane_plane_3 ( face )
1211 #=========================== Fin de la méthode ==================================
1213 #=========================== Début de la méthode =================================
1215 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, d_trans, icpt, n_recur ):
1216 """Crée la face médiane entre deux autres - cas des surfaces planes
1218 Intersection de la face avec le solide
1221 :nom_sketch: nom de l'esquisse
1222 :nom_normal: nom du vecteur normal
1223 :nom_solide: nom du solide à intersecter
1224 :d_trans: la distance de translation
1225 :icpt: numéro de la tentative
1228 :face: la face médiane
1231 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1232 blabla = "Dans {} :".format(nom_fonction)
1233 if self._verbose_max:
1234 print_tab (n_recur, blabla)
1235 print_tab (n_recur, "nom_sketch : ", nom_sketch)
1236 print_tab (n_recur, "nom_normal : ", nom_normal)
1237 print_tab (n_recur, "nom_solide : ", nom_solide)
1238 print_tab (n_recur, "d_trans : ", d_trans)
1240 # Création d'une face
1241 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1242 nom = "{}_Face_1_{}".format(self.nom_solide_aux,icpt)
1243 exec_nom (Face_1,nom)
1244 if self._verbose_max:
1245 print_tab (n_recur, "Après addFace pour Face_1 de nom ", nom)
1248 Translation_1 = model.addTranslation(self.part_doc, [model.selection("FACE", Face_1.result().name())], axis = model.selection("EDGE", nom_normal), distance = d_trans, keepSubResults = True)
1249 nom = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1250 exec_nom (Translation_1,nom)
1251 if self._verbose_max:
1252 print_tab (n_recur, "Après addTranslation pour Translation_1 de nom ", nom)
1253 Translation_1.result().setColor(85, 0, 255)
1255 # Intersection de cette face avec le solide initial
1256 face = self._creation_face_inter ( Translation_1.result().name(), nom_solide )
1260 #=========================== Fin de la méthode ==================================
1262 #=========================== Début de la méthode =================================
1264 def _cree_face_mediane_plane_3 ( self, face ):
1265 """Crée la face médiane entre deux autres - cas des surfaces planes
1267 Fusion des 2 intersections
1270 :face: la face médiane composée de plusieurs intersections
1273 :face_m: la face médiane
1276 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1277 blabla = "Dans {} :\n".format(nom_fonction)
1278 if self._verbose_max:
1282 # Nommage des sous-objets
1284 for iaux in range(face.result().numberOfSubs()):
1285 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1286 face.result().subResult(iaux).setName(nom)
1287 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1290 if self._verbose_max:
1291 print ("Fusion de {} faces.".format(len(l_fuse)))
1292 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1293 face_m.execute(True)
1297 #=========================== Fin de la méthode ==================================
1299 #=========================== Début de la méthode =================================
1301 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1302 """Crée la face médiane entre deux autres - cas des cylindres
1305 :solide: solide SHAPER à traiter
1306 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1307 :n_recur: niveau de récursivité
1310 :face: la face médiane
1313 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1314 blabla = "Dans {} :".format(nom_fonction)
1317 if self._verbose_max:
1318 print_tab (n_recur, blabla)
1319 print_tab (n_recur, "face_1 : ", caract_face_1)
1320 print_tab (n_recur, "face_2 : ", caract_face_2)
1322 # Caractéristiques des cylindres
1323 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 )
1325 # Contrôle de la validité de l'épaisseur
1326 erreur = self._verif_epaisseur ( epaisseur )
1328 # Création de la face, de couleur bleue si problème
1330 face = self._cree_face_mediane_cylindre_1 ( (coo_x, coo_y, coo_z), (axe_x, axe_y, axe_z), rayon, hauteur, n_recur )
1332 couleur_objet (solide, n_recur, coul_r=0, coul_g=0, coul_b=255, verbose=self._verbose_max)
1337 #=========================== Fin de la méthode ==================================
1339 #=========================== Début de la méthode =================================
1341 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1342 """Crée la face médiane entre deux autres - cas des cylindres
1344 Décodage des caractéristiques
1347 :solide: l'objet solide à traiter
1348 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1349 :n_recur: niveau de récursivité
1352 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1353 :axe_x, axe_y, axe_z: coordonnées de l'axe
1354 :rayon: rayon moyen entre les deux faces
1355 :hauteur: hauteur du cylindre
1356 :epaisseur: épaisseur de l'interface entre les deux faces
1359 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1360 blabla = "Dans {} :".format(nom_fonction)
1362 if self._verbose_max:
1363 print_tab (n_recur, blabla)
1364 print_tab (n_recur, "face_1 : ", caract_face_1)
1365 print_tab (n_recur, "face_2 : ", caract_face_2)
1367 # Coordonnées du centre de la base
1368 coo_x = caract_face_1[2][1]
1369 coo_y = caract_face_1[2][2]
1370 coo_z = caract_face_1[2][3]
1371 # Coordonnées de l'axe
1372 axe_x = caract_face_1[2][4]
1373 axe_y = caract_face_1[2][5]
1374 axe_z = caract_face_1[2][6]
1376 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1377 # Hauteur : une longueur caractéristique pour être certain de tout prendre
1378 l_diag = self._calcul_lg_caract ( solide, n_recur )
1379 hauteur = 10.*l_diag
1380 if self._verbose_max:
1381 print_tab (n_recur, "Hauteur englobante : ", hauteur)
1383 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1385 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1387 #=========================== Fin de la méthode ==================================
1389 #=========================== Début de la méthode =================================
1391 def _cree_face_mediane_cylindre_1 ( self, coo_c, v_axe, rayon, hauteur, n_recur ):
1392 """Crée la face médiane entre deux autres - cas des cylindres
1394 Création des objets temporaires et de la face externe du cylindre support
1397 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1398 :axe_x, axe_y, axe_z: coordonnées de l'axe
1399 :rayon: rayon moyen entre les deux faces
1400 :hauteur: hauteur du cylindre
1401 :n_recur: niveau de récursivité
1404 :face: la face médiane
1406 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1407 blabla = "Dans {} :\n".format(nom_fonction)
1409 # Les caractéristiques du cylindre à créer
1410 if self._verbose_max:
1411 print_tab (n_recur, blabla)
1412 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1413 print_tab (n_recur, "Axe : ({}, {}, {})".format(v_axe[0], v_axe[1], v_axe[2]))
1414 print_tab (n_recur, "Rayon : ", rayon)
1415 print_tab (n_recur, "Hauteur : ", hauteur)
1417 # 1. Création du point central
1418 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
1419 nom_centre = "{}_centre".format(self.nom_solide)
1420 exec_nom (centre,nom_centre)
1421 if self.fonction_0 is None:
1422 self.fonction_0 = centre
1424 # 2. Création du vecteur axial
1425 axe = model.addAxis(self.part_doc, v_axe[0], v_axe[1], v_axe[2])
1426 nom_axe = "{}_vecteur".format(self.nom_solide)
1427 exec_nom (axe,nom_axe)
1429 # 3. Création du cylindre en volume, de rayon médian
1430 Cylinder_1 = model.addCylinder(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon, hauteur)
1431 nom = "{}_Cylinder_1".format(self.nom_solide)
1432 exec_nom (Cylinder_1,nom)
1434 # 4. Création du cylindre en surface
1435 cylindre = self._creation_face_surface ( nom, "cylindre" )
1438 Translation_1 = model.addTranslation(self.part_doc, [model.selection("COMPOUND", cylindre.name())], axis = model.selection("EDGE", nom_axe), distance = -0.5*hauteur, keepSubResults = True)
1439 nom = "{}_Translation_1".format(self.nom_solide)
1440 exec_nom (Translation_1,nom)
1442 # 6. Intersection de la face cylindrique avec le solide initial
1443 face = self._creation_face_inter ( nom )
1447 #=========================== Fin de la méthode ==================================
1449 #=========================== Début de la méthode =================================
1451 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1452 """Crée la face médiane entre deux autres - cas des sphères
1455 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1456 :n_recur: niveau de récursivité
1459 :face: la face médiane
1462 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1463 blabla = "Dans {} :".format(nom_fonction)
1466 if self._verbose_max:
1467 print_tab (n_recur, blabla)
1468 print_tab (n_recur, "face_1 : ", caract_face_1)
1469 print_tab (n_recur, "face_2 : ", caract_face_2)
1471 # Caractéristiques des sphères
1472 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1474 # Contrôle de la validité de l'épaisseur
1475 erreur = self._verif_epaisseur ( epaisseur )
1477 # Création de la face
1479 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1485 #=========================== Fin de la méthode ==================================
1487 #=========================== Début de la méthode =================================
1489 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1490 """Crée la face médiane entre deux autres - cas des sphères
1492 Décodage des caractéristiques
1495 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1496 :n_recur: niveau de récursivité
1499 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1500 :rayon: rayon moyen entre les deux faces
1501 :epaisseur: épaisseur de l'interface entre les deux faces
1504 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1505 blabla = "Dans {} :".format(nom_fonction)
1508 if self._verbose_max:
1509 print_tab (n_recur, blabla)
1510 print_tab (n_recur, "face_1 : ", caract_face_1)
1511 print_tab (n_recur, "face_2 : ", caract_face_2)
1513 # Coordonnées du centre de la sphère
1514 coo_x = caract_face_1[2][1]
1515 coo_y = caract_face_1[2][2]
1516 coo_z = caract_face_1[2][3]
1518 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1520 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1522 return coo_x, coo_y, coo_z, rayon, epaisseur
1524 #=========================== Fin de la méthode ==================================
1526 #=========================== Début de la méthode =================================
1528 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1529 """Crée la face médiane entre deux autres - cas des sphères
1531 Création des objets de construction et de la face externe de la sphère support
1534 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1535 :rayon: rayon moyen entre les deux faces
1538 :face: la face externe de la sphère support
1541 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1542 blabla = "Dans {} :\n".format(nom_fonction)
1544 # Les caractéristiques de la sphère à créer
1545 if self._verbose_max:
1547 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1548 texte += "Rayon : {}".format(rayon)
1551 # 1. Création du point central
1552 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1553 nom_centre = "{}_centre".format(self.nom_solide)
1554 exec_nom (centre,nom_centre)
1555 if self.fonction_0 is None:
1556 self.fonction_0 = centre
1558 # 2. Création de la sphère en volume, de rayon médian
1559 Sphere_1 = model.addSphere(self.part_doc, model.selection("VERTEX", nom_centre), rayon)
1560 nom = "{}_Sphere_1".format(self.nom_solide)
1561 exec_nom (Sphere_1,nom)
1563 # 3. Création de la sphère en surface
1564 sphere = self._creation_face_surface ( nom, "sphere" )
1566 # 4. Intersection de la face sphérique avec le solide initial
1567 face = self._creation_face_inter ( sphere.name() )
1571 #=========================== Fin de la méthode ==================================
1573 #=========================== Début de la méthode =================================
1575 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1576 """Crée la face médiane entre deux autres - cas des tores
1579 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1580 :n_recur: niveau de récursivité
1583 :face: la face médiane
1586 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1587 blabla = "Dans {} :".format(nom_fonction)
1590 if self._verbose_max:
1591 print_tab (n_recur, blabla)
1592 print_tab (n_recur, "face_1 : ", caract_face_1)
1593 print_tab (n_recur, "face_2 : ", caract_face_2)
1595 # Caractéristiques des tores
1596 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 )
1598 # Contrôle de la validité de l'épaisseur (bidon)
1599 erreur = self._verif_epaisseur ( EP_MIN*10. )
1601 # Création de la face
1603 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1609 #=========================== Fin de la méthode ==================================
1611 #=========================== Début de la méthode =================================
1613 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1614 """Crée la face médiane entre deux autres - cas des tores
1616 Décodage des caractéristiques
1619 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1620 :n_recur: niveau de récursivité
1623 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1624 :axe_x, axe_y, axe_z: coordonnées de l'axe
1625 :rayon_1 : rayon principal
1626 :rayon_2 : rayon secondaire
1629 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1630 blabla = "Dans {} :".format(nom_fonction)
1633 if self._verbose_max:
1634 print_tab (n_recur, blabla)
1635 print_tab (n_recur, "face_1 : ", caract_face_1)
1636 print_tab (n_recur, "face_2 : ", caract_face_2)
1638 # Coordonnées du centre du tore
1639 coo_x = caract_face_1[2][1]
1640 coo_y = caract_face_1[2][2]
1641 coo_z = caract_face_1[2][3]
1642 # Coordonnées de l'axe
1643 axe_x = caract_face_1[2][4]
1644 axe_y = caract_face_1[2][5]
1645 axe_z = caract_face_1[2][6]
1647 rayon_1 = caract_face_2[2][7]
1648 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1650 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1652 #=========================== Fin de la méthode ==================================
1654 #=========================== Début de la méthode =================================
1656 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1657 """Crée la face médiane entre deux autres - cas des tores
1659 Création des objets de construction et de la face externe du tore support
1662 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1663 :axe_x, axe_y, axe_z: coordonnées de l'axe
1664 :rayon_1 : rayon principal
1665 :rayon_2 : rayon secondaire
1668 :face: la face externe du tore support
1671 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1672 blabla = "Dans {} :\n".format(nom_fonction)
1675 if self._verbose_max:
1677 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1678 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1679 texte += "Rayon principal : {}\n".format(rayon_1)
1680 texte += "Rayon secondaire : {}".format(rayon_2)
1683 # 1. Création du point central
1684 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1685 nom_centre = "{}_centre".format(self.nom_solide)
1686 exec_nom (centre,nom_centre)
1688 # 2. Création de l'axe
1689 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1690 nom_axe = "{}_axe".format(self.nom_solide)
1691 exec_nom (axe,nom_axe)
1693 # 3. Création du tore en volume, de rayon médian
1694 Tore_1 = model.addTorus(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon_1, rayon_2)
1695 nom = "{}_Tore_1".format(self.nom_solide)
1696 exec_nom (Tore_1,nom)
1698 # 4. Création du tore en surface
1699 tore = self._creation_face_surface ( nom, "tore" )
1701 # 5. Intersection de la face torique avec le solide initial
1702 face = self._creation_face_inter ( tore.name() )
1706 #=========================== Fin de la méthode ==================================
1708 #=========================== Début de la méthode =================================
1710 def _cree_face_mediane_cone ( self, caract_face_1, caract_face_2, n_recur ):
1711 """Crée la face médiane entre deux autres - cas des cônes
1714 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1715 :n_recur: niveau de récursivité
1718 :face: la face médiane
1721 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1722 blabla = "Dans {} :".format(nom_fonction)
1725 if self._verbose_max:
1726 print_tab (n_recur, blabla)
1727 print_tab (n_recur, "face_1 : ", caract_face_1)
1728 print_tab (n_recur, "face_2 : ", caract_face_2)
1730 # Caractéristiques des cônes
1731 coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur = self._cree_face_mediane_cone_0 ( caract_face_1, caract_face_2, n_recur )
1733 # Contrôle de la validité de l'épaisseur (bidon)
1734 erreur = self._verif_epaisseur ( EP_MIN*10. )
1736 # Création de la face
1738 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1744 #=========================== Fin de la méthode ==================================
1746 #=========================== Début de la méthode =================================
1748 def _cree_face_mediane_cone_0 ( self, caract_face_1, caract_face_2, n_recur ):
1749 """Crée la face médiane entre deux autres - cas des cônes
1751 Décodage des caractéristiques
1754 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1755 :n_recur: niveau de récursivité
1758 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1759 :axe_x, axe_y, axe_z: coordonnées de l'axe
1760 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1761 :hauteur: hauteur du cône
1764 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1765 blabla = "Dans {} :".format(nom_fonction)
1768 if self._verbose_max:
1769 print_tab (n_recur, blabla)
1770 print_tab (n_recur, "face_1 : ", caract_face_1)
1771 print_tab (n_recur, "face_2 : ", caract_face_2)
1773 # Coordonnées du centre de la base
1774 coo_x = caract_face_1[2][1]
1775 coo_y = caract_face_1[2][2]
1776 coo_z = caract_face_1[2][3]
1777 # Coordonnées de l'axe
1778 axe_x = caract_face_1[2][4]
1779 axe_y = caract_face_1[2][5]
1780 axe_z = caract_face_1[2][6]
1782 rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1783 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1785 hauteur = caract_face_1[2][9]
1788 if self._verbose_max:
1789 print_tab (n_recur, "coo_x : ", coo_x)
1790 print_tab (n_recur, "coo_y : ", coo_y)
1791 print_tab (n_recur, "coo_z : ", coo_z)
1792 print_tab (n_recur, "axe_x : ", axe_x)
1793 print_tab (n_recur, "axe_y : ", axe_y)
1794 print_tab (n_recur, "axe_z : ", axe_z)
1795 print_tab (n_recur, "rayon_1 : ", rayon_1)
1796 print_tab (n_recur, "rayon_2 : ", rayon_2)
1797 print_tab (n_recur, "hauteur : ", hauteur)
1799 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1801 #=========================== Fin de la méthode ==================================
1803 #=========================== Début de la méthode =================================
1805 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1806 """Crée la face médiane entre deux autres - cas des cônes
1808 Création des objets de construction et de la face externe du cône support
1811 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1812 :axe_x, axe_y, axe_z: coordonnées de l'axe
1813 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1814 :hauteur: hauteur du cône
1817 :face: la face externe du cône support
1819 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1820 blabla = "Dans {} :\n".format(nom_fonction)
1823 if self._verbose_max:
1825 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1826 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1827 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1828 texte += "Hauteur : {}".format(hauteur)
1831 # 1. Création du point central de la base, côté rayon_1
1832 centre_1 = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1833 nom_centre_1 = "{}_centre_1".format(self.nom_solide)
1834 exec_nom (centre_1,nom_centre_1)
1836 # 2. Création du point central, du côté de rayon_2
1837 centre_2 = model.addPoint(self.part_doc, coo_x+hauteur*axe_x, coo_y+hauteur*axe_y, coo_z+hauteur*axe_z)
1838 nom_centre_2 = "{}_centre_2".format(self.nom_solide)
1839 exec_nom (centre_2,nom_centre_2)
1841 # 3. Création de l'axe
1842 axe = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre_1), model.selection("VERTEX", nom_centre_2))
1843 nom_axe = "{}_axe".format(self.nom_solide)
1844 exec_nom (axe,nom_axe)
1846 # 4. Création du cône en volume, de rayon médian
1847 # 4.1. Calculs des rayons haut et bas, de sa hauteur et de la valeur de la translation
1848 rayon_b, rayon_s, hauteur_c, d_trans = self._cree_face_mediane_cone_2 ( rayon_1, rayon_2, hauteur )
1850 # 4.2. Création du grand cône
1851 Cone_1 = model.addCone(self.part_doc, model.selection("VERTEX", nom_centre_1), model.selection("EDGE", nom_axe), rayon_b, rayon_s, hauteur_c)
1852 nom_1 = "{}_Cone_1".format(self.nom_solide)
1853 exec_nom (Cone_1,nom_1)
1855 # 4.3. Translation pour superposer au cône de départ
1856 Translation_1 = model.addTranslation(self.part_doc, [model.selection("SOLID", nom_1)], axis = model.selection("EDGE", nom_axe), distance = d_trans, keepSubResults = True)
1857 nom_2 = "{}_Cone_1_trans".format(self.nom_solide)
1858 exec_nom (Translation_1,nom_2)
1860 # 5. Création du cône en surface
1861 nom = "{}/MF:Translated&{}".format(nom_2,nom_1)
1862 cone = self._creation_face_surface ( nom, "cone" )
1864 # 6. Intersection de la face conique avec le solide initial
1865 face = self._creation_face_inter ( cone.name() )
1869 #=========================== Fin de la méthode ==================================
1871 #=========================== Début de la méthode =================================
1873 def _cree_face_mediane_cone_2 ( self, rayon_1, rayon_2, hauteur ):
1874 """Crée la face médiane entre deux autres - cas des cônes
1876 Calcul des caractéristiques du cône enveloppant. Merci Thalès !
1877 Le coefficient multiplicateur est choisi pour être certain de tout prendre. On calcule la
1878 plus petite valeur et on ajoute arbitrairement 5.
1880 Remarque : on ne peut pas avoir un cône pointu car il est situé entre deux cônes donc il y a une épaisseur.
1883 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1884 :hauteur: hauteur du cône
1887 :rayon_b: rayon du cône - partie basse
1888 :rayon_s: rayon du cône - partie supérieure
1889 :hauteur_c: hauteur du cône
1890 :d_trans: distance de translation selon l'axe
1892 nom_fonction = __name__ + "/_cree_face_mediane_cone_2"
1893 blabla = "Dans {} :\n".format(nom_fonction)
1896 if self._verbose_max:
1898 texte += "rayon_1 : {}\n".format(rayon_1)
1899 texte += "rayon_2 : {}\n".format(rayon_2)
1900 texte += "Hauteur : {}".format(hauteur)
1905 # 1. Cas étroit en bas
1906 if ( rayon_1 < rayon_2 ):
1907 # Distance entre la pointe et la base
1908 coeff_a = rayon_1/(rayon_2-rayon_1)
1909 d_pointe_base = hauteur*coeff_a
1910 coeff = coeff_a + 1. + bonus
1911 if self._verbose_max:
1912 print ("Cas étroit en bas")
1913 print ("Distance de la pointe à la base : {}*{} = {}".format(coeff_a,hauteur,d_pointe_base))
1915 rayon_s = coeff*(rayon_2-rayon_1)
1916 d_trans = -d_pointe_base
1918 # 2. Cas étroit en haut
1919 # Manifestement cela n'arrive jamais une fois passé par du step et réimporté dans SHAPER
1921 # Distance entre la pointe et le haut
1922 coeff_a = rayon_1/(rayon_1-rayon_2)
1923 d_pointe_haut = hauteur*coeff_a
1924 coeff = coeff_a + 1. + bonus
1925 if self._verbose_max:
1926 print ("Cas étroit en haut")
1927 print ("Distance de la pointe et le haut : {}*{} = {}".format(coeff_a,hauteur,d_pointe_haut))
1928 rayon_b = coeff*(rayon_1-rayon_2)
1930 d_trans = -bonus*hauteur
1933 hauteur_c = coeff*hauteur
1935 if self._verbose_max:
1936 texte = "rayon_b : {}\n".format(rayon_b)
1937 texte += "rayon_s : {}\n".format(rayon_s)
1938 texte += "Translation : {}".format(d_trans)
1941 return rayon_b, rayon_s, hauteur_c, d_trans
1943 #=========================== Fin de la méthode ==================================
1945 #=========================== Début de la méthode =================================
1947 def _cree_centre_axe_plan ( self, coo_c, vect, prefixe, n_recur ):
1948 """Crée un centre, un axe, un plan
1951 :coo_c: coordonnées du centre de la base
1952 :vect: coordonnées du vecteur
1953 :prefix: prefixe du nom des objets
1954 :n_recur: niveau de récursivité
1958 :normal: vecteur normal
1962 nom_fonction = __name__ + "/_cree_centre_axe_plan"
1963 blabla = "Dans {} :".format(nom_fonction)
1964 if self._verbose_max:
1965 print_tab (n_recur, blabla)
1966 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1967 print_tab (n_recur, "Normale : ({}, {}, {})".format(vect[0], vect[1], vect[2]))
1969 # Création du point central
1970 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
1971 nom_centre = "{}_centre".format(prefixe)
1972 exec_nom (centre,nom_centre)
1973 if self.fonction_0 is None:
1974 self.fonction_0 = centre
1976 # Création du vecteur
1977 vecteur = model.addAxis(self.part_doc, vect[0], vect[1], vect[2])
1978 nom_vect = "{}_vecteur".format(prefixe)
1979 exec_nom (vecteur,nom_vect)
1981 # Création du plan perpendiculaire au vecteur normal
1982 plan = model.addPlane(self.part_doc, model.selection("EDGE", vecteur.name()), model.selection("VERTEX", centre.name()), True)
1983 nom_plan = "{}_plan".format(prefixe)
1984 exec_nom (plan,nom_plan)
1986 #print ("fin de {}".format(nom_fonction))
1988 return centre, vecteur, plan
1990 #=========================== Fin de la méthode ==================================
1992 #=========================== Début de la méthode =================================
1994 def _calcul_lg_caract ( self, objet, n_recur ):
1995 """Crée une longueur caractéristique de l'objet
1998 :objet: l'objet à traiter
1999 :n_recur: niveau de récursivité
2002 :l_caract: longueur caractéristique de l'objet
2005 nom_fonction = __name__ + "/_calcul_lg_caract"
2006 blabla = "Dans {} :".format(nom_fonction)
2008 if self._verbose_max:
2009 print_tab (n_recur, blabla)
2011 properties = model.getGeometryCalculation(self.part_doc,model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
2012 l_caract = properties[0]
2014 if self._verbose_max:
2015 print_tab (n_recur, "Longueur caractéristique : ", l_caract)
2019 #=========================== Fin de la méthode ==================================
2021 #=========================== Début de la méthode =================================
2023 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
2024 """Crée un volume de révolution
2027 :nom_sketch: nom de l'esquisse à révolutionner
2028 :nom_centre: nom du point associé au centre du volume de révolution
2029 :coo_x, coo_y, coo_z: coordonnées du centre du tore
2030 :axe_x, axe_y, axe_z: coordonnées de l'axe
2031 :rayon_1 : rayon principal
2032 :rayon_2 : rayon secondaire
2033 :nom_objet: nom de l'objet 2D créé
2036 nom_fonction = __name__ + "/_cree_revolution"
2037 blabla = "Dans {} :\n".format(nom_fonction)
2039 if self._verbose_max:
2041 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
2042 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
2045 # Création d'un point décalé par rapport au point central
2046 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
2047 nom_point = "{}_point".format(self.nom_solide)
2048 exec_nom (point,nom_point)
2050 # Création de l'axe de la rotation
2051 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
2052 nom_axe_r = "{}_axe_r".format(self.nom_solide)
2053 exec_nom (axe_r,nom_axe_r)
2055 # Création de l'objet complet
2056 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
2057 exec_nom (objet, nom_objet, (85, 0, 255))
2059 #=========================== Fin de la méthode ==================================
2061 #=========================== Début de la méthode =================================
2063 def _creation_face_surface ( self, nom_objet, suffixe ):
2064 """Crée la face qui est la surface externe d'un objet
2066 . Crée le groupe de la face externe
2067 . Transforme le groupe en face résultat
2070 :nom_objet: nom de l'objet 3D à traiter
2071 :suffixe: suffixe pour nommer l'objet 2D
2072 :nom_solide: nom du solide initial ; si None, on prend self.nom_solide_aux
2075 :objet_2d: l'objet 2D support de la face externe de l'objet 3D
2078 nom_fonction = __name__ + "/_creation_face_surface"
2079 blabla = "Dans {} :\n".format(nom_fonction)
2081 if self._verbose_max:
2084 # 1. Le groupe de la surface
2085 groupe = model.addGroup(self.part_doc, "Faces", [model.selection("FACE", "{}/Face_1".format(nom_objet))])
2086 nom = "{}_{}_groupe".format(self.nom_solide,suffixe)
2087 exec_nom (groupe, nom, (85, 0, 255))
2089 # 2. Création de la face en surface
2090 objet_2d = model.addGroupShape(self.part_doc, [model.selection("COMPOUND", nom)])
2091 nom = "{}_{}".format(self.nom_solide,suffixe)
2092 exec_nom (objet_2d, nom, (85, 0, 255))
2096 #=========================== Fin de la méthode ==================================
2098 #=========================== Début de la méthode =================================
2100 def _creation_face_inter ( self, nom_objet, nom_solide=None ):
2101 """Crée la face par intersection entre l'objet initial et une face complète
2103 . Repère la face principale de l'objet support
2104 . Réalise l'intersection avec le solide initial
2107 :nom_objet: nom de l'objet 2D créé
2108 :nom_solide: nom du solide initial ; si None, on prend self.nom_solide_aux
2111 :face: la face externe de l'objet support intersecté avec le solide initial
2114 nom_fonction = __name__ + "/_creation_face_inter"
2115 blabla = "Dans {} :\n".format(nom_fonction)
2117 if self._verbose_max:
2119 texte += "nom_objet = {}\n".format(nom_objet)
2120 texte += "nom_solide = {}".format(nom_solide)
2123 if nom_solide is None:
2124 nom_solide = self.nom_solide_aux
2126 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_objet)], keepSubResults = True)
2131 #=========================== Fin de la méthode ==================================
2133 #=========================== Début de la méthode =================================
2135 def face_mediane_solide (self, solide, n_recur=0):
2136 """Calcul de la face médiane pour un solide
2139 :solide: solide SHAPER à traiter
2140 :n_recur: niveau de récursivité
2143 :erreur: code d'erreur
2144 :message: message d'erreur
2147 nom_fonction = __name__ + "/face_mediane_solide"
2148 blabla = "Dans {} :".format(nom_fonction)
2150 if self._verbose_max:
2151 print_tab (n_recur, blabla, saut_av=True)
2153 print_tab (n_recur, "Traitement du solide ", solide.name())
2162 # 2. Calcul des caractéristiques géométriques des faces
2164 tb_caract = self._calcul_caract_faces ( solide, n_recur )
2166 # 3. Tri des faces en fonction de leurs caractéristiques géométriques
2168 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract, n_recur )
2172 # 4. Création de la face médiane
2174 erreur, face = self._cree_face_mediane ( solide, caract_face_1, caract_face_2, n_recur )
2175 if ( erreur or ( face is None ) ):
2178 # 6. Exportation step
2180 if self._export_step:
2181 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2182 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2183 export.execute(True)
2190 if ( erreur and self._verbose_max ):
2191 print (blabla, message)
2193 return erreur, message
2195 #=========================== Fin de la méthode ==================================
2197 #=========================== Début de la méthode =================================
2199 def _traitement_objet (self, solide, n_recur=0):
2200 """Traitement d'un objet
2203 :solide: solide SHAPER à traiter
2204 :n_recur: niveau de récursivité
2207 :erreur: code d'erreur
2208 :message: message d'erreur
2211 nom_fonction = __name__ + "/_traitement_objet"
2212 blabla = "Dans {} :".format(nom_fonction)
2214 if self._verbose_max:
2215 print_tab (n_recur, blabla, saut_av=True)
2216 texte = "solide = {} ".format(solide.name())
2217 print_tab (n_recur, texte, solide)
2219 # 1. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2220 # Attention à ne pas recréer le répertoire à chaque fois
2221 if self._export_step:
2223 if self.rep_step is None:
2225 if self._verbose_max:
2226 print_tab (n_recur, "Préparation de l'export STEP")
2228 if self.ficcao is None:
2229 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2231 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2232 if os.path.isdir(self.rep_step):
2233 l_aux = os.listdir(self.rep_step)
2234 for nomfic in l_aux:
2235 os.remove(os.path.join(self.rep_step,nomfic))
2237 os.mkdir(self.rep_step)
2239 if self._verbose_max:
2240 print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2242 # 2. Calcul réel de la face médiane
2244 erreur, message = self.face_mediane_solide (solide, n_recur)
2246 return erreur, message
2248 #=========================== Fin de la méthode ==================================
2250 #=========================== Début de la méthode =================================
2252 def surf_fic_cao (self, ficcao, nom_objet=None):
2253 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2256 :ficcao: fichier de l'objet à traiter
2257 :nom_objet: un nom à donner à l'objet à traiter
2260 :erreur: code d'erreur
2261 :message: message d'erreur
2264 nom_fonction = __name__ + "/surf_fic_cao"
2265 blabla = "Dans {} :".format(nom_fonction)
2267 if self._verbose_max:
2277 if self.affiche_aide_globale:
2280 # 1. Définition de la pièce
2282 self.part_doc = model.activeDocument()
2283 if ( self.part_doc.kind() == "PartSet" ):
2284 part = model.addPart(self.part_doc)
2285 self.part_doc = part.document()
2287 # 2. Import de la CAO
2289 self.ficcao = ficcao
2290 print ("Traitement du fichier {}".format(ficcao))
2292 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2296 # 3. Calcul des surfaces
2298 erreur, message = self.surf_objet_shaper ( objet )
2305 if ( erreur and self._verbose_max ):
2306 print (blabla, message)
2308 return erreur, message
2310 #=========================== Fin de la méthode ==================================
2312 #=========================== Début de la méthode =================================
2314 def surf_objet_shaper (self, objet):
2315 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2318 :objet: objet à traiter
2321 :erreur: code d'erreur
2322 :message: message d'erreur
2325 nom_fonction = __name__ + "/surf_objet_shaper"
2326 blabla = "Dans {} :".format(nom_fonction)
2328 if self._verbose_max:
2336 if self.affiche_aide_globale:
2339 # 1. Acquisition de la liste des noms des sous-objets solides
2341 self.d_statut_so = dict()
2342 self.l_noms_so = list()
2343 self.l_faces_m = list()
2345 _ = self._nom_sous_objets (objet, True)
2346 if self._verbose_max:
2347 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2349 # 2. Les faces médianes
2351 erreur, message = self._surf_objet_shaper_0 ( objet )
2355 # 3. Gestion des faces créées
2357 self._surf_objet_shaper_1 ( )
2359 # 4. Futur message pour le résultat
2361 if ( self._export_step and not erreur ):
2362 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2366 return erreur, message
2368 #=========================== Fin de la méthode ==================================
2370 #=========================== Début de la méthode =================================
2372 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2373 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2376 :objet: objet à traiter
2377 :n_recur: niveau de récursivité
2380 :erreur: code d'erreur
2381 :message: message d'erreur
2384 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2385 blabla = "Dans {} :".format(nom_fonction)
2387 if self._verbose_max:
2388 print_tab (n_recur, blabla)
2389 print_tab (n_recur, "n_recur = ", n_recur)
2396 # 1. Au premier passage, il faut récupérer la pièce SHAPER et garder la référence au résultat principal
2398 if ( n_recur == 0 ):
2399 self.part_doc = model.activeDocument()
2400 objet_0 = objet.result()
2401 self.objet_principal = objet_0
2402 objet_bis = objet.defaultResult().shape()
2403 if self._verbose_max:
2404 print_tab (0, "Examen de l'objet initial ", objet.result().name(), saut_av=True)
2405 print_tab (0, "Type python : ", type(objet))
2406 print_tab (0, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2409 if self._verbose_max:
2410 print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2411 print_tab (n_recur, "Type python : ", type(objet))
2412 print_tab (n_recur, "shapeType : ", objet.shapeType())
2414 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2416 nb_sub_results = objet_0.numberOfSubs()
2418 if self._verbose_max:
2419 print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType(), saut_av=True)
2420 print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2422 for n_sobj in range(nb_sub_results):
2424 # 2.1. Exploration récursive de l'arborescence
2426 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2433 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2435 if ( objet_0.shapeType() == "SOLID" ):
2436 erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2440 # 3. Futur message pour le résultat
2442 if self._export_step:
2443 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2447 return erreur, message
2449 #=========================== Fin de la méthode ==================================
2451 #=========================== Début de la méthode =================================
2453 def _surf_objet_shaper_1 (self, n_recur=0):
2454 """Gestion des surfaces médianes créées
2457 :n_recur: niveau de récursivité
2460 :erreur: code d'erreur
2461 :message: message d'erreur
2464 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2465 blabla = "Dans {} :\n".format(nom_fonction)
2467 if self._verbose_max:
2468 print_tab (n_recur, blabla)
2470 # 1. Informations sur les faces à problème
2472 if self.faces_pb_nb:
2473 if ( self.faces_pb_nb == 1 ):
2474 texte = "1 face pose"
2476 texte = "{} faces posent".format(self.faces_pb_nb)
2477 print_tab (n_recur, "{} problème.".format(texte), self.faces_pb_msg, saut_av=True)
2479 # 2. Si plus d'une face a été créée
2480 if ( len(self.l_faces_m) > 1 ):
2482 # 2.1. Partition du paquet de faces
2484 if self._verbose_max:
2485 print_tab (n_recur, "Partitionnnement des faces créées.")
2487 # 2.1.1. Pour une raison mystérieuse, il faut commencer par les faces entières, puis mettre les sous-faces éventuelles
2489 for (face,_) in self.l_faces_m:
2490 if not face.result().numberOfSubs():
2491 d_faces[face.name()] = [face.name()]
2492 for (face,_) in self.l_faces_m:
2493 nb_sub_results = face.result().numberOfSubs()
2496 for n_sobj in range(nb_sub_results):
2497 laux.append(face.result().subResult(n_sobj).name())
2498 d_faces[face.name()] = laux
2501 for _, laux in d_faces.items():
2502 for s_face_n in laux:
2503 l_objets.append(model.selection("FACE", s_face_n))
2505 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2506 nom = "{}_M".format(self.objet_principal.name())
2507 exec_nom (Partition_1,nom)
2510 for face_n, laux in d_faces.items():
2511 Partition_1.result().subResult(iaux).setName("{}".format(face_n))
2512 if ( len(laux) > 1 ):
2513 for jaux, s_face_n in enumerate(laux):
2514 Partition_1.result().subResult(iaux).subResult(jaux).setName("{}_M".format(s_face_n))
2516 couleur_objet (Partition_1, n_recur, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
2518 # 2.2. Récupération des faces individuelles
2520 if self._verbose_max:
2521 print_tab (n_recur, "Récupération des faces individuelles.")
2524 for iaux, (face,_) in enumerate(self.l_faces_m):
2525 l_objets.append(face.result())
2527 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2528 exec_nom (Recover_1)
2529 for iaux, (face,_) in enumerate(self.l_faces_m):
2530 Recover_1.results()[iaux].setName("{}".format(face.name()))
2531 Recover_1.results()[iaux].setColor(0, 170, 0)
2532 nb_sub_results = Recover_1.results()[iaux].numberOfSubs()
2533 for n_sobj in range(nb_sub_results):
2534 Recover_1.results()[iaux].subResult(n_sobj).setName("{}_{}".format(face.name(),n_sobj))
2535 Recover_1.results()[iaux].subResult(n_sobj).setColor(0, 170, 0)
2537 # 3. Mise en dossier
2539 if self._verbose_max:
2540 print_tab (n_recur, "Mise en dossier.")
2542 for (face,fonction_0) in self.l_faces_m:
2543 if fonction_0 is not None:
2544 nom = face.name()[:-2]
2545 if self._verbose_max:
2546 print ( "Dossier {} de {} à {}".format(nom,fonction_0.name(),face.name()))
2547 dossier = model.addFolder(self.part_doc, fonction_0, face)
2548 dossier.setName(nom)
2550 if ( len(self.l_faces_m) > 1 ):
2552 nom = self.objet_principal.name()
2553 if self._verbose_max:
2554 print ( "Dossier {} de {} à {}".format(nom,Partition_1.name(),Recover_1.name()))
2555 dossier = model.addFolder(self.part_doc, Partition_1, Recover_1)
2556 dossier.setName(nom)
2558 #=========================== Fin de la méthode ==================================
2560 #=========================== Début de la méthode =================================
2562 def surf_solide_shaper (self, solide, n_recur):
2563 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2566 :solide: solide SHAPER à traiter
2567 :n_recur: numéro de la récurrence
2570 :erreur: code d'erreur
2571 :message: message d'erreur
2574 nom_fonction = __name__ + "/surf_solide_shaper"
2575 blabla = "Dans {} :".format(nom_fonction)
2577 if self._verbose_max:
2578 print_tab (n_recur, blabla, saut_av=True)
2585 self.nom_solide = solide.name()
2586 if self._verbose_max:
2587 print_tab (n_recur, "solide : ", self.nom_solide)
2589 # 1. Isolement du solide
2590 solide_aux, recover = self._isole_solide ( solide, n_recur )
2592 # 2. Traitement de l'objet correspondant
2593 erreur, message = self._traitement_objet ( solide_aux, n_recur=n_recur )
2595 if ( erreur and self._verbose_max ):
2596 print (blabla, message)
2598 # 3. Neutralisation des erreurs dues à l'épaisseur
2599 if ( erreur in (-2,-1,2) ):
2605 # 4. Mise en forme de l'objet principal récupéré
2606 if ( recover is not None ):
2607 _ = self._nom_sous_objets (recover, False)
2611 return erreur, message
2613 #=========================== Fin de la méthode ==================================
2615 #========================== Fin de la classe ====================================