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.17"
41 #========================= Les imports - Début ===================================
52 from SketchAPI import *
53 from salome.shaper import model
54 from salome.shaper import geom
56 from GeomAlgoAPI import *
60 #========================== Les imports - Fin ====================================
63 D_FMT["stp"] = ["stp", "step"]
64 D_FMT["igs"] = ["igs", "iges"]
65 for CLE in ("brep", "xao"):
68 # statut = 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
87 # Transparence des solides traités correctement
90 # Limite basse de l'épaisseur pour pouvoir faire les intersections
93 #========================= Début de la fonction ==================================
95 def decode_cao (fmt_cao):
96 """Décode le format de la cao
99 :fmt_cao: format du fichier, step, iges, etc.
101 :fmt_cao_0: format décodé
106 fmt_cao_low = fmt_cao.lower()
108 for cle, l_aux in D_FMT.items():
109 if ( fmt_cao_low in l_aux ):
115 #========================= Fin de la fonction ===================================
117 #========================= Début de la fonction ==================================
119 def import_cao (part_doc, ficcao, nom_objet=None, verbose=False):
120 """Importation d'une cao
124 :ficcao: le fichier de la CAO
125 :nom_objet: nom à donner à l'objet lu, éventuellement
127 :objet: l'objet importé dans SHAPER
130 nom_fonction = __name__ + "/import_cao"
131 blabla = "Dans {} :\n".format(nom_fonction)
132 message_0 = "Fichier : {}\n".format(ficcao)
134 message = blabla + message_0
135 message += "nom_objet : {}".format(nom_objet)
143 laux = ficcao.split(".")
144 fmt_cao_0 = decode_cao (laux[-1])
146 if ( fmt_cao_0 not in ("stp", "brep", "igs", "xao") ):
147 message += "Le format de CAO est inconnu"
151 message += "Le fichier de CAO n'a pas été décodé correctement."
154 elif not os.path.isfile(ficcao):
155 message += "Le fichier de CAO est inconnu."
161 objet = model.addImport(part_doc, ficcao)
162 exec_nom (objet, nom_objet)
166 texte = "Objet : '{}'\n".format(objet.result().name())
167 texte += "De type : '{}'".format(objet.result().shapeType())
170 return erreur, message, objet
172 #========================= Fin de la fonction ===================================
174 #========================= Début de la fonction ==================================
176 def couleur_objet (objet, n_recur=0, coul_r=1, coul_g=0, coul_b=0, verbose=False):
177 """Appliquer une couleur à un objet et à ses sous_objets
180 :objet: objet à traiter
181 :n_recur: niveau de récursivité
182 :coul_r,coul_g,coul_b: code RGB de la couleur à appliquer
185 :rang: rang du sous-objet
188 nom_fonction = __name__ + "/couleur_objet"
189 blabla = "Dans {} :".format(nom_fonction)
193 print ("n_recur = {}".format(n_recur))
194 print_tab(n_recur, "objet : ", objet.name())
195 print_tab(n_recur, "RGB = ({},{},{})".format(coul_r,coul_g,coul_b))
197 # 1. Au premier passage, il faut garder la référence au résultat principal
200 objet_0 = objet.result()
206 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
208 nb_sub_results = objet_0.numberOfSubs()
211 print_tab(n_recur, "Examen de l'objet",objet_0.name())
212 texte = "Formé de {} sous-objets".format(nb_sub_results)
213 print_tab(n_recur, texte)
215 for n_sobj in range(nb_sub_results):
217 # 2.1. Exploration récursive de l'arborescence
219 couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b, verbose )
221 # 2.2. Cet objet n'a pas de sous-objets : on le colore
223 print_tab(n_recur, "Couleur affectée à l'objet ",objet_0.name())
224 objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
226 #print ("sortie de {}".format(nom_fonction))
228 #========================= Fin de la fonction ===================================
230 #========================= Début de la fonction ==================================
232 def print_tab (nb_tab, message, argu=None, saut_av=False, saut_ap=False):
233 """Imprime avec des tabulations
236 :nb_tab: nombre de tabulations à appliquer
237 :message: message principal
238 :argu: argument du format
239 :saut_av: saut de ligne avant le texte
240 :saut_ap: saut de ligne après le texte
248 for _ in range(nb_tab):
252 if ( argu is not None ):
253 texte += "{}".format(argu)
260 #========================= Fin de la fonction ===================================
262 #========================= Début de la fonction ==================================
264 def nommage (objet, nom, couleur=None):
265 """Nomme un objet et son résultat
268 :objet: objet à traiter
269 :nom: nom à attribuer
270 :couleur: éventuellement couleur
274 objet.result().setName(nom)
276 if ( couleur is not None ):
277 objet.result().setColor(couleur[0], couleur[1], couleur[2])
279 #========================= Fin de la fonction ===================================
281 #========================= Début de la fonction ==================================
283 def exec_nom (fonction, nom=None, couleur=None):
284 """Exécute la fonction après l'avoir nommée et nommé son résultat; Couleur éventuelle
287 :fonction: fonction à traiter
288 :nom: nom à attribuer éventuellement
289 :couleur: éventuellement couleur
292 if ( nom is not None ):
293 nommage (fonction, nom, couleur)
295 fonction.execute(True)
297 #========================= Fin de la fonction ===================================
300 #=================================== La classe ===================================
302 class SurfaceMediane (object):
304 """Calcul des surfaces médianes de solides minces
306 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
307 une structure qui est un solide ou un assemblage de solides (compound).
308 Pour réaliser l'opération, trois façons de faire :
310 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
312 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
313 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
315 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
316 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
319 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
320 de taille identique et supérieure aux tailles des autres faces du solide. \
321 Cela fonctionne pour des surfaces planes ou de forme canonique.
322 Il crée alors une surface au milieu de ces deux grandes faces. \
323 Cette face est coloriée en vert, le solide est en vert et transparent.
325 On sait traiter les faces :
332 Si la création n'a pas eu lieu, un message est émis et les solides sont mis en couleur :
333 . Rouge : le solide n'est pas assez mince.
334 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
335 . Orange : la forme de la face n'est pas reconnue.
343 . Exportation finale dans un fichier step. Par défaut, pas d'export.
344 -export_step/-no_export_step
347 surf_fic_cao --> import_cao
348 --> surf_objet_shaper (récursif) --> _nom_sous_objets
349 --> _surf_objet_shaper_0
350 --> surf_solide_shaper --> _isole_solide --> _isole_solide_a
352 --> _traitement_objet --> face_mediane_solide --> _faces_du_solide
354 --> _cree_face_mediane
356 _cree_face_mediane --> _cree_face_mediane_plane
357 --> _cree_face_mediane_cylindre
358 --> _cree_face_mediane_sphere
359 --> _cree_face_mediane_tore
360 --> _cree_face_mediane_cone
361 --> _cree_face_mediane_0
370 affiche_aide_globale = 0
377 nom_solide_aux = None
383 objet_principal = None
384 # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
386 # Statut de chaque sous-objet connu par son nom :
387 # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
389 # Liste des faces médianes créées et des fonctions initiales
391 # La fonction initiale
397 #=========================== Début de la méthode =================================
399 def __init__ ( self, liste_option ):
401 """Le constructeur de la classe SurfaceMediane
403 Décodage des arguments
404 On cherche ici les arguments généraux : aide, verbeux
407 for option in liste_option :
410 if isinstance(option,str):
411 saux = option.upper()
413 if saux in ( "-H", "-HELP" ):
414 self.affiche_aide_globale = 1
417 elif saux == "-VMAX" :
419 self._verbose_max = 1
420 elif saux == "-EXPORT_STEP":
421 self._export_step = True
422 elif saux == "-NO_EXPORT_STEP":
423 self._export_step = False
425 #=========================== Fin de la méthode ==================================
427 #=========================== Début de la méthode =================================
430 """A la suppression de l'instance de classe"""
431 if self._verbose_max:
432 print ("Suppression de l'instance de la classe.")
434 #=========================== Fin de la méthode ==================================
436 #=========================== Début de la méthode =================================
438 def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
439 """Gère les noms des sous_objets solides
442 :objet: objet à traiter
443 :lecture: vrai pour lire les noms, faux pour les attribuer
444 :n_recur: niveau de récursivité
445 :rang: rang du sous-objet
448 :rang: rang du sous-objet
451 nom_fonction = __name__ + "/_nom_sous_objets"
452 blabla = "Dans {} :\n".format(nom_fonction)
454 if self._verbose_max:
456 for _ in range(n_recur):
458 texte = "\n{}{}".format(prefixe,blabla)
459 texte += "{}n_recur = {}".format(prefixe,n_recur)
460 texte += "\n{}lecture = {}".format(prefixe,lecture)
463 # 1. Au premier passage, il faut garder la référence au résultat principal
466 objet_0 = objet.result()
467 if self._verbose_max:
468 print ("d_statut_so = {}".format(self.d_statut_so))
472 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
474 nb_sub_results = objet_0.numberOfSubs()
476 if self._verbose_max:
477 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
478 texte += "de type '{}'".format(objet_0.shapeType())
479 texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
482 for n_sobj in range(nb_sub_results):
484 # 2.1. Exploration récursive de l'arborescence
486 rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
488 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
490 if ( objet_0.shapeType() == "SOLID" ):
491 # A la lecture, on enregistre le nom
494 self.l_noms_so.append(nom)
495 self.d_statut_so[nom] = 0
496 # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
498 nom = self.l_noms_so[rang]
500 etat = self.d_statut_so[nom]
501 objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
503 objet_0.setTransparency (TRANSPARENCE)
508 #=========================== Fin de la méthode ==================================
510 #=========================== Début de la méthode =================================
512 def _isole_solide ( self, solide, n_recur ):
513 """Isole le solide de son arboresence
516 :solide: le solide à traiter
517 :n_recur: numéro de la récurrence
520 :objet: le solide isolé
521 :recover: la fonction de récupération
524 nom_fonction = __name__ + "/_isole_solide"
525 blabla = "Dans {} :".format(nom_fonction)
526 if self._verbose_max:
527 print_tab (n_recur, blabla)
528 texte = "Pour le solide '{}' ".format(solide.name())
529 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
530 print_tab (n_recur, texte)
532 if ( solide.name() != self.objet_principal.name() ):
533 objet, recover = self._isole_solide_a ( solide, n_recur )
536 objet, recover = self._isole_solide_b ( solide, n_recur )
538 if self._verbose_max:
539 print_tab (n_recur, "objet final : ", objet.name())
540 print_tab (n_recur, "fonction_0 : {}".format(self.fonction_0))
541 print_tab (n_recur, "recover : {}".format(recover))
543 return objet, recover
545 #=========================== Fin de la méthode ==================================
547 #=========================== Début de la méthode =================================
549 def _isole_solide_a ( self, solide, n_recur ):
550 """Isole le solide de son arboresence
553 :solide: le solide à traiter
554 :n_recur: numéro de la récurrence
557 :objet: le solide isolé
558 :recover: la fonction de récupération
561 nom_fonction = __name__ + "/_isole_solide_a"
562 blabla = "Dans {} :".format(nom_fonction)
563 if self._verbose_max:
564 print_tab (n_recur, blabla)
565 texte = "Pour le solide '{}' ".format(solide.name())
566 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
567 print_tab (n_recur, texte)
569 if self._verbose_max:
570 print_tab (n_recur, ". Extraction du solide '{}'".format(self.objet_principal.name()))
572 # 1. Extraction du solide
573 remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
574 exec_nom (remove_subshapes)
575 remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
577 self.nom_solide_aux = "{}_S".format(solide.name())
578 if self._verbose_max:
579 print_tab (n_recur, "\tAttribution à remove_subshapes.result() du nom '{}'".format(self.nom_solide_aux))
580 exec_nom (remove_subshapes,self.nom_solide_aux)
582 self.fonction_0 = remove_subshapes
584 # 2. Récupération de l'objet principal
585 recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
586 if self._verbose_max:
587 print_tab (n_recur, "\tAttribution à recover du nom '{}'".format(self.objet_principal.name()))
588 exec_nom (recover,self.objet_principal.name())
590 return remove_subshapes.result(), recover
592 #=========================== Fin de la méthode ==================================
594 #=========================== Début de la méthode =================================
596 def _isole_solide_b ( self, solide, n_recur ):
597 """Isole le solide de son arboresence
600 :solide: le solide à traiter
601 :n_recur: numéro de la récurrence
604 :objet: le solide isolé
605 :recover: la fonction de récupération
608 nom_fonction = __name__ + "/_isole_solide_b"
609 blabla = "Dans {} :".format(nom_fonction)
610 if self._verbose_max:
611 print_tab (n_recur, blabla)
612 texte = "Pour le solide '{}' ".format(solide.name())
613 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
614 print_tab (n_recur, texte)
616 if self._verbose_max:
617 print_tab (n_recur, ". Mise en place du solide")
619 self.nom_solide_aux = self.objet_principal.name()
620 self.fonction_0 = None
624 #=========================== Fin de la méthode ==================================
626 #=========================== Début de la méthode =================================
628 def _faces_du_solide ( self, solide, n_recur=0 ):
629 """Détermine les faces d'un solide
632 :solide: solide SHAPER à traiter
633 :n_recur: niveau de récursivité
636 :l_faces_car: pour chaque face du solide (surface,caractéristiques)
639 nom_fonction = __name__ + "/_faces_du_solide"
640 blabla = "Dans {} :".format(nom_fonction)
641 if self._verbose_max:
642 print_tab (n_recur, blabla, saut_av=True)
646 if self._verbose_max:
647 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
648 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
651 #print_tab (n_recur, "volume = ", GeomAlgoAPI_ShapeTools.volume(solide.shape()))
652 # 1. Repérage des faces
653 objResult = solide.resultSubShapePair()[0]
655 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
657 l_faces.append(exp.current().face())
662 for iface, face in enumerate(l_faces):
663 surf = GeomAlgoAPI_ShapeTools.area(face)
664 caract = geom.shapeInfo(face)
665 if self._verbose_max:
666 print_tab (n_recur, "\tFace n°{} ; ".format(iface), "surface = {}, caractéristiques = {}".format(surf,caract))
667 l_faces_car.append((surf,caract))
671 #=========================== Fin de la méthode ==================================
673 #=========================== Début de la méthode =================================
675 def _calcul_caract_faces ( self, solide, n_recur ):
676 """Calcule les caractéristiques géométriques des faces du solide
679 :solide: solide SHAPER à traiter
680 :n_recur: niveau de récursivité
683 :tb_caract: tableau des caractéristiques géométriques des faces
686 nom_fonction = __name__ + "/_calcul_caract_faces"
687 blabla = "Dans {} :".format(nom_fonction)
688 if self._verbose_max:
689 print_tab (n_recur, blabla, saut_av=True)
690 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
691 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
693 # 1. Repérage des faces
694 objResult = solide.resultSubShapePair()[0]
696 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
698 l_faces.append(exp.current().face())
701 # 2. Caractéristiques
702 nb_faces = len(l_faces)
703 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
704 for iaux, face in enumerate(l_faces):
705 surf = GeomAlgoAPI_ShapeTools.area(face)
706 caract = geom.shapeInfo(face)
707 if self._verbose_max:
708 print_tab (n_recur, "\tFace n°{} ; ".format(iaux), "surface = {}, caractéristiques = {}".format(surf,caract))
710 tb_caract [iaux][0] = face
711 tb_caract [iaux][1] = surf
712 tb_caract [iaux][2] = caract
714 #if self._verbose_max:
715 #for iaux in range(nb_faces):
716 #print ("\t. tb_caract : {} {}".format(surf,tb_caract[iaux][2]))
720 #=========================== Fin de la méthode ==================================
722 #=========================== Début de la méthode =================================
724 def _tri_faces ( self, tb_caract, n_recur ):
725 """Trie les faces en fonction de leurs surfaces
728 :tb_caract: tableau des caractéristiques géométriques des faces
729 :n_recur: niveau de récursivité
732 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
738 nom_fonction = __name__ + "/_tri_faces"
739 blabla = "Dans {} :".format(nom_fonction)
741 # 1. Tri du tableau en fonction des surfaces
742 if self._verbose_max:
743 print_tab (n_recur, blabla)
744 print_tab (n_recur, "tb_caract brut : ", tb_caract)
745 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
746 if self._verbose_max:
747 print_tab (n_recur, "tb_caract trié :", tb_caract_1)
749 if self._verbose_max:
750 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
751 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
754 # 2. La surface suivante doit être différente, sinon ce n'est pas un solide mince
755 if ( len(tb_caract) > 2 ):
757 if self._verbose_max:
758 texte += "\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
760 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
761 if ( ecart < self._epsilon ):
762 message = "\nSolide '{}'\n".format(self.nom_solide)
763 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
764 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
765 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
766 if self._verbose_max:
767 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
768 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
769 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
771 self.d_statut_so[self.nom_solide] = -1
772 self.faces_pb_nb += 1
773 self.faces_pb_msg += message
775 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
777 #=========================== Fin de la méthode ==================================
779 #=========================== Début de la méthode =================================
781 def _verif_epaisseur ( self, epaisseur ):
782 """Contrôle de la validité de l'épaisseur
785 :epaisseur: épaisseur du solide
788 nom_fonction = __name__ + "/_verif_epaisseur"
789 blabla = "Dans {} :\n".format(nom_fonction)
791 if self._verbose_max:
793 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
794 texte += ". EP_MIN : {}".format(EP_MIN)
797 if ( epaisseur <= EP_MIN ):
798 message = "\nSolide '{}'\n".format(self.nom_solide)
799 message += ". Epaisseur : {}\n".format(epaisseur)
800 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
801 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
803 self.d_statut_so[self.nom_solide] = 2
804 self.faces_pb_nb += 1
805 self.faces_pb_msg += message
809 #print ("erreur = {}".format(erreur))
813 #=========================== Fin de la méthode ==================================
815 #=========================== Début de la méthode =================================
817 def _cree_face_mediane ( self, solide, caract_face_1, caract_face_2, n_recur ):
818 """Crée la face médiane entre deux autres
821 :solide: solide SHAPER à traiter
822 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
823 :n_recur: niveau de récursivité
826 :face: la face médiane créée
829 nom_fonction = __name__ + "/_cree_face_mediane"
830 blabla = "Dans {} :".format(nom_fonction)
832 if self._verbose_max:
833 print_tab (n_recur, blabla)
834 print_tab (n_recur, "face_1 : " ,caract_face_1)
835 print_tab (n_recur, "face_2 : " ,caract_face_2)
840 # 1. Forme de la face
841 forme = caract_face_1[2][0]
843 # 2. Traitement selon la forme de la face
845 if forme in ( "Disk" , "Plane", "Rectangle"):
846 erreur, face = self._cree_face_mediane_plane ( solide, caract_face_1, caract_face_2, n_recur )
848 # 2.2. Face cylindrique
849 elif ( forme == "Cylinder" ):
850 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
852 # 2.3. Face sphérique
853 elif ( forme == "Sphere" ):
854 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
857 elif ( forme == "Torus" ):
858 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
861 elif ( forme == "Cone" ):
862 erreur, face = self._cree_face_mediane_cone ( caract_face_1, caract_face_2, n_recur )
864 # 2.N. Face de forme inconnue
866 message = "\nSolide '{}'\n".format(self.nom_solide)
867 message += "sa face la plus grande est de forme : {}\n".format(forme)
868 message += "==> Impossible de créer la face médiane.\n"
870 self.d_statut_so[self.nom_solide] = -2
871 self.faces_pb_nb += 1
872 self.faces_pb_msg += message
874 # 3. Gestion de la face produite
877 self._cree_face_mediane_0 ( face, n_recur )
879 if self._verbose_max:
880 print_tab (n_recur, "Sortie de "+blabla)
884 #=========================== Fin de la méthode ==================================
886 #=========================== Début de la méthode =================================
888 def _cree_face_mediane_0 ( self, face, n_recur ):
889 """Gestion de la face médiane créée entre deux autres
892 :face: la face médiane créée
893 :n_recur: niveau de récursivité
896 nom_fonction = __name__ + "/_cree_face_mediane_0"
897 blabla = "Dans {} :".format(nom_fonction)
899 if self._verbose_max:
900 print_tab (n_recur, blabla)
903 nom_face = self.nom_solide+"_M"
904 if self._verbose_max:
905 print_tab (n_recur,"Nom de la face créée : ", nom_face)
906 #if ( self.nom_solide_aux != self.objet_principal.name() ):
908 nommage (face, nom_face)
910 # 2. Mémorisation de la face et de la fonction initiale
911 self.l_faces_m.append((face, self.fonction_0))
913 # 3. Couleur verte pour la face
914 couleur_objet (face, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
916 # 4. Changement de statut pour le solide
917 self.d_statut_so[self.nom_solide] = 1
919 if self._verbose_max:
920 print_tab (n_recur, "Sortie de _cree_face_mediane_0")
922 #=========================== Fin de la méthode ==================================
924 #=========================== Début de la méthode =================================
926 def _cree_face_mediane_plane ( self, solide, caract_face_1, caract_face_2, n_recur ):
927 """Crée la face médiane entre deux autres - cas des surfaces planes
930 :solide: l'objet solide à traiter
931 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
932 :n_recur: niveau de récursivité
935 :face: la face médiane
938 nom_fonction = __name__ + "/_cree_face_mediane_plane"
939 blabla = "Dans {} :".format(nom_fonction)
940 if self._verbose_max:
941 print_tab (n_recur, blabla)
943 # Caractéristiques des surfaces
944 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 )
946 # Contrôle de la validité de l'épaisseur
947 erreur = self._verif_epaisseur ( d_face_1_2 )
949 # Création de la face
951 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 )
957 #=========================== Fin de la méthode ==================================
959 #=========================== Début de la méthode =================================
961 def _cree_face_mediane_plane_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
962 """Crée la face médiane entre deux autres - cas des surfaces planes
964 Décodage des caractéristiques
967 :solide: l'objet solide à traiter
968 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
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]
995 # taille : une longueur caractéristique pour être certain de tout prendre
996 l_diag = self._calcul_lg_caract ( solide, n_recur )
998 if self._verbose_max:
999 print_tab (n_recur, "Taille englobante : ",taille)
1001 # 2. Distance entre les deux faces
1002 face_1 = caract_face_1[0]
1003 face_2 = caract_face_2[0]
1004 d_face_1_2 = GeomAlgoAPI_ShapeTools.minimalDistance(face_1, face_2)
1005 if self._verbose_max:
1006 print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
1008 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
1010 #=========================== Fin de la méthode ==================================
1012 #=========================== Début de la méthode =================================
1014 def _cree_face_mediane_plane_1 ( self, solide, coo_c, vnor, taille, d_face_1_2, n_recur ):
1015 """Crée la face médiane entre deux autres - cas des surfaces planes
1017 Création des objets de construction et de la face médiane
1020 :solide: l'objet solide à traiter
1021 :coo_c: coordonnées du centre de la base
1022 :vnor: coordonnées du vecteur normal
1023 :taille: estimation de la taille de la future face
1024 :d_face_1_2: la distance entre les deux faces
1025 :n_recur: niveau de récursivité
1028 :face: la face médiane
1031 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
1032 blabla = "Dans {} :".format(nom_fonction)
1033 if self._verbose_max:
1034 print_tab (n_recur, blabla)
1035 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1036 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
1037 print_tab (n_recur, "Taille : ", taille)
1038 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1041 _, v_norm, plan = self._cree_centre_axe_plan ( coo_c, vnor, self.nom_solide, n_recur )
1043 # 2. Création de l'esquisse
1044 sketch = self._cree_face_mediane_plane_1_a ( plan, taille, n_recur )
1047 face = self._cree_face_mediane_plane_1_b ( solide, sketch, v_norm, d_face_1_2, n_recur )
1049 #print ("fin de {}".format(nom_fonction))
1053 #=========================== Fin de la méthode ==================================
1055 #=========================== Début de la méthode =================================
1057 def _cree_face_mediane_plane_1_a ( self, plan, taille, n_recur ):
1058 """Crée la face médiane entre deux autres - cas des surfaces planes - l'esquisse
1062 :taille: estimation de la taille de la future face
1063 :n_recur: niveau de récursivité
1069 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_a"
1070 blabla = "Dans {} :".format(nom_fonction)
1071 if self._verbose_max:
1072 print_tab (n_recur, blabla)
1073 print_tab (n_recur, "Plan : {}".format(plan.name()))
1074 print_tab (n_recur, "taille : {}".format(taille))
1076 sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1077 sketch.execute(True)
1079 ### Create SketchLine
1080 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1081 SketchLine_1.execute(True)
1083 ### Create SketchLine
1084 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1085 SketchLine_2.execute(True)
1087 ### Create SketchLine
1088 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1089 SketchLine_3.execute(True)
1091 ### Create SketchLine
1092 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1093 SketchLine_4.execute(True)
1097 nom_sketch = "{}_esquisse".format(self.nom_solide)
1098 exec_nom (sketch,nom_sketch)
1100 #print ("fin de {}".format(nom_fonction))
1104 #=========================== Fin de la méthode ==================================
1106 #=========================== Début de la méthode =================================
1108 def _cree_face_mediane_plane_1_b ( self, solide, sketch, v_norm, d_face_1_2, n_recur ):
1109 """Crée la face médiane entre deux autres - cas des surfaces planes
1111 Création de la face médiane
1114 :solide: l'objet solide à traiter
1116 :v_norm: vecteur normal
1117 :d_face_1_2: la distance entre les deux faces
1118 :n_recur: niveau de récursivité
1121 :face: la face médiane
1124 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_b"
1125 blabla = "Dans {} :".format(nom_fonction)
1126 if self._verbose_max:
1127 print_tab (n_recur, blabla)
1128 print_tab (n_recur, "Esquisse : ", sketch.name())
1129 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1131 # 1. Copie du solide pour gérer les intersections
1132 #Copy_1 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1133 Copy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1134 nom = "{}_Copy_1".format(self.nom_solide_aux)
1135 exec_nom (Copy_1,nom)
1136 if self._verbose_max:
1137 print_tab (n_recur, "Après addMultiTranslation Copy_1 de nom ", nom)
1138 nom_solide = Copy_1.result().name()
1141 Recover_1 = model.addRecover(self.part_doc, Copy_1, [solide])
1142 nom = "{}_Recover_1".format(self.nom_solide_aux)
1143 exec_nom (Recover_1,nom)
1144 if self._verbose_max:
1145 print_tab (n_recur, "Après addRecover Recover_1 de nom ", nom)
1147 # 2. Création d'une face ; on la translate d'une demi-épaisseur.
1148 for iaux in range(2):
1150 # 2.1. Création d'une face à partir du sketch et translation perpendiculaire au plan de la face
1151 # On essaie les 2 côtés alternativement car on ne sait pas lequel sera le bon
1153 d_trans = -0.5*d_face_1_2*float(2*iaux-1)
1155 face = self._cree_face_mediane_plane_2 ( sketch.name(), v_norm.name(), nom_solide, d_trans, iaux, n_recur )
1157 # 2.2. Si on est du bon côté, alors on intersecte la face avec le solide et c'est bon
1159 face = self._cree_face_mediane_plane_11 ( face, Recover_1, n_recur )
1162 # 2.3. Si l'intersection est vide, on crée une nouvelle copie du solide avant de tester l'autre côté
1164 if self._verbose_max:
1165 print_tab (n_recur, "L'intersection est vide. On essaie l'autre côté")
1167 ### Create LinearCopy
1168 #Copy_2 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1169 Copy_2 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", Recover_1.result().name())], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1170 nom = "{}_Copy_2".format(self.nom_solide_aux)
1171 exec_nom (Copy_2,nom)
1172 if self._verbose_max:
1173 print_tab (n_recur, "Après addMultiTranslation Copy_2 de nom ", nom)
1174 nom_solide = Copy_2.result().name()
1176 #print ("fin de {}".format(nom_fonction))
1180 #=========================== Fin de la méthode ==================================
1182 #=========================== Début de la méthode =================================
1184 def _cree_face_mediane_plane_11 ( self, face, Recover_1, n_recur ):
1185 """Crée la face médiane entre deux autres - cas des surfaces planes
1187 Création des objets de construction et de la face médiane
1190 :face: la face médiane
1191 :Recover_1: la récupératiuon du solide
1192 :n_recur: niveau de récursivité
1195 :face: la face médiane
1198 nom_fonction = __name__ + "/_cree_face_mediane_plane_11"
1199 blabla = "Dans {} :".format(nom_fonction)
1200 if self._verbose_max:
1201 print_tab (n_recur, blabla)
1202 print_tab (n_recur, "face : ", face.name())
1204 # Si on traite un objet solide unique, on le récupère
1205 if ( self.nom_solide_aux == self.objet_principal.name() ):
1206 if self._verbose_max:
1207 print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1208 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1209 nom = "{}_Recover_2".format(self.nom_solide_aux)
1210 exec_nom (Recover_2,nom)
1212 nb_inter = face.result().numberOfSubs()
1213 if self._verbose_max:
1214 print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1217 face = self._cree_face_mediane_plane_3 ( face )
1221 #=========================== Fin de la méthode ==================================
1223 #=========================== Début de la méthode =================================
1225 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, d_trans, icpt, n_recur ):
1226 """Crée la face médiane entre deux autres - cas des surfaces planes
1228 Intersection de la face avec le solide
1231 :nom_sketch: nom de l'esquisse
1232 :nom_normal: nom du vecteur normal
1233 :nom_solide: nom du solide à intersecter
1234 :d_trans: la distance de translation
1235 :icpt: numéro de la tentative
1238 :face: la face médiane
1241 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1242 blabla = "Dans {} :".format(nom_fonction)
1243 if self._verbose_max:
1244 print_tab (n_recur, blabla)
1245 print_tab (n_recur, "nom_sketch : ", nom_sketch)
1246 print_tab (n_recur, "nom_normal : ", nom_normal)
1247 print_tab (n_recur, "nom_solide : ", nom_solide)
1248 print_tab (n_recur, "d_trans : ", d_trans)
1250 # Création d'une face
1251 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1252 nom = "{}_Face_1_{}".format(self.nom_solide_aux,icpt)
1253 exec_nom (Face_1,nom)
1254 if self._verbose_max:
1255 print_tab (n_recur, "Après addFace pour Face_1 de nom ", nom)
1258 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)
1259 nom = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1260 exec_nom (Translation_1,nom)
1261 if self._verbose_max:
1262 print_tab (n_recur, "Après addTranslation pour Translation_1 de nom ", nom)
1263 Translation_1.result().setColor(85, 0, 255)
1265 # Intersection de cette face avec le solide initial
1266 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", Translation_1.result().name())], keepSubResults = True)
1271 #=========================== Fin de la méthode ==================================
1273 #=========================== Début de la méthode =================================
1275 def _cree_face_mediane_plane_3 ( self, face ):
1276 """Crée la face médiane entre deux autres - cas des surfaces planes
1278 Fusion des 2 intersections
1281 :face: la face médiane composée de plusieurs intersections
1284 :face_m: la face médiane
1287 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1288 blabla = "Dans {} :\n".format(nom_fonction)
1289 if self._verbose_max:
1293 # Nommage des sous-objets
1295 for iaux in range(face.result().numberOfSubs()):
1296 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1297 face.result().subResult(iaux).setName(nom)
1298 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1301 if self._verbose_max:
1302 print ("Fusion de {} faces.".format(len(l_fuse)))
1303 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1304 face_m.execute(True)
1308 #=========================== Fin de la méthode ==================================
1310 #=========================== Début de la méthode =================================
1312 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1313 """Crée la face médiane entre deux autres - cas des cylindres
1316 :solide: solide SHAPER à traiter
1317 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1318 :n_recur: niveau de récursivité
1321 :face: la face médiane
1324 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1325 blabla = "Dans {} :".format(nom_fonction)
1328 if self._verbose_max:
1329 print_tab (n_recur, blabla)
1330 print_tab (n_recur, "face_1 : ", caract_face_1)
1331 print_tab (n_recur, "face_2 : ", caract_face_2)
1333 # Caractéristiques des cylindres
1334 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 )
1336 # Contrôle de la validité de l'épaisseur
1337 erreur = self._verif_epaisseur ( epaisseur )
1339 # Création de la face
1341 face = self._cree_face_mediane_cylindre_1 ( (coo_x, coo_y, coo_z), (axe_x, axe_y, axe_z), rayon, hauteur, n_recur )
1343 couleur_objet (solide, n_recur, coul_r=0, coul_g=0, coul_b=255, verbose=self._verbose_max)
1348 #=========================== Fin de la méthode ==================================
1350 #=========================== Début de la méthode =================================
1352 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1353 """Crée la face médiane entre deux autres - cas des cylindres
1355 Décodage des caractéristiques
1358 :solide: l'objet solide à traiter
1359 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1360 :n_recur: niveau de récursivité
1363 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1364 :axe_x, axe_y, axe_z: coordonnées de l'axe
1365 :rayon: rayon moyen entre les deux faces
1366 :hauteur: hauteur du cylindre
1367 :epaisseur: épaisseur de l'interface entre les deux faces
1370 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1371 blabla = "Dans {} :".format(nom_fonction)
1373 if self._verbose_max:
1374 print_tab (n_recur, blabla)
1375 print_tab (n_recur, "face_1 : ", caract_face_1)
1376 print_tab (n_recur, "face_2 : ", caract_face_2)
1378 # Coordonnées du centre de la base
1379 coo_x = caract_face_1[2][1]
1380 coo_y = caract_face_1[2][2]
1381 coo_z = caract_face_1[2][3]
1382 # Coordonnées de l'axe
1383 axe_x = caract_face_1[2][4]
1384 axe_y = caract_face_1[2][5]
1385 axe_z = caract_face_1[2][6]
1387 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1388 # Hauteur : une longueur caractéristique pour être certain de tout prendre
1389 l_diag = self._calcul_lg_caract ( solide, n_recur )
1390 hauteur = 10.*l_diag
1391 if self._verbose_max:
1392 print_tab (n_recur, "Hauteur englobante : ", hauteur)
1394 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1396 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1398 #=========================== Fin de la méthode ==================================
1400 #=========================== Début de la méthode =================================
1402 def _cree_face_mediane_cylindre_1 ( self, coo_c, v_axe, rayon, hauteur, n_recur ):
1403 """Crée la face médiane entre deux autres - cas des cylindres
1405 Création des objets temporaires et de la face externe du cylindre support
1408 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1409 :axe_x, axe_y, axe_z: coordonnées de l'axe
1410 :rayon: rayon moyen entre les deux faces
1411 :hauteur: hauteur du cylindre
1412 :n_recur: niveau de récursivité
1415 :face: la face médiane
1417 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1418 blabla = "Dans {} :\n".format(nom_fonction)
1420 # Les caractéristiques du cylindre à créer
1421 if self._verbose_max:
1422 print_tab (n_recur, blabla)
1423 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1424 print_tab (n_recur, "Axe : ({}, {}, {})".format(v_axe[0], v_axe[1], v_axe[2]))
1425 print_tab (n_recur, "Rayon : ", rayon)
1426 print_tab (n_recur, "Hauteur : ", hauteur)
1428 # Création du point central
1429 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
1430 nom_centre = "{}_centre".format(self.nom_solide)
1431 exec_nom (centre,nom_centre)
1432 if self.fonction_0 is None:
1433 self.fonction_0 = centre
1435 # Création du vecteur axial
1436 axe = model.addAxis(self.part_doc, v_axe[0], v_axe[1], v_axe[2])
1437 nom_axe = "{}_vecteur".format(self.nom_solide)
1438 exec_nom (axe,nom_axe)
1440 # Création du cylindre en volume, de rayon médian
1441 Cylinder_1 = model.addCylinder(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon, hauteur)
1442 nom = "{}_Cylinder_1".format(self.nom_solide)
1443 exec_nom (Cylinder_1,nom)
1445 # Le groupe de la surface
1446 Group_1 = model.addGroup(self.part_doc, "Faces", [model.selection("FACE", "{}/Face_1".format(nom))])
1447 nom = "{}_Group_1".format(self.nom_solide)
1448 exec_nom (Group_1,nom)
1450 # Création du cylindre en surface
1451 cylindre = model.addGroupShape(self.part_doc, [model.selection("COMPOUND", nom)])
1452 nom = "{}_cylindre".format(self.nom_solide)
1453 exec_nom (cylindre, nom, (85, 0, 255))
1456 Translation_1 = model.addTranslation(self.part_doc, [model.selection("COMPOUND", nom)], axis = model.selection("EDGE", nom_axe), distance = -0.5*hauteur, keepSubResults = True)
1457 nom = "{}_Translation_1".format(self.nom_solide)
1458 exec_nom (Translation_1,nom)
1460 # Intersection de la face cylindrique avec le solide initial
1461 face = self._creation_face_inter ( nom )
1465 #=========================== Fin de la méthode ==================================
1467 #=========================== Début de la méthode =================================
1469 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1470 """Crée la face médiane entre deux autres - cas des sphères
1473 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1474 :n_recur: niveau de récursivité
1477 :face: la face médiane
1480 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1481 blabla = "Dans {} :".format(nom_fonction)
1484 if self._verbose_max:
1485 print_tab (n_recur, blabla)
1486 print_tab (n_recur, "face_1 : ", caract_face_1)
1487 print_tab (n_recur, "face_2 : ", caract_face_2)
1489 # Caractéristiques des sphères
1490 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1492 # Contrôle de la validité de l'épaisseur
1493 erreur = self._verif_epaisseur ( epaisseur )
1495 # Création de la face
1497 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1503 #=========================== Fin de la méthode ==================================
1505 #=========================== Début de la méthode =================================
1507 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1508 """Crée la face médiane entre deux autres - cas des sphères
1510 Décodage des caractéristiques
1513 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1514 :n_recur: niveau de récursivité
1517 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1518 :rayon: rayon moyen entre les deux faces
1519 :epaisseur: épaisseur de l'interface entre les deux faces
1522 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1523 blabla = "Dans {} :".format(nom_fonction)
1526 if self._verbose_max:
1527 print_tab (n_recur, blabla)
1528 print_tab (n_recur, "face_1 : ", caract_face_1)
1529 print_tab (n_recur, "face_2 : ", caract_face_2)
1531 # Coordonnées du centre de la sphère
1532 coo_x = caract_face_1[2][1]
1533 coo_y = caract_face_1[2][2]
1534 coo_z = caract_face_1[2][3]
1536 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1538 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1540 return coo_x, coo_y, coo_z, rayon, epaisseur
1542 #=========================== Fin de la méthode ==================================
1544 #=========================== Début de la méthode =================================
1546 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1547 """Crée la face médiane entre deux autres - cas des sphères
1549 Création des objets de construction et de la face externe de la sphère support
1552 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1553 :rayon: rayon moyen entre les deux faces
1556 :face: la face externe de la sphère support
1559 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1560 blabla = "Dans {} :\n".format(nom_fonction)
1562 # Les caractéristiques de la sphère à créer
1563 if self._verbose_max:
1565 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1566 texte += "Rayon : {}".format(rayon)
1569 # Création du point central
1570 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1571 nom_centre = "{}_centre".format(self.nom_solide)
1572 exec_nom (centre,nom_centre)
1573 if self.fonction_0 is None:
1574 self.fonction_0 = centre
1576 # Création de la sphère en volume, de rayon médian
1577 Sphere_1 = model.addSphere(self.part_doc, model.selection("VERTEX", nom_centre), rayon)
1578 nom = "{}_Sphere_1".format(self.nom_solide)
1579 exec_nom (Sphere_1,nom)
1581 # Le groupe de la surface
1582 Group_1 = model.addGroup(self.part_doc, "Faces", [model.selection("FACE", "{}/Face_1".format(nom))])
1583 nom = "{}_Group_1".format(self.nom_solide)
1584 exec_nom (Group_1,nom)
1586 # Création de la sphère en surface
1587 sphere = model.addGroupShape(self.part_doc, [model.selection("COMPOUND", nom)])
1589 nom = "{}_sphere".format(self.nom_solide)
1590 exec_nom (sphere, nom, (85, 0, 255))
1592 # Intersection de la face sphérique avec le solide initial
1593 face = self._creation_face_inter ( nom )
1597 #=========================== Fin de la méthode ==================================
1599 #=========================== Début de la méthode =================================
1601 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1602 """Crée la face médiane entre deux autres - cas des tores
1605 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1606 :n_recur: niveau de récursivité
1609 :face: la face médiane
1612 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1613 blabla = "Dans {} :".format(nom_fonction)
1616 if self._verbose_max:
1617 print_tab (n_recur, blabla)
1618 print_tab (n_recur, "face_1 : ", caract_face_1)
1619 print_tab (n_recur, "face_2 : ", caract_face_2)
1621 # Caractéristiques des tores
1622 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 )
1624 # Contrôle de la validité de l'épaisseur (bidon)
1625 erreur = self._verif_epaisseur ( EP_MIN*10. )
1627 # Création de la face
1629 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1635 #=========================== Fin de la méthode ==================================
1637 #=========================== Début de la méthode =================================
1639 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1640 """Crée la face médiane entre deux autres - cas des tores
1642 Décodage des caractéristiques
1645 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1646 :n_recur: niveau de récursivité
1649 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1650 :axe_x, axe_y, axe_z: coordonnées de l'axe
1651 :rayon_1 : rayon principal
1652 :rayon_2 : rayon secondaire
1655 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1656 blabla = "Dans {} :".format(nom_fonction)
1659 if self._verbose_max:
1660 print_tab (n_recur, blabla)
1661 print_tab (n_recur, "face_1 : ", caract_face_1)
1662 print_tab (n_recur, "face_2 : ", caract_face_2)
1664 # Coordonnées du centre du tore
1665 coo_x = caract_face_1[2][1]
1666 coo_y = caract_face_1[2][2]
1667 coo_z = caract_face_1[2][3]
1668 # Coordonnées de l'axe
1669 axe_x = caract_face_1[2][4]
1670 axe_y = caract_face_1[2][5]
1671 axe_z = caract_face_1[2][6]
1673 rayon_1 = caract_face_2[2][7]
1674 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1676 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1678 #=========================== Fin de la méthode ==================================
1680 #=========================== Début de la méthode =================================
1682 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1683 """Crée la face médiane entre deux autres - cas des tores
1685 Création des objets de construction et de la face externe du tore support
1688 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1689 :axe_x, axe_y, axe_z: coordonnées de l'axe
1690 :rayon_1 : rayon principal
1691 :rayon_2 : rayon secondaire
1694 :face: la face externe du tore support
1697 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1698 blabla = "Dans {} :\n".format(nom_fonction)
1701 if self._verbose_max:
1703 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1704 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1705 texte += "Rayon principal : {}\n".format(rayon_1)
1706 texte += "Rayon secondaire : {}".format(rayon_2)
1709 # Création du point central
1710 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1711 nom_centre = "{}_centre".format(self.nom_solide)
1712 exec_nom (centre,nom_centre)
1715 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1716 nom_axe = "{}_axe".format(self.nom_solide)
1717 exec_nom (axe,nom_axe)
1719 # Création d'un plan passant par ce centre et cet axe
1720 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
1721 nom_plan = "{}_plan".format(self.nom_solide)
1722 exec_nom (plan,nom_plan)
1724 # Création de l'esquisse
1725 nom_par_1 = "{}_R_1".format(self.nom_solide)
1726 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1727 nom_par_2 = "{}_R_2".format(self.nom_solide)
1728 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1730 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1731 sketch.execute(True)
1733 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1734 SketchProjection_1.execute(True)
1735 SketchPoint_1 = SketchProjection_1.createdFeature()
1736 SketchPoint_1.execute(True)
1738 SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1739 SketchProjection_2.execute(True)
1740 SketchLine_1 = SketchProjection_2.createdFeature()
1741 SketchLine_1.execute(True)
1743 SketchPoint_2 = sketch.addPoint(rayon_1, 0.)
1744 SketchPoint_2.execute(True)
1745 sketch.setDistance(SketchPoint_1.result(), SketchPoint_2.coordinates(), nom_par_1, True)
1747 SketchLine_2 = sketch.addLine(0., 0., rayon_1, 0.)
1748 SketchLine_2.execute(True)
1749 SketchLine_2.setAuxiliary(True)
1750 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1751 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_2.endPoint())
1752 sketch.setPerpendicular(SketchLine_1.result(), SketchLine_2.result())
1754 SketchCircle_1 = sketch.addCircle(0., 0., rayon_2)
1755 SketchCircle_1.execute(True)
1756 sketch.setCoincident(SketchPoint_2.result(), SketchCircle_1.center())
1757 sketch.setRadius(SketchCircle_1.results()[1], nom_par_2)
1761 nom_sketch = "{}_esquisse".format(self.nom_solide)
1762 exec_nom (sketch,nom_sketch)
1764 # Création du tore complet
1765 nom_tore = "{}_tore".format(self.nom_solide)
1766 self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_tore )
1768 # Intersection de la face torique avec le solide initial
1769 face = self._creation_face_inter ( nom_tore )
1773 #=========================== Fin de la méthode ==================================
1775 #=========================== Début de la méthode =================================
1777 def _cree_face_mediane_cone ( self, caract_face_1, caract_face_2, n_recur ):
1778 """Crée la face médiane entre deux autres - cas des cones
1781 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1782 :n_recur: niveau de récursivité
1785 :face: la face médiane
1788 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1789 blabla = "Dans {} :".format(nom_fonction)
1792 if self._verbose_max:
1793 print_tab (n_recur, blabla)
1794 print_tab (n_recur, "face_1 : ", caract_face_1)
1795 print_tab (n_recur, "face_2 : ", caract_face_2)
1797 # Caractéristiques des cones
1798 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 )
1800 # Contrôle de la validité de l'épaisseur (bidon)
1801 erreur = self._verif_epaisseur ( EP_MIN*10. )
1803 # Création de la face
1805 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1811 #=========================== Fin de la méthode ==================================
1813 #=========================== Début de la méthode =================================
1815 def _cree_face_mediane_cone_0 ( self, caract_face_1, caract_face_2, n_recur ):
1816 """Crée la face médiane entre deux autres - cas des cones
1818 Décodage des caractéristiques
1821 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1822 :n_recur: niveau de récursivité
1825 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1826 :axe_x, axe_y, axe_z: coordonnées de l'axe
1827 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1828 :hauteur: hauteur du cone
1831 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1832 blabla = "Dans {} :".format(nom_fonction)
1835 if self._verbose_max:
1836 print_tab (n_recur, blabla)
1837 print_tab (n_recur, "face_1 : ", caract_face_1)
1838 print_tab (n_recur, "face_2 : ", caract_face_2)
1840 # Coordonnées du centre de la base
1841 coo_x = caract_face_1[2][1]
1842 coo_y = caract_face_1[2][2]
1843 coo_z = caract_face_1[2][3]
1844 # Coordonnées de l'axe
1845 axe_x = caract_face_1[2][4]
1846 axe_y = caract_face_1[2][5]
1847 axe_z = caract_face_1[2][6]
1849 rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1850 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1852 hauteur = caract_face_1[2][9]
1855 if self._verbose_max:
1856 print_tab (n_recur, "coo_x : ", coo_x)
1857 print_tab (n_recur, "coo_y : ", coo_y)
1858 print_tab (n_recur, "coo_z : ", coo_z)
1859 print_tab (n_recur, "axe_x : ", axe_x)
1860 print_tab (n_recur, "axe_y : ", axe_y)
1861 print_tab (n_recur, "axe_z : ", axe_z)
1862 print_tab (n_recur, "rayon_1 : ", rayon_1)
1863 print_tab (n_recur, "rayon_2 : ", rayon_2)
1864 print_tab (n_recur, "hauteur : ", hauteur)
1866 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1868 #=========================== Fin de la méthode ==================================
1870 #=========================== Début de la méthode =================================
1872 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1873 """Crée la face médiane entre deux autres - cas des cones
1875 Création des objets de construction et de la face externe du cone support
1878 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1879 :axe_x, axe_y, axe_z: coordonnées de l'axe
1880 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1881 :hauteur: hauteur du cone
1884 :face: la face externe du cone support
1886 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1887 blabla = "Dans {} :\n".format(nom_fonction)
1890 if self._verbose_max:
1892 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1893 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1894 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1895 texte += "Hauteur : {}".format(hauteur)
1898 # 1. Création du point central de la base, côté rayon_1
1899 centre_1 = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1900 nom_centre_1 = "{}_centre_1".format(self.nom_solide)
1901 exec_nom (centre_1,nom_centre_1)
1903 # 2. Création du point central, du côté de rayon_2
1904 centre_2 = model.addPoint(self.part_doc, coo_x+hauteur*axe_x, coo_y+hauteur*axe_y, coo_z+hauteur*axe_z)
1905 nom_centre_2 = "{}_centre_2".format(self.nom_solide)
1906 exec_nom (centre_2,nom_centre_2)
1908 # 3. Création de l'axe
1909 axe = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre_1), model.selection("VERTEX", nom_centre_2))
1910 nom_axe = "{}_axe".format(self.nom_solide)
1911 exec_nom (axe,nom_axe)
1913 # 4. Création d'un plan passant par le centre de la base et l'axe
1914 # 4.1. Création d'un vecteur perpendiculaire à l'axe
1916 v_perp = model.addAxis(self.part_doc, -coeff*axe_y, coeff*axe_x, 0.)
1917 nom_v_perp = "{}_v_perp".format(self.nom_solide)
1918 exec_nom (v_perp,nom_v_perp)
1919 # 4.2. Création du plan
1920 plan = model.addPlane(self.part_doc, model.selection("EDGE",nom_v_perp), model.selection("VERTEX", nom_centre_1), True)
1921 nom_plan = "{}_plan".format(self.nom_solide)
1922 exec_nom (plan,nom_plan)
1925 nom_par_1 = "{}_R_1".format(self.nom_solide)
1926 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1927 nom_par_2 = "{}_R_2".format(self.nom_solide)
1928 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1929 nom_par_3 = "{}_H".format(self.nom_solide)
1930 model.addParameter(self.part_doc, "{}".format(nom_par_3), "{}".format(hauteur))
1932 # 6. Création de l'esquisse
1934 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1935 sketch.execute(True)
1937 # 6.1. Projection des centres et de l'axe
1938 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre_1), False)
1939 SketchProjection_1.execute(True)
1940 SketchPoint_1 = SketchProjection_1.createdFeature()
1941 SketchPoint_1.execute(True)
1942 sk_coo_x_1 = SketchAPI_Point(SketchPoint_1).coordinates().x()
1943 sk_coo_y_1 = SketchAPI_Point(SketchPoint_1).coordinates().y()
1945 SketchProjection_2 = sketch.addProjection(model.selection("VERTEX", nom_centre_2), False)
1946 SketchProjection_2.execute(True)
1947 SketchPoint_2 = SketchProjection_2.createdFeature()
1948 SketchPoint_2.execute(True)
1949 sk_coo_x_2 = SketchAPI_Point(SketchPoint_2).coordinates().x()
1950 sk_coo_y_2 = SketchAPI_Point(SketchPoint_2).coordinates().y()
1952 SketchProjection_3 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1953 SketchProjection_3.execute(True)
1954 SketchLine_0 = SketchProjection_3.createdFeature()
1955 SketchLine_0.execute(True)
1957 # 6.2. Lignes perpendiculaires à l'axe passant par les centres
1958 SketchLine_1 = sketch.addLine(sk_coo_x_1, sk_coo_y_1, sk_coo_x_1+rayon_1, sk_coo_y_1)
1959 SketchLine_1.execute(True)
1960 SketchLine_1.setAuxiliary(True)
1961 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.startPoint())
1962 sketch.setPerpendicular(SketchLine_0.result(), SketchLine_1.result())
1963 sketch.setLength(SketchLine_1.result(), nom_par_1)
1965 SketchLine_2 = sketch.addLine(sk_coo_x_2, sk_coo_y_2, sk_coo_x_2+rayon_2, sk_coo_y_2)
1966 SketchLine_2.execute(True)
1967 SketchLine_2.setAuxiliary(True)
1968 sketch.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_2.startPoint())
1969 sketch.setPerpendicular(SketchLine_0.result(), SketchLine_2.result())
1970 sketch.setLength(SketchLine_2.result(), nom_par_2)
1972 # 6.3. Ligne joignant les extrémités des précédentes et point milieu
1973 SketchLine_3 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
1974 SketchLine_3.execute(True)
1975 sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_1.endPoint())
1976 sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_2.endPoint())
1977 SketchLine_3.setAuxiliary(True)
1978 SketchPoint_3 = sketch.addPoint(sk_coo_x_1, sk_coo_y_1)
1979 SketchPoint_3.execute(True)
1980 sketch.setMiddlePoint(SketchLine_3.result(), SketchPoint_3.coordinates())
1982 # 6.4. Ligne support de la future révolution
1983 SketchLine_4 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
1984 SketchLine_4.execute(True)
1985 sketch.setMiddlePoint(SketchLine_4.result(), SketchPoint_3.coordinates())
1986 sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_4.result())
1987 sketch.setLength(SketchLine_4.result(), "1.2*{}".format(nom_par_3))
1991 nom_sketch = "{}_esquisse".format(self.nom_solide)
1992 exec_nom (sketch,nom_sketch)
1994 # Création du cone complet
1995 nom_cone = "{}_cone".format(self.nom_solide)
1996 self._cree_revolution ( nom_sketch, nom_centre_1, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_cone )
1998 # Intersection de la face conique avec le solide initial
1999 face = self._creation_face_inter ( nom_cone )
2003 #=========================== Fin de la méthode ==================================
2005 #=========================== Début de la méthode =================================
2007 def _cree_centre_axe_plan ( self, coo_c, vect, prefixe, n_recur ):
2008 """Crée un centre, un axe, un plan
2011 :coo_c: coordonnées du centre de la base
2012 :vect: coordonnées du vecteur
2013 :prefix: prefixe du nom des objets
2014 :n_recur: niveau de récursivité
2018 :normal: vecteur normal
2022 nom_fonction = __name__ + "/_cree_centre_axe_plan"
2023 blabla = "Dans {} :".format(nom_fonction)
2024 if self._verbose_max:
2025 print_tab (n_recur, blabla)
2026 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
2027 print_tab (n_recur, "Normale : ({}, {}, {})".format(vect[0], vect[1], vect[2]))
2029 # Création du point central
2030 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
2031 nom_centre = "{}_centre".format(prefixe)
2032 exec_nom (centre,nom_centre)
2033 if self.fonction_0 is None:
2034 self.fonction_0 = centre
2036 # Création du vecteur
2037 vecteur = model.addAxis(self.part_doc, vect[0], vect[1], vect[2])
2038 nom_vect = "{}_vecteur".format(prefixe)
2039 exec_nom (vecteur,nom_vect)
2041 # Création du plan perpendiculaire au vecteur normal
2042 plan = model.addPlane(self.part_doc, model.selection("EDGE", vecteur.name()), model.selection("VERTEX", centre.name()), True)
2043 nom_plan = "{}_plan".format(prefixe)
2044 exec_nom (plan,nom_plan)
2046 #print ("fin de {}".format(nom_fonction))
2048 return centre, vecteur, plan
2050 #=========================== Fin de la méthode ==================================
2052 #=========================== Début de la méthode =================================
2054 def _calcul_lg_caract ( self, objet, n_recur ):
2055 """Crée une longueur caractéristique de l'objet
2058 :objet: l'objet à traiter
2059 :n_recur: niveau de récursivité
2062 :l_caract: longueur caractéristique de l'objet
2065 nom_fonction = __name__ + "/_calcul_lg_caract"
2066 blabla = "Dans {} :".format(nom_fonction)
2068 if self._verbose_max:
2069 print_tab (n_recur, blabla)
2071 properties = model.getGeometryCalculation(self.part_doc,model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
2072 l_caract = properties[0]
2074 if self._verbose_max:
2075 print_tab (n_recur, "Longueur caractéristique : ", l_caract)
2079 #=========================== Fin de la méthode ==================================
2081 #=========================== Début de la méthode =================================
2083 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
2084 """Crée un volume de révolution
2087 :nom_sketch: nom de l'esquisse à révolutionner
2088 :nom_centre: nom du point associé au centre du volume de révolution
2089 :coo_x, coo_y, coo_z: coordonnées du centre du tore
2090 :axe_x, axe_y, axe_z: coordonnées de l'axe
2091 :rayon_1 : rayon principal
2092 :rayon_2 : rayon secondaire
2093 :nom_objet: nom de l'objet 2D créé
2096 nom_fonction = __name__ + "/_cree_revolution"
2097 blabla = "Dans {} :\n".format(nom_fonction)
2099 if self._verbose_max:
2101 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
2102 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
2105 # Création d'un point décalé par rapport au point central
2106 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
2107 nom_point = "{}_point".format(self.nom_solide)
2108 exec_nom (point,nom_point)
2110 # Création de l'axe de la rotation
2111 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
2112 nom_axe_r = "{}_axe_r".format(self.nom_solide)
2113 exec_nom (axe_r,nom_axe_r)
2115 # Création de l'objet complet
2116 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
2117 exec_nom (objet, nom_objet, (85, 0, 255))
2119 #=========================== Fin de la méthode ==================================
2121 #=========================== Début de la méthode =================================
2123 def _creation_face_inter ( self, nom_objet ):
2124 """Crée la face par intersection entre l'objet initial et une face complète
2126 . Repère la face principale de l'objet support
2127 . Réalise l'intersection avec le solide initial
2130 :nom_objet: nom de l'objet 2D créé
2133 :face: la face externe de l'objet support intersecté avec le solide initial
2136 nom_fonction = __name__ + "/_creation_face_inter"
2137 blabla = "Dans {} :\n".format(nom_fonction)
2139 if self._verbose_max:
2142 face = model.addCommon(self.part_doc, [model.selection("SOLID", self.nom_solide_aux), model.selection("FACE", nom_objet)], keepSubResults = True)
2147 #=========================== Fin de la méthode ==================================
2149 #=========================== Début de la méthode =================================
2151 def face_mediane_solide (self, solide, n_recur=0):
2152 """Calcul de la face médiane pour un solide
2155 :solide: solide SHAPER à traiter
2156 :n_recur: niveau de récursivité
2159 :erreur: code d'erreur
2160 :message: message d'erreur
2163 nom_fonction = __name__ + "/face_mediane_solide"
2164 blabla = "Dans {} :".format(nom_fonction)
2166 if self._verbose_max:
2167 print_tab (n_recur, blabla, saut_av=True)
2169 print_tab (n_recur, "Traitement du solide ", solide.name())
2178 # 2. Calcul des caractéristiques géométriques des faces
2180 tb_caract = self._calcul_caract_faces ( solide, n_recur )
2182 # 3. Tri des faces en fonction de leurs caractéristiques géométriques
2184 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract, n_recur )
2188 # 4. Création de la face médiane
2190 erreur, face = self._cree_face_mediane ( solide, caract_face_1, caract_face_2, n_recur )
2191 if ( erreur or ( face is None ) ):
2194 # 6. Exportation step
2196 if self._export_step:
2197 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2198 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2199 export.execute(True)
2206 if ( erreur and self._verbose_max ):
2207 print (blabla, message)
2209 return erreur, message
2211 #=========================== Fin de la méthode ==================================
2213 #=========================== Début de la méthode =================================
2215 def _traitement_objet (self, solide, n_recur=0):
2216 """Traitement d'un objet
2219 :solide: solide SHAPER à traiter
2220 :n_recur: niveau de récursivité
2223 :erreur: code d'erreur
2224 :message: message d'erreur
2227 nom_fonction = __name__ + "/_traitement_objet"
2228 blabla = "Dans {} :".format(nom_fonction)
2230 if self._verbose_max:
2231 print_tab (n_recur, blabla, saut_av=True)
2232 texte = "solide = {} ".format(solide.name())
2233 print_tab (n_recur, texte, solide)
2235 # 1. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2236 # Attention à ne pas recréer le répertoire à chaque fois
2237 if self._export_step:
2239 if self.rep_step is None:
2241 if self._verbose_max:
2242 print_tab (n_recur, "Préparation de l'export STEP")
2244 if self.ficcao is None:
2245 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2247 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2248 if os.path.isdir(self.rep_step):
2249 l_aux = os.listdir(self.rep_step)
2250 for nomfic in l_aux:
2251 os.remove(os.path.join(self.rep_step,nomfic))
2253 os.mkdir(self.rep_step)
2255 if self._verbose_max:
2256 print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2258 # 2. Calcul réel de la face médiane
2260 erreur, message = self.face_mediane_solide (solide, n_recur)
2262 return erreur, message
2264 #=========================== Fin de la méthode ==================================
2266 #=========================== Début de la méthode =================================
2268 def surf_fic_cao (self, ficcao, nom_objet=None):
2269 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2272 :ficcao: fichier de l'objet à traiter
2273 :nom_objet: un nom à donner à l'objet à traiter
2276 :erreur: code d'erreur
2277 :message: message d'erreur
2280 nom_fonction = __name__ + "/surf_fic_cao"
2281 blabla = "Dans {} :".format(nom_fonction)
2283 if self._verbose_max:
2293 if self.affiche_aide_globale:
2296 # 1. Définition de la pièce
2298 self.part_doc = model.activeDocument()
2299 if ( self.part_doc.kind() == "PartSet" ):
2300 part = model.addPart(self.part_doc)
2301 self.part_doc = part.document()
2303 # 2. Import de la CAO
2305 self.ficcao = ficcao
2306 print ("Traitement du fichier {}".format(ficcao))
2308 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2312 # 3. Calcul des surfaces
2314 erreur, message = self.surf_objet_shaper ( objet )
2321 if ( erreur and self._verbose_max ):
2322 print (blabla, message)
2324 return erreur, message
2326 #=========================== Fin de la méthode ==================================
2328 #=========================== Début de la méthode =================================
2330 def surf_objet_shaper (self, objet):
2331 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2334 :objet: objet à traiter
2337 :erreur: code d'erreur
2338 :message: message d'erreur
2341 nom_fonction = __name__ + "/surf_objet_shaper"
2342 blabla = "Dans {} :".format(nom_fonction)
2344 if self._verbose_max:
2352 if self.affiche_aide_globale:
2355 # 1. Acquisition de la liste des noms des sous-objets solides
2357 self.d_statut_so = dict()
2358 self.l_noms_so = list()
2359 self.l_faces_m = list()
2361 _ = self._nom_sous_objets (objet, True)
2362 if self._verbose_max:
2363 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2365 # 2. Les faces médianes
2367 erreur, message = self._surf_objet_shaper_0 ( objet )
2371 # 3. Gestion des faces créées
2373 self._surf_objet_shaper_1 ( )
2375 # 4. Futur message pour le résultat
2377 if ( self._export_step and not erreur ):
2378 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2382 return erreur, message
2384 #=========================== Fin de la méthode ==================================
2386 #=========================== Début de la méthode =================================
2388 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2389 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2392 :objet: objet à traiter
2393 :n_recur: niveau de récursivité
2396 :erreur: code d'erreur
2397 :message: message d'erreur
2400 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2401 blabla = "Dans {} :".format(nom_fonction)
2403 if self._verbose_max:
2404 print_tab (n_recur, blabla)
2405 print_tab (n_recur, "n_recur = ", n_recur)
2412 # 1. Au premier passage, il faut récupérer la pièce SHAPER et garder la référence au résultat principal
2414 if ( n_recur == 0 ):
2415 self.part_doc = model.activeDocument()
2416 objet_0 = objet.result()
2417 self.objet_principal = objet_0
2418 objet_bis = objet.defaultResult().shape()
2419 if self._verbose_max:
2420 print_tab (0, "Examen de l'objet initial ", objet.result().name(), saut_av=True)
2421 print_tab (0, "Type python : ", type(objet))
2422 print_tab (0, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2425 if self._verbose_max:
2426 print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2427 print_tab (n_recur, "Type python : ", type(objet))
2428 print_tab (n_recur, "shapeType : ", objet.shapeType())
2430 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2432 nb_sub_results = objet_0.numberOfSubs()
2434 if self._verbose_max:
2435 print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType(), saut_av=True)
2436 print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2438 for n_sobj in range(nb_sub_results):
2440 # 2.1. Exploration récursive de l'arborescence
2442 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2449 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2451 if ( objet_0.shapeType() == "SOLID" ):
2452 erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2456 # 3. Futur message pour le résultat
2458 if self._export_step:
2459 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2463 return erreur, message
2465 #=========================== Fin de la méthode ==================================
2467 #=========================== Début de la méthode =================================
2469 def _surf_objet_shaper_1 (self, n_recur=0):
2470 """Gestion des surfaces médianes créées
2473 :n_recur: niveau de récursivité
2476 :erreur: code d'erreur
2477 :message: message d'erreur
2480 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2481 blabla = "Dans {} :\n".format(nom_fonction)
2483 if self._verbose_max:
2484 print_tab (n_recur, blabla)
2486 # 1. Informations sur les faces à problème
2488 if self.faces_pb_nb:
2489 if ( self.faces_pb_nb == 1 ):
2490 texte = "1 face pose"
2492 texte = "{} faces posent".format(self.faces_pb_nb)
2493 print_tab (n_recur, "{} problème.".format(texte), self.faces_pb_msg, saut_av=True)
2495 # 2. Si plus d'une face a été créée
2496 if ( len(self.l_faces_m) > 1 ):
2498 # 2.1. Partition du paquet de faces
2500 if self._verbose_max:
2501 print_tab (n_recur, "Partitionnnement des faces créées.")
2503 # 2.1.1. Pour une raison mystérieuse, il faut commencer par les faces entières, puis mettre les sous-faces éventuelles
2505 for (face,_) in self.l_faces_m:
2506 if not face.result().numberOfSubs():
2507 d_faces[face.name()] = [face.name()]
2508 for (face,_) in self.l_faces_m:
2509 nb_sub_results = face.result().numberOfSubs()
2512 for n_sobj in range(nb_sub_results):
2513 laux.append(face.result().subResult(n_sobj).name())
2514 d_faces[face.name()] = laux
2517 for _, laux in d_faces.items():
2518 for s_face_n in laux:
2519 l_objets.append(model.selection("FACE", s_face_n))
2521 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2522 nom = "{}_M".format(self.objet_principal.name())
2523 exec_nom (Partition_1,nom)
2526 for face_n, laux in d_faces.items():
2527 Partition_1.result().subResult(iaux).setName("{}".format(face_n))
2528 if ( len(laux) > 1 ):
2529 for jaux, s_face_n in enumerate(laux):
2530 Partition_1.result().subResult(iaux).subResult(jaux).setName("{}_M".format(s_face_n))
2532 couleur_objet (Partition_1, n_recur, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
2534 # 2.2. Récupération des faces individuelles
2536 if self._verbose_max:
2537 print_tab (n_recur, "Récupération des faces individuelles.")
2540 for iaux, (face,_) in enumerate(self.l_faces_m):
2541 l_objets.append(face.result())
2543 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2544 for iaux, (face,_) in enumerate(self.l_faces_m):
2545 Recover_1.results()[iaux].setName("{}".format(face.name()))
2546 Recover_1.results()[iaux].setColor(0, 170, 0)
2547 nb_sub_results = Recover_1.results()[iaux].numberOfSubs()
2548 for n_sobj in range(nb_sub_results):
2549 Recover_1.results()[iaux].subResult(n_sobj).setName("{}_{}".format(face.name(),n_sobj))
2550 Recover_1.results()[iaux].subResult(n_sobj).setColor(0, 170, 0)
2552 # 3. Mise en dossier
2554 if self._verbose_max:
2555 print_tab (n_recur, "Mise en dossier.")
2557 for (face,fonction_0) in self.l_faces_m:
2558 nom = face.name()[:-2]
2559 if self._verbose_max:
2560 print ( "Dossier {} de {} à {}".format(nom,fonction_0.name(),face.name()))
2561 dossier = model.addFolder(self.part_doc, fonction_0, face)
2562 #dossier.execute(True)
2563 dossier.setName(nom)
2565 if ( len(self.l_faces_m) > 1 ):
2567 nom = self.objet_principal.name()
2568 if self._verbose_max:
2569 print ( "Dossier {} de {} à {}".format(nom,Partition_1.name(),Recover_1.name()))
2570 dossier = model.addFolder(self.part_doc, Partition_1, Recover_1)
2571 #dossier.execute(True)
2572 dossier.setName(nom)
2574 #=========================== Fin de la méthode ==================================
2576 #=========================== Début de la méthode =================================
2578 def surf_solide_shaper (self, solide, n_recur):
2579 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2582 :solide: solide SHAPER à traiter
2583 :n_recur: numéro de la récurrence
2586 :erreur: code d'erreur
2587 :message: message d'erreur
2590 nom_fonction = __name__ + "/surf_solide_shaper"
2591 blabla = "Dans {} :".format(nom_fonction)
2593 if self._verbose_max:
2594 print_tab (n_recur, blabla, saut_av=True)
2601 self.nom_solide = solide.name()
2602 if self._verbose_max:
2603 print_tab (n_recur, "solide : ", self.nom_solide)
2605 # 1. Isolement du solide
2606 solide_aux, recover = self._isole_solide ( solide, n_recur )
2608 # 2. Traitement de l'objet correspondant
2609 erreur, message = self._traitement_objet ( solide_aux, n_recur=n_recur )
2611 if ( erreur and self._verbose_max ):
2612 print (blabla, message)
2614 # 3. Neutralisation des erreurs dues à l'épaisseur
2615 if ( erreur in (-2,-1,2) ):
2621 # 4. Mise en forme de l'objet principal récupéré
2622 if ( recover is not None ):
2623 _ = self._nom_sous_objets (recover, False)
2627 return erreur, message
2629 #=========================== Fin de la méthode ==================================
2631 #========================== Fin de la classe ====================================
2633 #==================================================================================
2635 #==================================================================================
2637 if __name__ == "__main__" :
2639 HOME_SH_SM_EXCHANGE = os.environ["HOME_SH_SM_EXCHANGE"]
2641 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "Solid_7.step"))
2642 L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Objet_1.stp"))
2643 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval_007.stp"))
2644 ##L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval.stp"))
2645 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2.step"))
2646 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_22.step"))
2647 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_5.step"))
2648 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Observatoire.stp"))
2650 for FIC_CAO in L_FIC_CAO:
2655 #L_OPTIONS.append("-h")
2656 #L_OPTIONS.append("-v")
2657 L_OPTIONS.append("-vmax")
2658 L_OPTIONS.append("-export_step")
2660 # 2. Lancement de la classe
2662 #print ("L_OPTIONS :", L_OPTIONS)
2664 SURFACE_MEDIANE = SurfaceMediane(L_OPTIONS)
2665 if SURFACE_MEDIANE.affiche_aide_globale:
2666 sys.stdout.write(SURFACE_MEDIANE.__doc__+"\n")
2669 PARTSET = model.moduleDocument()
2670 _ = model.addPart(PARTSET)
2671 ERREUR, MESSAGE_ERREUR = SURFACE_MEDIANE.surf_fic_cao(FIC_CAO)
2673 MESSAGE_ERREUR += "\n Code d'erreur : %d\n" % ERREUR
2674 sys.stderr.write(MESSAGE_ERREUR)