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.27"
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 : ")
741 for iaux, caract in enumerate(tb_caract):
742 print_tab (n_recur, "Face {} : ".format(iaux), caract)
744 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
745 if self._verbose_max:
747 print_tab (n_recur, "tb_caract trié de la plus petite à la plus grande surface :")
748 for caract in tb_caract_1:
749 print_tab (n_recur, "", caract)
752 if self._verbose_max:
753 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
754 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
757 # 2. La surface suivante doit être différente, sinon ce n'est pas un solide mince
758 if ( len(tb_caract) > 2 ):
760 if self._verbose_max:
761 texte += "\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
763 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
764 if ( ecart < self._epsilon ):
765 message = "\nSolide '{}'\n".format(self.nom_solide)
766 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
767 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
768 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
769 if self._verbose_max:
770 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
771 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
772 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
774 self.d_statut_so[self.nom_solide] = -1
775 self.faces_pb_nb += 1
776 self.faces_pb_msg += message
778 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
780 #=========================== Fin de la méthode ==================================
782 #=========================== Début de la méthode =================================
784 def _verif_epaisseur ( self, epaisseur ):
785 """Contrôle de la validité de l'épaisseur
788 :epaisseur: épaisseur du solide
791 nom_fonction = __name__ + "/_verif_epaisseur"
792 blabla = "Dans {} :\n".format(nom_fonction)
794 if self._verbose_max:
796 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
797 texte += ". EP_MIN : {}".format(EP_MIN)
800 if ( epaisseur <= EP_MIN ):
801 message = "\nSolide '{}'\n".format(self.nom_solide)
802 message += ". Epaisseur : {}\n".format(epaisseur)
803 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
804 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
806 self.d_statut_so[self.nom_solide] = 2
807 self.faces_pb_nb += 1
808 self.faces_pb_msg += message
812 #print ("erreur = {}".format(erreur))
816 #=========================== Fin de la méthode ==================================
818 #=========================== Début de la méthode =================================
820 def _cree_face_mediane ( self, solide, caract_face_1, caract_face_2, tb_caract, n_recur ):
821 """Crée la face médiane entre deux autres
824 :solide: solide SHAPER à traiter
825 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
826 :tb_caract: tableau des caractéristiques géométriques des faces
827 :n_recur: niveau de récursivité
830 :face: la face médiane créée
833 nom_fonction = __name__ + "/_cree_face_mediane"
834 blabla = "Dans {} :".format(nom_fonction)
836 if self._verbose_max:
837 print_tab (n_recur, blabla)
838 print_tab (n_recur, "face_1 : " ,caract_face_1)
839 print_tab (n_recur, "face_2 : " ,caract_face_2)
844 # 1. Forme de la face
845 forme = caract_face_1[2][0]
847 # 2. Traitement selon la forme de la face
849 if forme in ( "Disk", "Plane", "Rectangle" ):
850 erreur, face = self._cree_face_mediane_plane ( solide, caract_face_1, caract_face_2, tb_caract, n_recur )
852 # 2.2. Face cylindrique
853 elif ( forme == "Cylinder" ):
854 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
856 # 2.3. Face sphérique
857 elif ( forme == "Sphere" ):
858 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
861 elif ( forme == "Torus" ):
862 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
865 elif ( forme == "Cone" ):
866 erreur, face = self._cree_face_mediane_cone ( caract_face_1, caract_face_2, n_recur )
868 # 2.N. Face de forme inconnue
870 message = "\nSolide '{}'\n".format(self.nom_solide)
871 message += "sa face la plus grande est de forme : {}\n".format(forme)
872 message += "==> Impossible de créer la face médiane.\n"
874 self.d_statut_so[self.nom_solide] = -2
875 self.faces_pb_nb += 1
876 self.faces_pb_msg += message
878 # 3. Gestion de la face produite
881 self._cree_face_mediane_0 ( face, n_recur )
885 #=========================== Fin de la méthode ==================================
887 #=========================== Début de la méthode =================================
889 def _cree_face_mediane_0 ( self, face, n_recur ):
890 """Gestion de la face médiane créée entre deux autres
893 :face: la face médiane créée
894 :n_recur: niveau de récursivité
897 nom_fonction = __name__ + "/_cree_face_mediane_0"
898 blabla = "Dans {} :".format(nom_fonction)
900 if self._verbose_max:
901 print_tab (n_recur, blabla)
904 nom_face = self.nom_solide+"_M"
905 if self._verbose_max:
906 print_tab (n_recur,"Nom de la face créée : ", nom_face)
907 #if ( self.nom_solide_aux != self.objet_principal.name() ):
909 nommage (face, nom_face)
911 # 2. Mémorisation de la face et de la fonction initiale
912 self.l_faces_m.append((face, self.fonction_0))
914 # 3. Couleur verte pour la face
915 couleur_objet (face, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
917 # 4. Changement de statut pour le solide
918 self.d_statut_so[self.nom_solide] = 1
920 #=========================== Fin de la méthode ==================================
922 #=========================== Début de la méthode =================================
924 def _cree_face_mediane_plane ( self, solide, caract_face_1, caract_face_2, tb_caract, n_recur ):
925 """Crée la face médiane entre deux autres - cas des surfaces planes
928 :solide: l'objet solide à traiter
929 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
930 :tb_caract: tableau des caractéristiques géométriques des faces
931 :n_recur: niveau de récursivité
934 :face: la face médiane
937 nom_fonction = __name__ + "/_cree_face_mediane_plane"
938 blabla = "Dans {} :".format(nom_fonction)
939 if self._verbose_max:
940 print_tab (n_recur, blabla)
942 # Caractéristiques des surfaces
943 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, tb_caract, n_recur )
945 # Contrôle de la validité de l'épaisseur
946 erreur = self._verif_epaisseur ( d_face_1_2 )
948 # Création de la face
950 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 )
956 #=========================== Fin de la méthode ==================================
958 #=========================== Début de la méthode =================================
960 def _cree_face_mediane_plane_0 ( self, solide, caract_face_1, caract_face_2, tb_caract, n_recur ):
961 """Crée la face médiane entre deux autres - cas des surfaces planes
963 Décodage des caractéristiques
966 :solide: l'objet solide à traiter
967 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
968 :tb_caract: tableau des caractéristiques géométriques des faces
969 :n_recur: niveau de récursivité
972 :coo_x, coo_y, coo_z: coordonnées du centre de la base
973 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
974 :taille: estimation de la taille de la future face
975 :d_face_1_2: la distance entre les deux faces
978 nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
979 blabla = "Dans {} :".format(nom_fonction)
981 if self._verbose_max:
982 print_tab (n_recur, blabla)
983 print_tab (n_recur, "caract_face_1 : ", caract_face_1)
984 print_tab (n_recur, "caract_face_2 : ", caract_face_2)
986 # 1. Caractéristiques de la base
987 # Coordonnées du centre de la base
988 coo_x = caract_face_1[2][1]
989 coo_y = caract_face_1[2][2]
990 coo_z = caract_face_1[2][3]
991 # Coordonnées du vecteur normal
992 vnor_x = caract_face_1[2][4]
993 vnor_y = caract_face_1[2][5]
994 vnor_z = caract_face_1[2][6]
998 # taille : une longueur caractéristique pour être certain de tout prendre
999 l_diag = self._calcul_lg_caract_0 ( solide, tb_caract, n_recur )
1001 if self._verbose_max:
1002 print_tab (n_recur, "Taille englobante : ", taille)
1004 # 3. Distance entre les deux faces
1005 face_1 = caract_face_1[0]
1006 face_2 = caract_face_2[0]
1007 d_face_1_2 = GeomAlgoAPI_ShapeTools.minimalDistance(face_1, face_2)
1008 if self._verbose_max:
1009 print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
1011 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
1013 #=========================== Fin de la méthode ==================================
1015 #=========================== Début de la méthode =================================
1017 def _cree_face_mediane_plane_1 ( self, solide, coo_c, vnor, taille, d_face_1_2, n_recur ):
1018 """Crée la face médiane entre deux autres - cas des surfaces planes
1020 Création des objets de construction et de la face médiane
1023 :solide: l'objet solide à traiter
1024 :coo_c: coordonnées du centre de la base
1025 :vnor: coordonnées du vecteur normal
1026 :taille: estimation de la taille de la future face
1027 :d_face_1_2: la distance entre les deux faces
1028 :n_recur: niveau de récursivité
1031 :face: la face médiane
1034 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
1035 blabla = "Dans {} :".format(nom_fonction)
1036 if self._verbose_max:
1037 print_tab (n_recur, blabla)
1038 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1039 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
1040 print_tab (n_recur, "Taille : ", taille)
1041 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1044 _, v_norm, plan = self._cree_centre_axe_plan ( coo_c, vnor, self.nom_solide, n_recur )
1046 # 2. Création de l'esquisse
1047 sketch = self._cree_face_mediane_plane_1_a ( plan, taille, n_recur )
1050 face = self._cree_face_mediane_plane_1_b ( solide, sketch, v_norm, d_face_1_2, n_recur )
1052 #print ("fin de {}".format(nom_fonction))
1056 #=========================== Fin de la méthode ==================================
1058 #=========================== Début de la méthode =================================
1060 def _cree_face_mediane_plane_1_a ( self, plan, taille, n_recur ):
1061 """Crée la face médiane entre deux autres - cas des surfaces planes - l'esquisse
1065 :taille: estimation de la taille de la future face
1066 :n_recur: niveau de récursivité
1072 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_a"
1073 blabla = "Dans {} :".format(nom_fonction)
1074 if self._verbose_max:
1075 print_tab (n_recur, blabla)
1076 print_tab (n_recur, "Plan : {}".format(plan.name()))
1077 print_tab (n_recur, "taille : {}".format(taille))
1079 sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1080 sketch.execute(True)
1082 ### Create SketchLine
1083 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1084 SketchLine_1.execute(True)
1086 ### Create SketchLine
1087 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1088 SketchLine_2.execute(True)
1090 ### Create SketchLine
1091 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1092 SketchLine_3.execute(True)
1094 ### Create SketchLine
1095 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1096 SketchLine_4.execute(True)
1100 nom_sketch = "{}_esquisse".format(self.nom_solide)
1101 exec_nom (sketch,nom_sketch)
1103 #print ("fin de {}".format(nom_fonction))
1107 #=========================== Fin de la méthode ==================================
1109 #=========================== Début de la méthode =================================
1111 def _cree_face_mediane_plane_1_b ( self, solide, sketch, v_norm, d_face_1_2, n_recur ):
1112 """Crée la face médiane entre deux autres - cas des surfaces planes
1114 Création de la face médiane
1117 :solide: l'objet solide à traiter
1119 :v_norm: vecteur normal
1120 :d_face_1_2: la distance entre les deux faces
1121 :n_recur: niveau de récursivité
1124 :face: la face médiane
1127 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_b"
1128 blabla = "Dans {} :".format(nom_fonction)
1129 if self._verbose_max:
1130 print_tab (n_recur, blabla)
1131 print_tab (n_recur, "Esquisse : ", sketch.name())
1132 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1134 # 1. Copie du solide pour gérer les intersections
1135 #Copy_1 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1136 Copy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1137 nom = "{}_Copy_1".format(self.nom_solide_aux)
1138 exec_nom (Copy_1,nom)
1139 if self._verbose_max:
1140 print_tab (n_recur, "Après addMultiTranslation Copy_1 de nom ", nom)
1141 nom_solide = Copy_1.result().name()
1144 Recover_1 = model.addRecover(self.part_doc, Copy_1, [solide])
1145 nom = "{}_Recover_1".format(self.nom_solide_aux)
1146 exec_nom (Recover_1,nom)
1147 if self._verbose_max:
1148 print_tab (n_recur, "Après addRecover Recover_1 de nom ", nom)
1150 # 2. Création d'une face ; on la translate d'une demi-épaisseur.
1151 for iaux in range(2):
1153 # 2.1. Création d'une face à partir du sketch et translation perpendiculaire au plan de la face
1154 # On essaie les 2 côtés alternativement car on ne sait pas lequel sera le bon
1156 d_trans = -0.5*d_face_1_2*float(2*iaux-1)
1158 face = self._cree_face_mediane_plane_2 ( sketch.name(), v_norm.name(), nom_solide, d_trans, iaux, n_recur )
1160 # 2.2. Si on est du bon côté, alors on intersecte la face avec le solide et c'est bon
1162 face = self._cree_face_mediane_plane_11 ( face, Recover_1, n_recur )
1165 # 2.3. Si l'intersection est vide, on crée une nouvelle copie du solide avant de tester l'autre côté
1167 if self._verbose_max:
1168 print_tab (n_recur, "L'intersection est vide. On essaie l'autre côté")
1170 ### Create LinearCopy
1171 #Copy_2 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1172 Copy_2 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", Recover_1.result().name())], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1173 nom = "{}_Copy_2".format(self.nom_solide_aux)
1174 exec_nom (Copy_2,nom)
1175 if self._verbose_max:
1176 print_tab (n_recur, "Après addMultiTranslation Copy_2 de nom ", nom)
1177 nom_solide = Copy_2.result().name()
1179 #print ("fin de {}".format(nom_fonction))
1183 #=========================== Fin de la méthode ==================================
1185 #=========================== Début de la méthode =================================
1187 def _cree_face_mediane_plane_11 ( self, face, Recover_1, n_recur ):
1188 """Crée la face médiane entre deux autres - cas des surfaces planes
1190 Création des objets de construction et de la face médiane
1193 :face: la face médiane
1194 :Recover_1: la récupératiuon du solide
1195 :n_recur: niveau de récursivité
1198 :face: la face médiane
1201 nom_fonction = __name__ + "/_cree_face_mediane_plane_11"
1202 blabla = "Dans {} :".format(nom_fonction)
1203 if self._verbose_max:
1204 print_tab (n_recur, blabla)
1205 print_tab (n_recur, "face : ", face.name())
1207 # Si on traite un objet solide unique, on le récupère
1208 if ( self.nom_solide_aux == self.objet_principal.name() ):
1209 if self._verbose_max:
1210 print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1211 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1212 nom = "{}_Recover_2".format(self.nom_solide_aux)
1213 exec_nom (Recover_2,nom)
1215 nb_inter = face.result().numberOfSubs()
1216 if self._verbose_max:
1217 print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1220 face = self._cree_face_mediane_plane_3 ( face )
1224 #=========================== Fin de la méthode ==================================
1226 #=========================== Début de la méthode =================================
1228 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, d_trans, icpt, n_recur ):
1229 """Crée la face médiane entre deux autres - cas des surfaces planes
1231 Intersection de la face avec le solide
1234 :nom_sketch: nom de l'esquisse
1235 :nom_normal: nom du vecteur normal
1236 :nom_solide: nom du solide à intersecter
1237 :d_trans: la distance de translation
1238 :icpt: numéro de la tentative
1241 :face: la face médiane
1244 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1245 blabla = "Dans {} :".format(nom_fonction)
1246 if self._verbose_max:
1247 print_tab (n_recur, blabla)
1248 print_tab (n_recur, "nom_sketch : ", nom_sketch)
1249 print_tab (n_recur, "nom_normal : ", nom_normal)
1250 print_tab (n_recur, "nom_solide : ", nom_solide)
1251 print_tab (n_recur, "d_trans : ", d_trans)
1253 # Création d'une face
1254 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1255 nom = "{}_Face_1_{}".format(self.nom_solide_aux,icpt)
1256 exec_nom (Face_1,nom)
1257 if self._verbose_max:
1258 print_tab (n_recur, "Après addFace pour Face_1 de nom ", nom)
1261 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)
1262 nom = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1263 exec_nom (Translation_1,nom)
1264 if self._verbose_max:
1265 print_tab (n_recur, "Après addTranslation pour Translation_1 de nom ", nom)
1266 Translation_1.result().setColor(85, 0, 255)
1268 # Intersection de cette face avec le solide initial
1269 face = self._creation_face_inter ( Translation_1.result().name(), nom_solide )
1273 #=========================== Fin de la méthode ==================================
1275 #=========================== Début de la méthode =================================
1277 def _cree_face_mediane_plane_3 ( self, face ):
1278 """Crée la face médiane entre deux autres - cas des surfaces planes
1280 Fusion des 2 intersections
1283 :face: la face médiane composée de plusieurs intersections
1286 :face_m: la face médiane
1289 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1290 blabla = "Dans {} :\n".format(nom_fonction)
1291 if self._verbose_max:
1295 # Nommage des sous-objets
1297 for iaux in range(face.result().numberOfSubs()):
1298 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1299 face.result().subResult(iaux).setName(nom)
1300 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1303 if self._verbose_max:
1304 print ("Fusion de {} faces.".format(len(l_fuse)))
1305 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1306 face_m.execute(True)
1310 #=========================== Fin de la méthode ==================================
1312 #=========================== Début de la méthode =================================
1314 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1315 """Crée la face médiane entre deux autres - cas des cylindres
1318 :solide: solide SHAPER à traiter
1319 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1320 :n_recur: niveau de récursivité
1323 :face: la face médiane
1326 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1327 blabla = "Dans {} :".format(nom_fonction)
1330 if self._verbose_max:
1331 print_tab (n_recur, blabla)
1332 print_tab (n_recur, "face_1 : ", caract_face_1)
1333 print_tab (n_recur, "face_2 : ", caract_face_2)
1335 # Caractéristiques des cylindres
1336 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 )
1338 # Contrôle de la validité de l'épaisseur
1339 erreur = self._verif_epaisseur ( epaisseur )
1341 # Création de la face, de couleur bleue si problème
1343 face = self._cree_face_mediane_cylindre_1 ( (coo_x, coo_y, coo_z), (axe_x, axe_y, axe_z), rayon, hauteur, n_recur )
1345 couleur_objet (solide, n_recur, coul_r=0, coul_g=0, coul_b=255, verbose=self._verbose_max)
1350 #=========================== Fin de la méthode ==================================
1352 #=========================== Début de la méthode =================================
1354 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1355 """Crée la face médiane entre deux autres - cas des cylindres
1357 Décodage des caractéristiques
1360 :solide: l'objet solide à traiter
1361 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1362 :n_recur: niveau de récursivité
1365 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1366 :axe_x, axe_y, axe_z: coordonnées de l'axe
1367 :rayon: rayon moyen entre les deux faces
1368 :hauteur: hauteur du cylindre
1369 :epaisseur: épaisseur de l'interface entre les deux faces
1372 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1373 blabla = "Dans {} :".format(nom_fonction)
1375 if self._verbose_max:
1376 print_tab (n_recur, blabla)
1377 print_tab (n_recur, "face_1 : ", caract_face_1)
1378 print_tab (n_recur, "face_2 : ", caract_face_2)
1380 # Coordonnées du centre de la base
1381 coo_x = caract_face_1[2][1]
1382 coo_y = caract_face_1[2][2]
1383 coo_z = caract_face_1[2][3]
1384 # Coordonnées de l'axe
1385 axe_x = caract_face_1[2][4]
1386 axe_y = caract_face_1[2][5]
1387 axe_z = caract_face_1[2][6]
1389 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1390 # Hauteur : une longueur caractéristique pour être certain de tout prendre
1391 l_diag = self._calcul_lg_caract_1 ( solide, n_recur )
1392 hauteur = 10.*l_diag
1393 if self._verbose_max:
1394 print_tab (n_recur, "Hauteur englobante : ", hauteur)
1396 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1398 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1400 #=========================== Fin de la méthode ==================================
1402 #=========================== Début de la méthode =================================
1404 def _cree_face_mediane_cylindre_1 ( self, coo_c, v_axe, rayon, hauteur, n_recur ):
1405 """Crée la face médiane entre deux autres - cas des cylindres
1407 Création des objets temporaires et de la face externe du cylindre support
1410 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1411 :axe_x, axe_y, axe_z: coordonnées de l'axe
1412 :rayon: rayon moyen entre les deux faces
1413 :hauteur: hauteur du cylindre
1414 :n_recur: niveau de récursivité
1417 :face: la face médiane
1419 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1420 blabla = "Dans {} :\n".format(nom_fonction)
1422 # Les caractéristiques du cylindre à créer
1423 if self._verbose_max:
1424 print_tab (n_recur, blabla)
1425 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1426 print_tab (n_recur, "Axe : ({}, {}, {})".format(v_axe[0], v_axe[1], v_axe[2]))
1427 print_tab (n_recur, "Rayon : ", rayon)
1428 print_tab (n_recur, "Hauteur : ", hauteur)
1430 # 1. Création du point central
1431 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
1432 nom_centre = "{}_centre".format(self.nom_solide)
1433 exec_nom (centre,nom_centre)
1434 if self.fonction_0 is None:
1435 self.fonction_0 = centre
1437 # 2. Création du vecteur axial
1438 axe = model.addAxis(self.part_doc, v_axe[0], v_axe[1], v_axe[2])
1439 nom_axe = "{}_vecteur".format(self.nom_solide)
1440 exec_nom (axe,nom_axe)
1442 # 3. Création du cylindre en volume, de rayon médian
1443 Cylinder_1 = model.addCylinder(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon, hauteur)
1444 nom = "{}_Cylinder_1".format(self.nom_solide)
1445 exec_nom (Cylinder_1,nom)
1447 # 4. Création du cylindre en surface
1448 cylindre = self._creation_face_surface ( nom, "cylindre" )
1451 Translation_1 = model.addTranslation(self.part_doc, [model.selection("COMPOUND", cylindre.name())], axis = model.selection("EDGE", nom_axe), distance = -0.5*hauteur, keepSubResults = True)
1452 nom = "{}_Translation_1".format(self.nom_solide)
1453 exec_nom (Translation_1,nom)
1455 # 6. Intersection de la face cylindrique avec le solide initial
1456 face = self._creation_face_inter ( nom )
1460 #=========================== Fin de la méthode ==================================
1462 #=========================== Début de la méthode =================================
1464 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1465 """Crée la face médiane entre deux autres - cas des sphères
1468 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1469 :n_recur: niveau de récursivité
1472 :face: la face médiane
1475 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1476 blabla = "Dans {} :".format(nom_fonction)
1479 if self._verbose_max:
1480 print_tab (n_recur, blabla)
1481 print_tab (n_recur, "face_1 : ", caract_face_1)
1482 print_tab (n_recur, "face_2 : ", caract_face_2)
1484 # Caractéristiques des sphères
1485 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1487 # Contrôle de la validité de l'épaisseur
1488 erreur = self._verif_epaisseur ( epaisseur )
1490 # Création de la face
1492 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1498 #=========================== Fin de la méthode ==================================
1500 #=========================== Début de la méthode =================================
1502 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1503 """Crée la face médiane entre deux autres - cas des sphères
1505 Décodage des caractéristiques
1508 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1509 :n_recur: niveau de récursivité
1512 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1513 :rayon: rayon moyen entre les deux faces
1514 :epaisseur: épaisseur de l'interface entre les deux faces
1517 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1518 blabla = "Dans {} :".format(nom_fonction)
1521 if self._verbose_max:
1522 print_tab (n_recur, blabla)
1523 print_tab (n_recur, "face_1 : ", caract_face_1)
1524 print_tab (n_recur, "face_2 : ", caract_face_2)
1526 # Coordonnées du centre de la sphère
1527 coo_x = caract_face_1[2][1]
1528 coo_y = caract_face_1[2][2]
1529 coo_z = caract_face_1[2][3]
1531 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1533 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1535 return coo_x, coo_y, coo_z, rayon, epaisseur
1537 #=========================== Fin de la méthode ==================================
1539 #=========================== Début de la méthode =================================
1541 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1542 """Crée la face médiane entre deux autres - cas des sphères
1544 Création des objets de construction et de la face externe de la sphère support
1547 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1548 :rayon: rayon moyen entre les deux faces
1551 :face: la face externe de la sphère support
1554 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1555 blabla = "Dans {} :\n".format(nom_fonction)
1557 # Les caractéristiques de la sphère à créer
1558 if self._verbose_max:
1560 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1561 texte += "Rayon : {}".format(rayon)
1564 # 1. Création du point central
1565 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1566 nom_centre = "{}_centre".format(self.nom_solide)
1567 exec_nom (centre,nom_centre)
1568 if self.fonction_0 is None:
1569 self.fonction_0 = centre
1571 # 2. Création de la sphère en volume, de rayon médian
1572 Sphere_1 = model.addSphere(self.part_doc, model.selection("VERTEX", nom_centre), rayon)
1573 nom = "{}_Sphere_1".format(self.nom_solide)
1574 exec_nom (Sphere_1,nom)
1576 # 3. Création de la sphère en surface
1577 sphere = self._creation_face_surface ( nom, "sphere" )
1579 # 4. Intersection de la face sphérique avec le solide initial
1580 face = self._creation_face_inter ( sphere.name() )
1584 #=========================== Fin de la méthode ==================================
1586 #=========================== Début de la méthode =================================
1588 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1589 """Crée la face médiane entre deux autres - cas des tores
1592 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1593 :n_recur: niveau de récursivité
1596 :face: la face médiane
1599 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1600 blabla = "Dans {} :".format(nom_fonction)
1603 if self._verbose_max:
1604 print_tab (n_recur, blabla)
1605 print_tab (n_recur, "face_1 : ", caract_face_1)
1606 print_tab (n_recur, "face_2 : ", caract_face_2)
1608 # Caractéristiques des tores
1609 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 )
1611 # Contrôle de la validité de l'épaisseur (bidon)
1612 erreur = self._verif_epaisseur ( EP_MIN*10. )
1614 # Création de la face
1616 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1622 #=========================== Fin de la méthode ==================================
1624 #=========================== Début de la méthode =================================
1626 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1627 """Crée la face médiane entre deux autres - cas des tores
1629 Décodage des caractéristiques
1632 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1633 :n_recur: niveau de récursivité
1636 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1637 :axe_x, axe_y, axe_z: coordonnées de l'axe
1638 :rayon_1 : rayon principal
1639 :rayon_2 : rayon secondaire
1642 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1643 blabla = "Dans {} :".format(nom_fonction)
1646 if self._verbose_max:
1647 print_tab (n_recur, blabla)
1648 print_tab (n_recur, "face_1 : ", caract_face_1)
1649 print_tab (n_recur, "face_2 : ", caract_face_2)
1651 # Coordonnées du centre du tore
1652 coo_x = caract_face_1[2][1]
1653 coo_y = caract_face_1[2][2]
1654 coo_z = caract_face_1[2][3]
1655 # Coordonnées de l'axe
1656 axe_x = caract_face_1[2][4]
1657 axe_y = caract_face_1[2][5]
1658 axe_z = caract_face_1[2][6]
1660 rayon_1 = caract_face_2[2][7]
1661 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1663 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1665 #=========================== Fin de la méthode ==================================
1667 #=========================== Début de la méthode =================================
1669 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1670 """Crée la face médiane entre deux autres - cas des tores
1672 Création des objets de construction et de la face externe du tore support
1675 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1676 :axe_x, axe_y, axe_z: coordonnées de l'axe
1677 :rayon_1 : rayon principal
1678 :rayon_2 : rayon secondaire
1681 :face: la face externe du tore support
1684 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1685 blabla = "Dans {} :\n".format(nom_fonction)
1688 if self._verbose_max:
1690 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1691 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1692 texte += "Rayon principal : {}\n".format(rayon_1)
1693 texte += "Rayon secondaire : {}".format(rayon_2)
1696 # 1. Création du point central
1697 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1698 nom_centre = "{}_centre".format(self.nom_solide)
1699 exec_nom (centre,nom_centre)
1701 # 2. Création de l'axe
1702 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1703 nom_axe = "{}_axe".format(self.nom_solide)
1704 exec_nom (axe,nom_axe)
1706 # 3. Création du tore en volume, de rayon médian
1707 Tore_1 = model.addTorus(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon_1, rayon_2)
1708 nom = "{}_Tore_1".format(self.nom_solide)
1709 exec_nom (Tore_1,nom)
1711 # 4. Création du tore en surface
1712 tore = self._creation_face_surface ( nom, "tore" )
1714 # 5. Intersection de la face torique avec le solide initial
1715 face = self._creation_face_inter ( tore.name() )
1719 #=========================== Fin de la méthode ==================================
1721 #=========================== Début de la méthode =================================
1723 def _cree_face_mediane_cone ( self, caract_face_1, caract_face_2, n_recur ):
1724 """Crée la face médiane entre deux autres - cas des cônes
1727 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1728 :n_recur: niveau de récursivité
1731 :face: la face médiane
1734 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1735 blabla = "Dans {} :".format(nom_fonction)
1738 if self._verbose_max:
1739 print_tab (n_recur, blabla)
1740 print_tab (n_recur, "face_1 : ", caract_face_1)
1741 print_tab (n_recur, "face_2 : ", caract_face_2)
1743 # Caractéristiques des cônes
1744 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 )
1746 # Contrôle de la validité de l'épaisseur (bidon)
1747 erreur = self._verif_epaisseur ( EP_MIN*10. )
1749 # Création de la face
1751 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1757 #=========================== Fin de la méthode ==================================
1759 #=========================== Début de la méthode =================================
1761 def _cree_face_mediane_cone_0 ( self, caract_face_1, caract_face_2, n_recur ):
1762 """Crée la face médiane entre deux autres - cas des cônes
1764 Décodage des caractéristiques
1767 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1768 :n_recur: niveau de récursivité
1771 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1772 :axe_x, axe_y, axe_z: coordonnées de l'axe
1773 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1774 :hauteur: hauteur du cône
1777 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1778 blabla = "Dans {} :".format(nom_fonction)
1781 if self._verbose_max:
1782 print_tab (n_recur, blabla)
1783 print_tab (n_recur, "face_1 : ", caract_face_1)
1784 print_tab (n_recur, "face_2 : ", caract_face_2)
1786 # Coordonnées du centre de la base
1787 coo_x = caract_face_1[2][1]
1788 coo_y = caract_face_1[2][2]
1789 coo_z = caract_face_1[2][3]
1790 # Coordonnées de l'axe
1791 axe_x = caract_face_1[2][4]
1792 axe_y = caract_face_1[2][5]
1793 axe_z = caract_face_1[2][6]
1795 rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1796 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1798 hauteur = caract_face_1[2][9]
1801 if self._verbose_max:
1802 print_tab (n_recur, "coo_x : ", coo_x)
1803 print_tab (n_recur, "coo_y : ", coo_y)
1804 print_tab (n_recur, "coo_z : ", coo_z)
1805 print_tab (n_recur, "axe_x : ", axe_x)
1806 print_tab (n_recur, "axe_y : ", axe_y)
1807 print_tab (n_recur, "axe_z : ", axe_z)
1808 print_tab (n_recur, "rayon_1 : ", rayon_1)
1809 print_tab (n_recur, "rayon_2 : ", rayon_2)
1810 print_tab (n_recur, "hauteur : ", hauteur)
1812 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1814 #=========================== Fin de la méthode ==================================
1816 #=========================== Début de la méthode =================================
1818 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1819 """Crée la face médiane entre deux autres - cas des cônes
1821 Création des objets de construction et de la face externe du cône support
1824 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1825 :axe_x, axe_y, axe_z: coordonnées de l'axe
1826 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1827 :hauteur: hauteur du cône
1830 :face: la face externe du cône support
1832 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1833 blabla = "Dans {} :\n".format(nom_fonction)
1836 if self._verbose_max:
1838 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1839 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1840 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1841 texte += "Hauteur : {}".format(hauteur)
1844 # 1. Création du point central de la base, côté rayon_1
1845 centre_1 = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1846 nom_centre_1 = "{}_centre_1".format(self.nom_solide)
1847 exec_nom (centre_1,nom_centre_1)
1849 # 2. Création du point central, du côté de rayon_2
1850 centre_2 = model.addPoint(self.part_doc, coo_x+hauteur*axe_x, coo_y+hauteur*axe_y, coo_z+hauteur*axe_z)
1851 nom_centre_2 = "{}_centre_2".format(self.nom_solide)
1852 exec_nom (centre_2,nom_centre_2)
1854 # 3. Création de l'axe
1855 axe = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre_1), model.selection("VERTEX", nom_centre_2))
1856 nom_axe = "{}_axe".format(self.nom_solide)
1857 exec_nom (axe,nom_axe)
1859 # 4. Création du cône en volume, de rayon médian
1860 # 4.1. Calculs des rayons haut et bas, de sa hauteur et de la valeur de la translation
1861 rayon_b, rayon_s, hauteur_c, d_trans = self._cree_face_mediane_cone_2 ( rayon_1, rayon_2, hauteur )
1863 # 4.2. Création du grand cône
1864 Cone_1 = model.addCone(self.part_doc, model.selection("VERTEX", nom_centre_1), model.selection("EDGE", nom_axe), rayon_b, rayon_s, hauteur_c)
1865 nom_1 = "{}_Cone_1".format(self.nom_solide)
1866 exec_nom (Cone_1,nom_1)
1868 # 4.3. Translation pour superposer au cône de départ
1869 Translation_1 = model.addTranslation(self.part_doc, [model.selection("SOLID", nom_1)], axis = model.selection("EDGE", nom_axe), distance = d_trans, keepSubResults = True)
1870 nom_2 = "{}_Cone_1_trans".format(self.nom_solide)
1871 exec_nom (Translation_1,nom_2)
1873 # 5. Création du cône en surface
1874 nom = "{}/MF:Translated&{}".format(nom_2,nom_1)
1875 cone = self._creation_face_surface ( nom, "cone" )
1877 # 6. Intersection de la face conique avec le solide initial
1878 face = self._creation_face_inter ( cone.name() )
1882 #=========================== Fin de la méthode ==================================
1884 #=========================== Début de la méthode =================================
1886 def _cree_face_mediane_cone_2 ( self, rayon_1, rayon_2, hauteur ):
1887 """Crée la face médiane entre deux autres - cas des cônes
1889 Calcul des caractéristiques du cône enveloppant. Merci Thalès !
1890 Le coefficient multiplicateur est choisi pour être certain de tout prendre. On calcule la
1891 plus petite valeur et on ajoute arbitrairement 5.
1893 Remarque : on ne peut pas avoir un cône pointu car il est situé entre deux cônes donc il y a une épaisseur.
1896 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1897 :hauteur: hauteur du cône
1900 :rayon_b: rayon du cône - partie basse
1901 :rayon_s: rayon du cône - partie supérieure
1902 :hauteur_c: hauteur du cône
1903 :d_trans: distance de translation selon l'axe
1905 nom_fonction = __name__ + "/_cree_face_mediane_cone_2"
1906 blabla = "Dans {} :\n".format(nom_fonction)
1909 if self._verbose_max:
1911 texte += "rayon_1 : {}\n".format(rayon_1)
1912 texte += "rayon_2 : {}\n".format(rayon_2)
1913 texte += "Hauteur : {}".format(hauteur)
1918 # 1. Cas étroit en bas
1919 if ( rayon_1 < rayon_2 ):
1920 # Distance entre la pointe et la base
1921 coeff_a = rayon_1/(rayon_2-rayon_1)
1922 d_pointe_base = hauteur*coeff_a
1923 coeff = coeff_a + 1. + bonus
1924 if self._verbose_max:
1925 print ("Cas étroit en bas")
1926 print ("Distance de la pointe à la base : {}*{} = {}".format(coeff_a,hauteur,d_pointe_base))
1928 rayon_s = coeff*(rayon_2-rayon_1)
1929 d_trans = -d_pointe_base
1931 # 2. Cas étroit en haut
1932 # Manifestement cela n'arrive jamais une fois passé par du step et réimporté dans SHAPER
1934 # Distance entre la pointe et le haut
1935 coeff_a = rayon_1/(rayon_1-rayon_2)
1936 d_pointe_haut = hauteur*coeff_a
1937 coeff = coeff_a + 1. + bonus
1938 if self._verbose_max:
1939 print ("Cas étroit en haut")
1940 print ("Distance de la pointe et le haut : {}*{} = {}".format(coeff_a,hauteur,d_pointe_haut))
1941 rayon_b = coeff*(rayon_1-rayon_2)
1943 d_trans = -bonus*hauteur
1946 hauteur_c = coeff*hauteur
1948 if self._verbose_max:
1949 texte = "rayon_b : {}\n".format(rayon_b)
1950 texte += "rayon_s : {}\n".format(rayon_s)
1951 texte += "Translation : {}".format(d_trans)
1954 return rayon_b, rayon_s, hauteur_c, d_trans
1956 #=========================== Fin de la méthode ==================================
1958 #=========================== Début de la méthode =================================
1960 def _cree_centre_axe_plan ( self, coo_c, vect, prefixe, n_recur ):
1961 """Crée un centre, un axe, un plan
1964 :coo_c: coordonnées du centre de la base
1965 :vect: coordonnées du vecteur
1966 :prefix: prefixe du nom des objets
1967 :n_recur: niveau de récursivité
1971 :normal: vecteur normal
1975 nom_fonction = __name__ + "/_cree_centre_axe_plan"
1976 blabla = "Dans {} :".format(nom_fonction)
1977 if self._verbose_max:
1978 print_tab (n_recur, blabla)
1979 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1980 print_tab (n_recur, "Normale : ({}, {}, {})".format(vect[0], vect[1], vect[2]))
1982 # Création du point central
1983 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
1984 nom_centre = "{}_centre".format(prefixe)
1985 exec_nom (centre,nom_centre)
1986 if self.fonction_0 is None:
1987 self.fonction_0 = centre
1989 # Création du vecteur
1990 vecteur = model.addAxis(self.part_doc, vect[0], vect[1], vect[2])
1991 nom_vect = "{}_vecteur".format(prefixe)
1992 exec_nom (vecteur,nom_vect)
1994 # Création du plan perpendiculaire au vecteur normal
1995 plan = model.addPlane(self.part_doc, model.selection("EDGE", vecteur.name()), model.selection("VERTEX", centre.name()), True)
1996 nom_plan = "{}_plan".format(prefixe)
1997 exec_nom (plan,nom_plan)
1999 #print ("fin de {}".format(nom_fonction))
2001 return centre, vecteur, plan
2003 #=========================== Fin de la méthode ==================================
2005 #=========================== Début de la méthode =================================
2007 def _calcul_lg_caract_0 ( self, objet, tb_caract, n_recur ):
2008 """Crée une longueur caractéristique de l'objet formés de surfaces planes
2010 Les caractéristiques sont comme en IHM avec 'Inspection' :
2011 . Si la face est un rectangle, la caractéristique est :
2012 Xcoin, Ycoin, Zcoin, Xnormale, Ynormale, Znormale, Largeur, Hauteur
2013 . Si la face est un polygone, elle est vue comme un plan et la caractéristique est :
2014 Xcentre, Ycentre, Zcentre, Xnormale, Ynormale, Znormale
2015 . Si la face est un disque, elle est vue comme un plan et la caractéristique est :
2016 Xcentre, Ycentre, Zcentre, Xnormale, Ynormale, Znormale, Rayon
2018 Si on se contente de raisonner avec la boîte englobante de la face, on a le risque qu'elle ne soit pas au bon endroit.
2020 Il faut ici calculer la dimension d'une boîte centrée sur l'origine qui englobe à coup sûr le solide.
2023 :objet: l'objet à traiter
2024 :tb_caract: tableau des caractéristiques géométriques des faces
2025 :n_recur: niveau de récursivité
2028 :l_caract: longueur caractéristique de l'objet
2031 nom_fonction = __name__ + "/_calcul_lg_caract_0"
2032 blabla = "Dans {} :".format(nom_fonction)
2034 if self._verbose_max:
2035 print_tab (n_recur, blabla)
2037 # 1. On parcourt toutes les faces en repérant les rectangles.
2038 # Pour ces rectangles on va calculer les plus grandes valeurs des coordonnées et des épaisseurs.
2040 avec_rectangle = False
2043 for iaux, caract in enumerate(tb_caract):
2044 if self._verbose_max:
2045 print_tab (n_recur, "Face {} : ".format(iaux), caract)
2046 if ( caract[-1][0] == "Rectangle" ):
2047 avec_rectangle = True
2048 xyz_max = max(xyz_max,abs(caract[-1][1]),abs(caract[-1][2]),abs(caract[-1][3]))
2049 d_max = max(d_max,caract[-1][7],caract[-1][8])
2051 if self._verbose_max:
2052 print_tab (n_recur, "xyz_max : ", xyz_max)
2053 print_tab (n_recur, "d_max : ", d_max)
2056 # 2.1. S'il y avait des rectangles, on prend un cube plus grand
2058 l_caract = (xyz_max+d_max)*np.sqrt(3.)
2059 # 2.2. Sinon, on peut utiliser la formule classique
2061 l_caract = self._calcul_lg_caract_1 ( objet, n_recur )
2063 if self._verbose_max:
2064 print_tab (n_recur, "Longueur caractéristique : ", l_caract)
2068 #=========================== Fin de la méthode ==================================
2070 #=========================== Début de la méthode =================================
2072 def _calcul_lg_caract_1 ( self, objet, n_recur ):
2073 """Crée une longueur caractéristique de l'objet
2076 :objet: l'objet à traiter
2077 :n_recur: niveau de récursivité
2080 :l_caract: longueur caractéristique de l'objet
2083 nom_fonction = __name__ + "/_calcul_lg_caract_1"
2084 blabla = "Dans {} :".format(nom_fonction)
2086 if self._verbose_max:
2087 print_tab (n_recur, blabla)
2089 properties = model.getGeometryCalculation(self.part_doc,model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
2090 l_caract = properties[0]
2092 if self._verbose_max:
2093 print_tab (n_recur, "Longueur caractéristique : ", l_caract)
2097 #=========================== Fin de la méthode ==================================
2099 #=========================== Début de la méthode =================================
2101 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
2102 """Crée un volume de révolution
2105 :nom_sketch: nom de l'esquisse à révolutionner
2106 :nom_centre: nom du point associé au centre du volume de révolution
2107 :coo_x, coo_y, coo_z: coordonnées du centre du tore
2108 :axe_x, axe_y, axe_z: coordonnées de l'axe
2109 :rayon_1 : rayon principal
2110 :rayon_2 : rayon secondaire
2111 :nom_objet: nom de l'objet 2D créé
2114 nom_fonction = __name__ + "/_cree_revolution"
2115 blabla = "Dans {} :\n".format(nom_fonction)
2117 if self._verbose_max:
2119 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
2120 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
2123 # Création d'un point décalé par rapport au point central
2124 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
2125 nom_point = "{}_point".format(self.nom_solide)
2126 exec_nom (point,nom_point)
2128 # Création de l'axe de la rotation
2129 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
2130 nom_axe_r = "{}_axe_r".format(self.nom_solide)
2131 exec_nom (axe_r,nom_axe_r)
2133 # Création de l'objet complet
2134 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
2135 exec_nom (objet, nom_objet, (85, 0, 255))
2137 #=========================== Fin de la méthode ==================================
2139 #=========================== Début de la méthode =================================
2141 def _creation_face_surface ( self, nom_objet, suffixe ):
2142 """Crée la face qui est la surface externe d'un objet
2144 . Crée le groupe de la face externe
2145 . Transforme le groupe en face résultat
2148 :nom_objet: nom de l'objet 3D à traiter
2149 :suffixe: suffixe pour nommer l'objet 2D
2150 :nom_solide: nom du solide initial ; si None, on prend self.nom_solide_aux
2153 :objet_2d: l'objet 2D support de la face externe de l'objet 3D
2156 nom_fonction = __name__ + "/_creation_face_surface"
2157 blabla = "Dans {} :\n".format(nom_fonction)
2159 if self._verbose_max:
2162 # 1. Le groupe de la surface
2163 groupe = model.addGroup(self.part_doc, "Faces", [model.selection("FACE", "{}/Face_1".format(nom_objet))])
2164 nom = "{}_{}_groupe".format(self.nom_solide,suffixe)
2165 exec_nom (groupe, nom, (85, 0, 255))
2167 # 2. Création de la face en surface
2168 objet_2d = model.addGroupShape(self.part_doc, [model.selection("COMPOUND", nom)])
2169 nom = "{}_{}".format(self.nom_solide,suffixe)
2170 exec_nom (objet_2d, nom, (85, 0, 255))
2174 #=========================== Fin de la méthode ==================================
2176 #=========================== Début de la méthode =================================
2178 def _creation_face_inter ( self, nom_objet, nom_solide=None ):
2179 """Crée la face par intersection entre l'objet initial et une face complète
2181 . Repère la face principale de l'objet support
2182 . Réalise l'intersection avec le solide initial
2185 :nom_objet: nom de l'objet 2D créé
2186 :nom_solide: nom du solide initial ; si None, on prend self.nom_solide_aux
2189 :face: la face externe de l'objet support intersecté avec le solide initial
2192 nom_fonction = __name__ + "/_creation_face_inter"
2193 blabla = "Dans {} :\n".format(nom_fonction)
2195 if self._verbose_max:
2197 texte += "nom_objet = {}\n".format(nom_objet)
2198 texte += "nom_solide = {}".format(nom_solide)
2201 if nom_solide is None:
2202 nom_solide = self.nom_solide_aux
2204 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_objet)], keepSubResults = True)
2209 #=========================== Fin de la méthode ==================================
2211 #=========================== Début de la méthode =================================
2213 def face_mediane_solide (self, solide, n_recur=0):
2214 """Calcul de la face médiane pour un solide
2217 :solide: solide SHAPER à traiter
2218 :n_recur: niveau de récursivité
2221 :erreur: code d'erreur
2222 :message: message d'erreur
2225 nom_fonction = __name__ + "/face_mediane_solide"
2226 blabla = "Dans {} :".format(nom_fonction)
2228 if self._verbose_max:
2229 print_tab (n_recur, blabla, saut_av=True)
2231 print_tab (n_recur, "Traitement du solide ", solide.name())
2240 # 2. Calcul des caractéristiques géométriques des faces
2242 tb_caract = self._calcul_caract_faces ( solide, n_recur )
2244 # 3. Tri des faces en fonction de leurs caractéristiques géométriques
2246 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract, n_recur )
2250 # 4. Création de la face médiane
2252 erreur, face = self._cree_face_mediane ( solide, caract_face_1, caract_face_2, tb_caract, n_recur )
2253 if ( erreur or ( face is None ) ):
2256 # 6. Exportation step
2258 if self._export_step:
2259 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2260 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2261 export.execute(True)
2268 if ( erreur and self._verbose_max ):
2269 print (blabla, message)
2271 return erreur, message
2273 #=========================== Fin de la méthode ==================================
2275 #=========================== Début de la méthode =================================
2277 def _traitement_objet (self, solide, n_recur=0):
2278 """Traitement d'un objet
2281 :solide: solide SHAPER à traiter
2282 :n_recur: niveau de récursivité
2285 :erreur: code d'erreur
2286 :message: message d'erreur
2289 nom_fonction = __name__ + "/_traitement_objet"
2290 blabla = "Dans {} :".format(nom_fonction)
2292 if self._verbose_max:
2293 print_tab (n_recur, blabla, saut_av=True)
2294 texte = "solide = {} ".format(solide.name())
2295 print_tab (n_recur, texte, solide)
2297 # 1. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2298 # Attention à ne pas recréer le répertoire à chaque fois
2299 if self._export_step:
2301 if self.rep_step is None:
2303 if self._verbose_max:
2304 print_tab (n_recur, "Préparation de l'export STEP")
2306 if self.ficcao is None:
2307 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2309 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2310 if os.path.isdir(self.rep_step):
2311 l_aux = os.listdir(self.rep_step)
2312 for nomfic in l_aux:
2313 os.remove(os.path.join(self.rep_step,nomfic))
2315 os.mkdir(self.rep_step)
2317 if self._verbose_max:
2318 print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2320 # 2. Calcul réel de la face médiane
2322 erreur, message = self.face_mediane_solide (solide, n_recur)
2324 return erreur, message
2326 #=========================== Fin de la méthode ==================================
2328 #=========================== Début de la méthode =================================
2330 def surf_fic_cao (self, ficcao, nom_objet=None):
2331 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2334 :ficcao: fichier de l'objet à traiter
2335 :nom_objet: un nom à donner à l'objet à traiter
2338 :erreur: code d'erreur
2339 :message: message d'erreur
2342 nom_fonction = __name__ + "/surf_fic_cao"
2343 blabla = "Dans {} :".format(nom_fonction)
2345 if self._verbose_max:
2355 if self.affiche_aide_globale:
2358 # 1. Définition de la pièce
2360 self.part_doc = model.activeDocument()
2361 if ( self.part_doc.kind() == "PartSet" ):
2362 part = model.addPart(self.part_doc)
2363 self.part_doc = part.document()
2365 # 2. Import de la CAO
2367 self.ficcao = ficcao
2368 print ("Traitement du fichier {}".format(ficcao))
2370 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2374 # 3. Calcul des surfaces
2376 erreur, message = self.surf_objet_shaper ( objet )
2383 if ( erreur and self._verbose_max ):
2384 print (blabla, message)
2386 return erreur, message
2388 #=========================== Fin de la méthode ==================================
2390 #=========================== Début de la méthode =================================
2392 def surf_objet_shaper (self, objet):
2393 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2396 :objet: objet à traiter
2399 :erreur: code d'erreur
2400 :message: message d'erreur
2403 nom_fonction = __name__ + "/surf_objet_shaper"
2404 blabla = "Dans {} :".format(nom_fonction)
2406 if self._verbose_max:
2414 if self.affiche_aide_globale:
2417 # 1. Acquisition de la liste des noms des sous-objets solides
2419 self.d_statut_so = dict()
2420 self.l_noms_so = list()
2421 self.l_faces_m = list()
2423 _ = self._nom_sous_objets (objet, True)
2424 if self._verbose_max:
2425 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2427 # 2. Les faces médianes
2429 erreur, message = self._surf_objet_shaper_0 ( objet )
2433 # 3. Gestion des faces créées
2435 self._surf_objet_shaper_1 ( )
2437 # 4. Futur message pour le résultat
2439 if ( self._export_step and not erreur ):
2440 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2444 return erreur, message
2446 #=========================== Fin de la méthode ==================================
2448 #=========================== Début de la méthode =================================
2450 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2451 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2454 :objet: objet à traiter
2455 :n_recur: niveau de récursivité
2458 :erreur: code d'erreur
2459 :message: message d'erreur
2462 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2463 blabla = "Dans {} :".format(nom_fonction)
2465 if self._verbose_max:
2466 print_tab (n_recur, blabla)
2467 print_tab (n_recur, "n_recur = ", n_recur)
2474 # 1. Au premier passage, il faut récupérer la pièce SHAPER et garder la référence au résultat principal
2476 if ( n_recur == 0 ):
2477 self.part_doc = model.activeDocument()
2478 objet_0 = objet.result()
2479 self.objet_principal = objet_0
2480 objet_bis = objet.defaultResult().shape()
2481 if self._verbose_max:
2482 print_tab (0, "Examen de l'objet initial ", objet.result().name(), saut_av=True)
2483 print_tab (0, "Type python : ", type(objet))
2484 print_tab (0, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2487 if self._verbose_max:
2488 print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2489 print_tab (n_recur, "Type python : ", type(objet))
2490 print_tab (n_recur, "shapeType : ", objet.shapeType())
2492 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2494 nb_sub_results = objet_0.numberOfSubs()
2496 if self._verbose_max:
2497 print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType(), saut_av=True)
2498 print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2500 for n_sobj in range(nb_sub_results):
2502 # 2.1. Exploration récursive de l'arborescence
2504 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2511 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2513 if ( objet_0.shapeType() == "SOLID" ):
2514 erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2518 # 3. Futur message pour le résultat
2520 if self._export_step:
2521 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2525 return erreur, message
2527 #=========================== Fin de la méthode ==================================
2529 #=========================== Début de la méthode =================================
2531 def _surf_objet_shaper_1 (self, n_recur=0):
2532 """Gestion des surfaces médianes créées
2535 :n_recur: niveau de récursivité
2538 :erreur: code d'erreur
2539 :message: message d'erreur
2542 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2543 blabla = "Dans {} :\n".format(nom_fonction)
2545 if self._verbose_max:
2546 print_tab (n_recur, blabla)
2548 # 1. Informations sur les faces à problème
2550 if self.faces_pb_nb:
2551 if ( self.faces_pb_nb == 1 ):
2552 texte = "1 face pose"
2554 texte = "{} faces posent".format(self.faces_pb_nb)
2555 print_tab (n_recur, "{} problème.".format(texte), self.faces_pb_msg, saut_av=True)
2557 # 2. Si plus d'une face a été créée
2558 if ( len(self.l_faces_m) > 1 ):
2560 # 2.1. Partition du paquet de faces
2562 if self._verbose_max:
2563 print_tab (n_recur, "Partitionnnement des faces créées.")
2565 # 2.1.1. Pour une raison mystérieuse, il faut commencer par les faces entières, puis mettre les sous-faces éventuelles
2567 for (face,_) in self.l_faces_m:
2568 if not face.result().numberOfSubs():
2569 d_faces[face.name()] = [face.name()]
2570 for (face,_) in self.l_faces_m:
2571 nb_sub_results = face.result().numberOfSubs()
2574 for n_sobj in range(nb_sub_results):
2575 laux.append(face.result().subResult(n_sobj).name())
2576 d_faces[face.name()] = laux
2579 for _, laux in d_faces.items():
2580 for s_face_n in laux:
2581 l_objets.append(model.selection("FACE", s_face_n))
2583 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2584 nom = "{}_M".format(self.objet_principal.name())
2585 exec_nom (Partition_1,nom)
2588 for face_n, laux in d_faces.items():
2589 Partition_1.result().subResult(iaux).setName("{}".format(face_n))
2590 if ( len(laux) > 1 ):
2591 for jaux, s_face_n in enumerate(laux):
2592 Partition_1.result().subResult(iaux).subResult(jaux).setName("{}_M".format(s_face_n))
2594 couleur_objet (Partition_1, n_recur, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
2596 # 2.2. Récupération des faces individuelles
2598 if self._verbose_max:
2599 print_tab (n_recur, "Récupération des faces individuelles.")
2602 for iaux, (face,_) in enumerate(self.l_faces_m):
2603 l_objets.append(face.result())
2605 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2606 exec_nom (Recover_1)
2607 for iaux, (face,_) in enumerate(self.l_faces_m):
2608 Recover_1.results()[iaux].setName("{}".format(face.name()))
2609 Recover_1.results()[iaux].setColor(0, 170, 0)
2610 nb_sub_results = Recover_1.results()[iaux].numberOfSubs()
2611 for n_sobj in range(nb_sub_results):
2612 Recover_1.results()[iaux].subResult(n_sobj).setName("{}_{}".format(face.name(),n_sobj))
2613 Recover_1.results()[iaux].subResult(n_sobj).setColor(0, 170, 0)
2615 # 3. Mise en dossier
2617 if self._verbose_max:
2618 print_tab (n_recur, "Mise en dossier.")
2620 for (face,fonction_0) in self.l_faces_m:
2621 if fonction_0 is not None:
2622 nom = face.name()[:-2]
2623 if self._verbose_max:
2624 print ( "Dossier {} de {} à {}".format(nom,fonction_0.name(),face.name()))
2625 dossier = model.addFolder(self.part_doc, fonction_0, face)
2626 dossier.setName(nom)
2628 if ( len(self.l_faces_m) > 1 ):
2630 nom = self.objet_principal.name()
2631 if self._verbose_max:
2632 print ( "Dossier {} de {} à {}".format(nom,Partition_1.name(),Recover_1.name()))
2633 dossier = model.addFolder(self.part_doc, Partition_1, Recover_1)
2634 dossier.setName(nom)
2636 #=========================== Fin de la méthode ==================================
2638 #=========================== Début de la méthode =================================
2640 def surf_solide_shaper (self, solide, n_recur):
2641 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2644 :solide: solide SHAPER à traiter
2645 :n_recur: numéro de la récurrence
2648 :erreur: code d'erreur
2649 :message: message d'erreur
2652 nom_fonction = __name__ + "/surf_solide_shaper"
2653 blabla = "Dans {} :".format(nom_fonction)
2655 if self._verbose_max:
2656 print_tab (n_recur, blabla, saut_av=True)
2663 self.nom_solide = solide.name()
2664 if self._verbose_max:
2665 print_tab (n_recur, "solide : ", self.nom_solide)
2667 # 1. Isolement du solide
2668 solide_aux, recover = self._isole_solide ( solide, n_recur )
2670 # 2. Traitement de l'objet correspondant
2671 erreur, message = self._traitement_objet ( solide_aux, n_recur=n_recur )
2673 if ( erreur and self._verbose_max ):
2674 print (blabla, message)
2676 # 3. Neutralisation des erreurs dues à l'épaisseur
2677 if ( erreur in (-2,-1,2) ):
2683 # 4. Mise en forme de l'objet principal récupéré
2684 if ( recover is not None ):
2685 _ = self._nom_sous_objets (recover, False)
2689 return erreur, message
2691 #=========================== Fin de la méthode ==================================
2693 #========================== Fin de la classe ====================================