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.23"
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 ("n_recur = {}".format(n_recur))
193 print_tab(n_recur, "objet : ", objet.name())
194 print_tab(n_recur, "RGB = ({},{},{})".format(coul_r,coul_g,coul_b))
196 # 1. Au premier passage, il faut garder la référence au résultat principal
199 objet_0 = objet.result()
203 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
205 nb_sub_results = objet_0.numberOfSubs()
208 print_tab(n_recur, "Examen de l'objet",objet_0.name())
209 texte = "Formé de {} sous-objets".format(nb_sub_results)
210 print_tab(n_recur, texte)
212 for n_sobj in range(nb_sub_results):
214 # 2.1. Exploration récursive de l'arborescence
216 couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b, verbose )
218 # 2.2. Cet objet n'a pas de sous-objets : on le colore
220 print_tab(n_recur, "Couleur affectée à l'objet ",objet_0.name())
221 objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
223 #print ("sortie de {}".format(nom_fonction))
225 #========================= Fin de la fonction ===================================
227 #========================= Début de la fonction ==================================
229 def print_tab (nb_tab, message, argu=None, saut_av=False, saut_ap=False):
230 """Imprime avec des tabulations
233 :nb_tab: nombre de tabulations à appliquer
234 :message: message principal
235 :argu: argument du format
236 :saut_av: saut de ligne avant le texte
237 :saut_ap: saut de ligne après le texte
245 for _ in range(nb_tab):
249 if ( argu is not None ):
250 texte += "{}".format(argu)
257 #========================= Fin de la fonction ===================================
259 #========================= Début de la fonction ==================================
261 def nommage (objet, nom, couleur=None):
262 """Nomme un objet et son résultat
265 :objet: objet à traiter
266 :nom: nom à attribuer
267 :couleur: éventuellement couleur
271 objet.result().setName(nom)
273 if ( couleur is not None ):
274 objet.result().setColor(couleur[0], couleur[1], couleur[2])
276 #========================= Fin de la fonction ===================================
278 #========================= Début de la fonction ==================================
280 def exec_nom (fonction, nom=None, couleur=None):
281 """Exécute la fonction puis éventuellement la nomme et nomme son résultat ; Couleur éventuelle
283 Attention : il faut commencer par exécuter la fonction sinon l enommage n'est pas cohérent en mode macro. Mystère...
286 :fonction: fonction à traiter
287 :nom: nom à attribuer éventuellement
288 :couleur: éventuellement couleur
291 fonction.execute(True)
293 if ( nom is not None ):
294 nommage (fonction, nom, couleur)
296 #========================= Fin de la fonction ===================================
299 #=================================== La classe ===================================
301 class SurfaceMediane (object):
303 """Calcul des surfaces médianes de solides minces
305 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
306 une structure qui est un solide ou un assemblage de solides (compound).
307 Pour réaliser l'opération, trois façons de faire :
309 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
311 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
312 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
314 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
315 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
318 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
319 de taille identique et supérieure aux tailles des autres faces du solide. \
320 Cela fonctionne pour des surfaces planes ou de forme canonique.
321 Il crée alors une surface au milieu de ces deux grandes faces. \
322 Cette face est coloriée en vert, le solide est en vert et transparent.
324 On sait traiter les faces :
331 Si la création n'a pas eu lieu, un message est émis et les solides sont mis en couleur :
332 . Rouge : le solide n'est pas assez mince.
333 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
334 . Orange : la forme de la face n'est pas reconnue.
342 . Exportation finale dans un fichier step. Par défaut, pas d'export.
343 -export_step/-no_export_step
346 surf_fic_cao --> import_cao
347 --> surf_objet_shaper (récursif) --> _nom_sous_objets
348 --> _surf_objet_shaper_0
349 --> surf_solide_shaper --> _isole_solide --> _isole_solide_a
351 --> _traitement_objet --> face_mediane_solide --> _faces_du_solide
353 --> _cree_face_mediane
355 _cree_face_mediane --> _cree_face_mediane_plane
356 --> _cree_face_mediane_cylindre
357 --> _cree_face_mediane_sphere
358 --> _cree_face_mediane_tore
359 --> _cree_face_mediane_cone
360 --> _cree_face_mediane_0
369 affiche_aide_globale = 0
376 nom_solide_aux = None
382 objet_principal = None
383 # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
385 # Statut de chaque sous-objet connu par son nom :
386 # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
388 # Liste des faces médianes créées et des fonctions initiales
390 # La fonction initiale
396 #=========================== Début de la méthode =================================
398 def __init__ ( self, liste_option ):
400 """Le constructeur de la classe SurfaceMediane
402 Décodage des arguments
403 On cherche ici les arguments généraux : aide, verbeux
406 for option in liste_option :
409 if isinstance(option,str):
410 saux = option.upper()
412 if saux in ( "-H", "-HELP" ):
413 self.affiche_aide_globale = 1
416 elif saux == "-VMAX" :
418 self._verbose_max = 1
419 elif saux == "-EXPORT_STEP":
420 self._export_step = True
421 elif saux == "-NO_EXPORT_STEP":
422 self._export_step = False
424 #=========================== Fin de la méthode ==================================
426 #=========================== Début de la méthode =================================
429 """A la suppression de l'instance de classe"""
430 if self._verbose_max:
431 print ("Suppression de l'instance de la classe.")
433 #=========================== Fin de la méthode ==================================
435 #=========================== Début de la méthode =================================
437 def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
438 """Gère les noms des sous_objets solides
441 :objet: objet à traiter
442 :lecture: vrai pour lire les noms, faux pour les attribuer
443 :n_recur: niveau de récursivité
444 :rang: rang du sous-objet
447 :rang: rang du sous-objet
450 nom_fonction = __name__ + "/_nom_sous_objets"
451 blabla = "Dans {} :\n".format(nom_fonction)
453 if self._verbose_max:
455 for _ in range(n_recur):
457 texte = "\n{}{}".format(prefixe,blabla)
458 texte += "{}n_recur = {}".format(prefixe,n_recur)
459 texte += "\n{}lecture = {}".format(prefixe,lecture)
462 # 1. Au premier passage, il faut garder la référence au résultat principal
465 objet_0 = objet.result()
466 if self._verbose_max:
467 print ("d_statut_so = {}".format(self.d_statut_so))
471 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
473 nb_sub_results = objet_0.numberOfSubs()
475 if self._verbose_max:
476 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
477 texte += "de type '{}'".format(objet_0.shapeType())
478 texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
481 for n_sobj in range(nb_sub_results):
483 # 2.1. Exploration récursive de l'arborescence
485 rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
487 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
489 if ( objet_0.shapeType() == "SOLID" ):
490 # A la lecture, on enregistre le nom
493 self.l_noms_so.append(nom)
494 self.d_statut_so[nom] = 0
495 # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
497 nom = self.l_noms_so[rang]
499 etat = self.d_statut_so[nom]
500 objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
502 objet_0.setTransparency (TRANSPARENCE)
507 #=========================== Fin de la méthode ==================================
509 #=========================== Début de la méthode =================================
511 def _isole_solide ( self, solide, n_recur ):
512 """Isole le solide de son arboresence
515 :solide: le solide à traiter
516 :n_recur: numéro de la récurrence
519 :objet: le solide isolé
520 :recover: la fonction de récupération
523 nom_fonction = __name__ + "/_isole_solide"
524 blabla = "Dans {} :".format(nom_fonction)
525 if self._verbose_max:
526 print_tab (n_recur, blabla)
527 texte = "Pour le solide '{}' ".format(solide.name())
528 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
529 print_tab (n_recur, texte)
531 if ( solide.name() != self.objet_principal.name() ):
532 objet, recover = self._isole_solide_a ( solide, n_recur )
535 objet, recover = self._isole_solide_b ( solide, n_recur )
537 if self._verbose_max:
538 print_tab (n_recur, "objet final : ", objet.name())
539 print_tab (n_recur, "fonction_0 : {}".format(self.fonction_0))
540 print_tab (n_recur, "recover : {}".format(recover))
542 return objet, recover
544 #=========================== Fin de la méthode ==================================
546 #=========================== Début de la méthode =================================
548 def _isole_solide_a ( self, solide, n_recur ):
549 """Isole le solide de son arboresence
552 :solide: le solide à traiter
553 :n_recur: numéro de la récurrence
556 :objet: le solide isolé
557 :recover: la fonction de récupération
560 nom_fonction = __name__ + "/_isole_solide_a"
561 blabla = "Dans {} :".format(nom_fonction)
562 if self._verbose_max:
563 print_tab (n_recur, blabla)
564 texte = "Pour le solide '{}' ".format(solide.name())
565 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
566 print_tab (n_recur, texte)
568 if self._verbose_max:
569 print_tab (n_recur, ". Extraction du solide '{}'".format(self.objet_principal.name()))
571 # 1. Extraction du solide
572 remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
573 remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
575 self.nom_solide_aux = "{}_S".format(solide.name())
576 if self._verbose_max:
577 print_tab (n_recur, "\tAttribution à remove_subshapes.result() du nom '{}'".format(self.nom_solide_aux))
578 exec_nom (remove_subshapes,self.nom_solide_aux)
580 self.fonction_0 = remove_subshapes
582 # 2. Récupération de l'objet principal
583 recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
584 if self._verbose_max:
585 print_tab (n_recur, "\tAttribution à recover du nom '{}'".format(self.objet_principal.name()))
586 exec_nom (recover,self.objet_principal.name())
588 return remove_subshapes.result(), recover
590 #=========================== Fin de la méthode ==================================
592 #=========================== Début de la méthode =================================
594 def _isole_solide_b ( self, solide, n_recur ):
595 """Isole le solide de son arboresence
598 :solide: le solide à traiter
599 :n_recur: numéro de la récurrence
602 :objet: le solide isolé
603 :recover: la fonction de récupération
606 nom_fonction = __name__ + "/_isole_solide_b"
607 blabla = "Dans {} :".format(nom_fonction)
608 if self._verbose_max:
609 print_tab (n_recur, blabla)
610 texte = "Pour le solide '{}' ".format(solide.name())
611 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
612 print_tab (n_recur, texte)
614 if self._verbose_max:
615 print_tab (n_recur, ". Mise en place du solide")
617 self.nom_solide_aux = self.objet_principal.name()
618 self.fonction_0 = None
622 #=========================== Fin de la méthode ==================================
624 #=========================== Début de la méthode =================================
626 def _faces_du_solide ( self, solide, n_recur=0 ):
627 """Détermine les faces d'un solide
630 :solide: solide SHAPER à traiter
631 :n_recur: niveau de récursivité
634 :l_faces_car: pour chaque face du solide (surface,caractéristiques)
637 nom_fonction = __name__ + "/_faces_du_solide"
638 blabla = "Dans {} :".format(nom_fonction)
639 if self._verbose_max:
640 print_tab (n_recur, blabla, saut_av=True)
644 if self._verbose_max:
645 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
646 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
649 #print_tab (n_recur, "volume = ", GeomAlgoAPI_ShapeTools.volume(solide.shape()))
650 # 1. Repérage des faces
651 objResult = solide.resultSubShapePair()[0]
653 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
655 l_faces.append(exp.current().face())
660 for iface, face in enumerate(l_faces):
661 surf = GeomAlgoAPI_ShapeTools.area(face)
662 caract = geom.shapeInfo(face)
663 if self._verbose_max:
664 print_tab (n_recur, "\tFace n°{} ; ".format(iface), "surface = {}, caractéristiques = {}".format(surf,caract))
665 l_faces_car.append((surf,caract))
669 #=========================== Fin de la méthode ==================================
671 #=========================== Début de la méthode =================================
673 def _calcul_caract_faces ( self, solide, n_recur ):
674 """Calcule les caractéristiques géométriques des faces du solide
677 :solide: solide SHAPER à traiter
678 :n_recur: niveau de récursivité
681 :tb_caract: tableau des caractéristiques géométriques des faces
684 nom_fonction = __name__ + "/_calcul_caract_faces"
685 blabla = "Dans {} :".format(nom_fonction)
686 if self._verbose_max:
687 print_tab (n_recur, blabla, saut_av=True)
688 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
689 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
691 # 1. Repérage des faces
692 objResult = solide.resultSubShapePair()[0]
694 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
696 l_faces.append(exp.current().face())
699 # 2. Caractéristiques
700 nb_faces = len(l_faces)
701 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
702 for iaux, face in enumerate(l_faces):
703 surf = GeomAlgoAPI_ShapeTools.area(face)
704 caract = geom.shapeInfo(face)
705 if self._verbose_max:
706 print_tab (n_recur, "\tFace n°{} ; ".format(iaux), "surface = {}, caractéristiques = {}".format(surf,caract))
708 tb_caract [iaux][0] = face
709 tb_caract [iaux][1] = surf
710 tb_caract [iaux][2] = caract
712 #if self._verbose_max:
713 #for iaux in range(nb_faces):
714 #print ("\t. tb_caract : {} {}".format(surf,tb_caract[iaux][2]))
718 #=========================== Fin de la méthode ==================================
720 #=========================== Début de la méthode =================================
722 def _tri_faces ( self, tb_caract, n_recur ):
723 """Trie les faces en fonction de leurs surfaces
726 :tb_caract: tableau des caractéristiques géométriques des faces
727 :n_recur: niveau de récursivité
730 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
736 nom_fonction = __name__ + "/_tri_faces"
737 blabla = "Dans {} :".format(nom_fonction)
739 # 1. Tri du tableau en fonction des surfaces
740 if self._verbose_max:
741 print_tab (n_recur, blabla)
742 print_tab (n_recur, "tb_caract brut : ", tb_caract)
743 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
744 if self._verbose_max:
745 print_tab (n_recur, "tb_caract trié :", tb_caract_1)
747 if self._verbose_max:
748 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
749 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
752 # 2. La surface suivante doit être différente, sinon ce n'est pas un solide mince
753 if ( len(tb_caract) > 2 ):
755 if self._verbose_max:
756 texte += "\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
758 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
759 if ( ecart < self._epsilon ):
760 message = "\nSolide '{}'\n".format(self.nom_solide)
761 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
762 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
763 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
764 if self._verbose_max:
765 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
766 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
767 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
769 self.d_statut_so[self.nom_solide] = -1
770 self.faces_pb_nb += 1
771 self.faces_pb_msg += message
773 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
775 #=========================== Fin de la méthode ==================================
777 #=========================== Début de la méthode =================================
779 def _verif_epaisseur ( self, epaisseur ):
780 """Contrôle de la validité de l'épaisseur
783 :epaisseur: épaisseur du solide
786 nom_fonction = __name__ + "/_verif_epaisseur"
787 blabla = "Dans {} :\n".format(nom_fonction)
789 if self._verbose_max:
791 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
792 texte += ". EP_MIN : {}".format(EP_MIN)
795 if ( epaisseur <= EP_MIN ):
796 message = "\nSolide '{}'\n".format(self.nom_solide)
797 message += ". Epaisseur : {}\n".format(epaisseur)
798 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
799 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
801 self.d_statut_so[self.nom_solide] = 2
802 self.faces_pb_nb += 1
803 self.faces_pb_msg += message
807 #print ("erreur = {}".format(erreur))
811 #=========================== Fin de la méthode ==================================
813 #=========================== Début de la méthode =================================
815 def _cree_face_mediane ( self, solide, caract_face_1, caract_face_2, n_recur ):
816 """Crée la face médiane entre deux autres
819 :solide: solide SHAPER à traiter
820 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
821 :n_recur: niveau de récursivité
824 :face: la face médiane créée
827 nom_fonction = __name__ + "/_cree_face_mediane"
828 blabla = "Dans {} :".format(nom_fonction)
830 if self._verbose_max:
831 print_tab (n_recur, blabla)
832 print_tab (n_recur, "face_1 : " ,caract_face_1)
833 print_tab (n_recur, "face_2 : " ,caract_face_2)
838 # 1. Forme de la face
839 forme = caract_face_1[2][0]
841 # 2. Traitement selon la forme de la face
843 if forme in ( "Disk" , "Plane", "Rectangle"):
844 erreur, face = self._cree_face_mediane_plane ( solide, caract_face_1, caract_face_2, n_recur )
846 # 2.2. Face cylindrique
847 elif ( forme == "Cylinder" ):
848 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
850 # 2.3. Face sphérique
851 elif ( forme == "Sphere" ):
852 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
855 elif ( forme == "Torus" ):
856 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
859 elif ( forme == "Cone" ):
860 erreur, face = self._cree_face_mediane_cone ( caract_face_1, caract_face_2, n_recur )
862 # 2.N. Face de forme inconnue
864 message = "\nSolide '{}'\n".format(self.nom_solide)
865 message += "sa face la plus grande est de forme : {}\n".format(forme)
866 message += "==> Impossible de créer la face médiane.\n"
868 self.d_statut_so[self.nom_solide] = -2
869 self.faces_pb_nb += 1
870 self.faces_pb_msg += message
872 # 3. Gestion de la face produite
875 self._cree_face_mediane_0 ( face, n_recur )
879 #=========================== Fin de la méthode ==================================
881 #=========================== Début de la méthode =================================
883 def _cree_face_mediane_0 ( self, face, n_recur ):
884 """Gestion de la face médiane créée entre deux autres
887 :face: la face médiane créée
888 :n_recur: niveau de récursivité
891 nom_fonction = __name__ + "/_cree_face_mediane_0"
892 blabla = "Dans {} :".format(nom_fonction)
894 if self._verbose_max:
895 print_tab (n_recur, blabla)
898 nom_face = self.nom_solide+"_M"
899 if self._verbose_max:
900 print_tab (n_recur,"Nom de la face créée : ", nom_face)
901 #if ( self.nom_solide_aux != self.objet_principal.name() ):
903 nommage (face, nom_face)
905 # 2. Mémorisation de la face et de la fonction initiale
906 self.l_faces_m.append((face, self.fonction_0))
908 # 3. Couleur verte pour la face
909 couleur_objet (face, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
911 # 4. Changement de statut pour le solide
912 self.d_statut_so[self.nom_solide] = 1
914 #=========================== Fin de la méthode ==================================
916 #=========================== Début de la méthode =================================
918 def _cree_face_mediane_plane ( self, solide, caract_face_1, caract_face_2, n_recur ):
919 """Crée la face médiane entre deux autres - cas des surfaces planes
922 :solide: l'objet solide à traiter
923 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
924 :n_recur: niveau de récursivité
927 :face: la face médiane
930 nom_fonction = __name__ + "/_cree_face_mediane_plane"
931 blabla = "Dans {} :".format(nom_fonction)
932 if self._verbose_max:
933 print_tab (n_recur, blabla)
935 # Caractéristiques des surfaces
936 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 )
938 # Contrôle de la validité de l'épaisseur
939 erreur = self._verif_epaisseur ( d_face_1_2 )
941 # Création de la face
943 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 )
949 #=========================== Fin de la méthode ==================================
951 #=========================== Début de la méthode =================================
953 def _cree_face_mediane_plane_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
954 """Crée la face médiane entre deux autres - cas des surfaces planes
956 Décodage des caractéristiques
959 :solide: l'objet solide à traiter
960 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
961 :n_recur: niveau de récursivité
964 :coo_x, coo_y, coo_z: coordonnées du centre de la base
965 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
966 :taille: estimation de la taille de la future face
967 :d_face_1_2: la distance entre les deux faces
970 nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
971 blabla = "Dans {} :".format(nom_fonction)
973 if self._verbose_max:
974 print_tab (n_recur, blabla)
975 print_tab (n_recur, "caract_face_1 : ", caract_face_1)
976 print_tab (n_recur, "caract_face_2 : ", caract_face_2)
978 # 1. Caractéristiques de la base
979 # Coordonnées du centre de la base
980 coo_x = caract_face_1[2][1]
981 coo_y = caract_face_1[2][2]
982 coo_z = caract_face_1[2][3]
983 # Coordonnées du vecteur normal
984 vnor_x = caract_face_1[2][4]
985 vnor_y = caract_face_1[2][5]
986 vnor_z = caract_face_1[2][6]
987 # taille : une longueur caractéristique pour être certain de tout prendre
988 l_diag = self._calcul_lg_caract ( solide, n_recur )
990 if self._verbose_max:
991 print_tab (n_recur, "Taille englobante : ",taille)
993 # 2. Distance entre les deux faces
994 face_1 = caract_face_1[0]
995 face_2 = caract_face_2[0]
996 d_face_1_2 = GeomAlgoAPI_ShapeTools.minimalDistance(face_1, face_2)
997 if self._verbose_max:
998 print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
1000 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
1002 #=========================== Fin de la méthode ==================================
1004 #=========================== Début de la méthode =================================
1006 def _cree_face_mediane_plane_1 ( self, solide, coo_c, vnor, taille, d_face_1_2, n_recur ):
1007 """Crée la face médiane entre deux autres - cas des surfaces planes
1009 Création des objets de construction et de la face médiane
1012 :solide: l'objet solide à traiter
1013 :coo_c: coordonnées du centre de la base
1014 :vnor: coordonnées du vecteur normal
1015 :taille: estimation de la taille de la future face
1016 :d_face_1_2: la distance entre les deux faces
1017 :n_recur: niveau de récursivité
1020 :face: la face médiane
1023 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
1024 blabla = "Dans {} :".format(nom_fonction)
1025 if self._verbose_max:
1026 print_tab (n_recur, blabla)
1027 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1028 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
1029 print_tab (n_recur, "Taille : ", taille)
1030 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1033 _, v_norm, plan = self._cree_centre_axe_plan ( coo_c, vnor, self.nom_solide, n_recur )
1035 # 2. Création de l'esquisse
1036 sketch = self._cree_face_mediane_plane_1_a ( plan, taille, n_recur )
1039 face = self._cree_face_mediane_plane_1_b ( solide, sketch, v_norm, d_face_1_2, n_recur )
1041 #print ("fin de {}".format(nom_fonction))
1045 #=========================== Fin de la méthode ==================================
1047 #=========================== Début de la méthode =================================
1049 def _cree_face_mediane_plane_1_a ( self, plan, taille, n_recur ):
1050 """Crée la face médiane entre deux autres - cas des surfaces planes - l'esquisse
1054 :taille: estimation de la taille de la future face
1055 :n_recur: niveau de récursivité
1061 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_a"
1062 blabla = "Dans {} :".format(nom_fonction)
1063 if self._verbose_max:
1064 print_tab (n_recur, blabla)
1065 print_tab (n_recur, "Plan : {}".format(plan.name()))
1066 print_tab (n_recur, "taille : {}".format(taille))
1068 sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1069 sketch.execute(True)
1071 ### Create SketchLine
1072 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1073 SketchLine_1.execute(True)
1075 ### Create SketchLine
1076 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1077 SketchLine_2.execute(True)
1079 ### Create SketchLine
1080 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1081 SketchLine_3.execute(True)
1083 ### Create SketchLine
1084 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1085 SketchLine_4.execute(True)
1089 nom_sketch = "{}_esquisse".format(self.nom_solide)
1090 exec_nom (sketch,nom_sketch)
1092 #print ("fin de {}".format(nom_fonction))
1096 #=========================== Fin de la méthode ==================================
1098 #=========================== Début de la méthode =================================
1100 def _cree_face_mediane_plane_1_b ( self, solide, sketch, v_norm, d_face_1_2, n_recur ):
1101 """Crée la face médiane entre deux autres - cas des surfaces planes
1103 Création de la face médiane
1106 :solide: l'objet solide à traiter
1108 :v_norm: vecteur normal
1109 :d_face_1_2: la distance entre les deux faces
1110 :n_recur: niveau de récursivité
1113 :face: la face médiane
1116 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_b"
1117 blabla = "Dans {} :".format(nom_fonction)
1118 if self._verbose_max:
1119 print_tab (n_recur, blabla)
1120 print_tab (n_recur, "Esquisse : ", sketch.name())
1121 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1123 # 1. Copie du solide pour gérer les intersections
1124 #Copy_1 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1125 Copy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1126 nom = "{}_Copy_1".format(self.nom_solide_aux)
1127 exec_nom (Copy_1,nom)
1128 if self._verbose_max:
1129 print_tab (n_recur, "Après addMultiTranslation Copy_1 de nom ", nom)
1130 nom_solide = Copy_1.result().name()
1133 Recover_1 = model.addRecover(self.part_doc, Copy_1, [solide])
1134 nom = "{}_Recover_1".format(self.nom_solide_aux)
1135 exec_nom (Recover_1,nom)
1136 if self._verbose_max:
1137 print_tab (n_recur, "Après addRecover Recover_1 de nom ", nom)
1139 # 2. Création d'une face ; on la translate d'une demi-épaisseur.
1140 for iaux in range(2):
1142 # 2.1. Création d'une face à partir du sketch et translation perpendiculaire au plan de la face
1143 # On essaie les 2 côtés alternativement car on ne sait pas lequel sera le bon
1145 d_trans = -0.5*d_face_1_2*float(2*iaux-1)
1147 face = self._cree_face_mediane_plane_2 ( sketch.name(), v_norm.name(), nom_solide, d_trans, iaux, n_recur )
1149 # 2.2. Si on est du bon côté, alors on intersecte la face avec le solide et c'est bon
1151 face = self._cree_face_mediane_plane_11 ( face, Recover_1, n_recur )
1154 # 2.3. Si l'intersection est vide, on crée une nouvelle copie du solide avant de tester l'autre côté
1156 if self._verbose_max:
1157 print_tab (n_recur, "L'intersection est vide. On essaie l'autre côté")
1159 ### Create LinearCopy
1160 #Copy_2 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1161 Copy_2 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", Recover_1.result().name())], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1162 nom = "{}_Copy_2".format(self.nom_solide_aux)
1163 exec_nom (Copy_2,nom)
1164 if self._verbose_max:
1165 print_tab (n_recur, "Après addMultiTranslation Copy_2 de nom ", nom)
1166 nom_solide = Copy_2.result().name()
1168 #print ("fin de {}".format(nom_fonction))
1172 #=========================== Fin de la méthode ==================================
1174 #=========================== Début de la méthode =================================
1176 def _cree_face_mediane_plane_11 ( self, face, Recover_1, n_recur ):
1177 """Crée la face médiane entre deux autres - cas des surfaces planes
1179 Création des objets de construction et de la face médiane
1182 :face: la face médiane
1183 :Recover_1: la récupératiuon du solide
1184 :n_recur: niveau de récursivité
1187 :face: la face médiane
1190 nom_fonction = __name__ + "/_cree_face_mediane_plane_11"
1191 blabla = "Dans {} :".format(nom_fonction)
1192 if self._verbose_max:
1193 print_tab (n_recur, blabla)
1194 print_tab (n_recur, "face : ", face.name())
1196 # Si on traite un objet solide unique, on le récupère
1197 if ( self.nom_solide_aux == self.objet_principal.name() ):
1198 if self._verbose_max:
1199 print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1200 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1201 nom = "{}_Recover_2".format(self.nom_solide_aux)
1202 exec_nom (Recover_2,nom)
1204 nb_inter = face.result().numberOfSubs()
1205 if self._verbose_max:
1206 print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1209 face = self._cree_face_mediane_plane_3 ( face )
1213 #=========================== Fin de la méthode ==================================
1215 #=========================== Début de la méthode =================================
1217 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, d_trans, icpt, n_recur ):
1218 """Crée la face médiane entre deux autres - cas des surfaces planes
1220 Intersection de la face avec le solide
1223 :nom_sketch: nom de l'esquisse
1224 :nom_normal: nom du vecteur normal
1225 :nom_solide: nom du solide à intersecter
1226 :d_trans: la distance de translation
1227 :icpt: numéro de la tentative
1230 :face: la face médiane
1233 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1234 blabla = "Dans {} :".format(nom_fonction)
1235 if self._verbose_max:
1236 print_tab (n_recur, blabla)
1237 print_tab (n_recur, "nom_sketch : ", nom_sketch)
1238 print_tab (n_recur, "nom_normal : ", nom_normal)
1239 print_tab (n_recur, "nom_solide : ", nom_solide)
1240 print_tab (n_recur, "d_trans : ", d_trans)
1242 # Création d'une face
1243 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1244 nom = "{}_Face_1_{}".format(self.nom_solide_aux,icpt)
1245 exec_nom (Face_1,nom)
1246 if self._verbose_max:
1247 print_tab (n_recur, "Après addFace pour Face_1 de nom ", nom)
1250 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)
1251 nom = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1252 exec_nom (Translation_1,nom)
1253 if self._verbose_max:
1254 print_tab (n_recur, "Après addTranslation pour Translation_1 de nom ", nom)
1255 Translation_1.result().setColor(85, 0, 255)
1257 # Intersection de cette face avec le solide initial
1258 face = self._creation_face_inter ( Translation_1.result().name(), nom_solide )
1262 #=========================== Fin de la méthode ==================================
1264 #=========================== Début de la méthode =================================
1266 def _cree_face_mediane_plane_3 ( self, face ):
1267 """Crée la face médiane entre deux autres - cas des surfaces planes
1269 Fusion des 2 intersections
1272 :face: la face médiane composée de plusieurs intersections
1275 :face_m: la face médiane
1278 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1279 blabla = "Dans {} :\n".format(nom_fonction)
1280 if self._verbose_max:
1284 # Nommage des sous-objets
1286 for iaux in range(face.result().numberOfSubs()):
1287 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1288 face.result().subResult(iaux).setName(nom)
1289 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1292 if self._verbose_max:
1293 print ("Fusion de {} faces.".format(len(l_fuse)))
1294 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1295 face_m.execute(True)
1299 #=========================== Fin de la méthode ==================================
1301 #=========================== Début de la méthode =================================
1303 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1304 """Crée la face médiane entre deux autres - cas des cylindres
1307 :solide: solide SHAPER à traiter
1308 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1309 :n_recur: niveau de récursivité
1312 :face: la face médiane
1315 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1316 blabla = "Dans {} :".format(nom_fonction)
1319 if self._verbose_max:
1320 print_tab (n_recur, blabla)
1321 print_tab (n_recur, "face_1 : ", caract_face_1)
1322 print_tab (n_recur, "face_2 : ", caract_face_2)
1324 # Caractéristiques des cylindres
1325 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 )
1327 # Contrôle de la validité de l'épaisseur
1328 erreur = self._verif_epaisseur ( epaisseur )
1330 # Création de la face, de couleur bleue si problème
1332 face = self._cree_face_mediane_cylindre_1 ( (coo_x, coo_y, coo_z), (axe_x, axe_y, axe_z), rayon, hauteur, n_recur )
1334 couleur_objet (solide, n_recur, coul_r=0, coul_g=0, coul_b=255, verbose=self._verbose_max)
1339 #=========================== Fin de la méthode ==================================
1341 #=========================== Début de la méthode =================================
1343 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1344 """Crée la face médiane entre deux autres - cas des cylindres
1346 Décodage des caractéristiques
1349 :solide: l'objet solide à traiter
1350 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1351 :n_recur: niveau de récursivité
1354 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1355 :axe_x, axe_y, axe_z: coordonnées de l'axe
1356 :rayon: rayon moyen entre les deux faces
1357 :hauteur: hauteur du cylindre
1358 :epaisseur: épaisseur de l'interface entre les deux faces
1361 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1362 blabla = "Dans {} :".format(nom_fonction)
1364 if self._verbose_max:
1365 print_tab (n_recur, blabla)
1366 print_tab (n_recur, "face_1 : ", caract_face_1)
1367 print_tab (n_recur, "face_2 : ", caract_face_2)
1369 # Coordonnées du centre de la base
1370 coo_x = caract_face_1[2][1]
1371 coo_y = caract_face_1[2][2]
1372 coo_z = caract_face_1[2][3]
1373 # Coordonnées de l'axe
1374 axe_x = caract_face_1[2][4]
1375 axe_y = caract_face_1[2][5]
1376 axe_z = caract_face_1[2][6]
1378 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1379 # Hauteur : une longueur caractéristique pour être certain de tout prendre
1380 l_diag = self._calcul_lg_caract ( solide, n_recur )
1381 hauteur = 10.*l_diag
1382 if self._verbose_max:
1383 print_tab (n_recur, "Hauteur englobante : ", hauteur)
1385 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1387 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1389 #=========================== Fin de la méthode ==================================
1391 #=========================== Début de la méthode =================================
1393 def _cree_face_mediane_cylindre_1 ( self, coo_c, v_axe, rayon, hauteur, n_recur ):
1394 """Crée la face médiane entre deux autres - cas des cylindres
1396 Création des objets temporaires et de la face externe du cylindre support
1399 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1400 :axe_x, axe_y, axe_z: coordonnées de l'axe
1401 :rayon: rayon moyen entre les deux faces
1402 :hauteur: hauteur du cylindre
1403 :n_recur: niveau de récursivité
1406 :face: la face médiane
1408 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1409 blabla = "Dans {} :\n".format(nom_fonction)
1411 # Les caractéristiques du cylindre à créer
1412 if self._verbose_max:
1413 print_tab (n_recur, blabla)
1414 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1415 print_tab (n_recur, "Axe : ({}, {}, {})".format(v_axe[0], v_axe[1], v_axe[2]))
1416 print_tab (n_recur, "Rayon : ", rayon)
1417 print_tab (n_recur, "Hauteur : ", hauteur)
1419 # 1. Création du point central
1420 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
1421 nom_centre = "{}_centre".format(self.nom_solide)
1422 exec_nom (centre,nom_centre)
1423 if self.fonction_0 is None:
1424 self.fonction_0 = centre
1426 # 2. Création du vecteur axial
1427 axe = model.addAxis(self.part_doc, v_axe[0], v_axe[1], v_axe[2])
1428 nom_axe = "{}_vecteur".format(self.nom_solide)
1429 exec_nom (axe,nom_axe)
1431 # 3. Création du cylindre en volume, de rayon médian
1432 Cylinder_1 = model.addCylinder(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon, hauteur)
1433 nom = "{}_Cylinder_1".format(self.nom_solide)
1434 exec_nom (Cylinder_1,nom)
1436 # 4. Création du cylindre en surface
1437 cylindre = self._creation_face_surface ( nom, "cylindre" )
1440 Translation_1 = model.addTranslation(self.part_doc, [model.selection("COMPOUND", cylindre.name())], axis = model.selection("EDGE", nom_axe), distance = -0.5*hauteur, keepSubResults = True)
1441 nom = "{}_Translation_1".format(self.nom_solide)
1442 exec_nom (Translation_1,nom)
1444 # 6. Intersection de la face cylindrique avec le solide initial
1445 face = self._creation_face_inter ( nom )
1449 #=========================== Fin de la méthode ==================================
1451 #=========================== Début de la méthode =================================
1453 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1454 """Crée la face médiane entre deux autres - cas des sphères
1457 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1458 :n_recur: niveau de récursivité
1461 :face: la face médiane
1464 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1465 blabla = "Dans {} :".format(nom_fonction)
1468 if self._verbose_max:
1469 print_tab (n_recur, blabla)
1470 print_tab (n_recur, "face_1 : ", caract_face_1)
1471 print_tab (n_recur, "face_2 : ", caract_face_2)
1473 # Caractéristiques des sphères
1474 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1476 # Contrôle de la validité de l'épaisseur
1477 erreur = self._verif_epaisseur ( epaisseur )
1479 # Création de la face
1481 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1487 #=========================== Fin de la méthode ==================================
1489 #=========================== Début de la méthode =================================
1491 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1492 """Crée la face médiane entre deux autres - cas des sphères
1494 Décodage des caractéristiques
1497 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1498 :n_recur: niveau de récursivité
1501 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1502 :rayon: rayon moyen entre les deux faces
1503 :epaisseur: épaisseur de l'interface entre les deux faces
1506 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1507 blabla = "Dans {} :".format(nom_fonction)
1510 if self._verbose_max:
1511 print_tab (n_recur, blabla)
1512 print_tab (n_recur, "face_1 : ", caract_face_1)
1513 print_tab (n_recur, "face_2 : ", caract_face_2)
1515 # Coordonnées du centre de la sphère
1516 coo_x = caract_face_1[2][1]
1517 coo_y = caract_face_1[2][2]
1518 coo_z = caract_face_1[2][3]
1520 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1522 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1524 return coo_x, coo_y, coo_z, rayon, epaisseur
1526 #=========================== Fin de la méthode ==================================
1528 #=========================== Début de la méthode =================================
1530 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1531 """Crée la face médiane entre deux autres - cas des sphères
1533 Création des objets de construction et de la face externe de la sphère support
1536 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1537 :rayon: rayon moyen entre les deux faces
1540 :face: la face externe de la sphère support
1543 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1544 blabla = "Dans {} :\n".format(nom_fonction)
1546 # Les caractéristiques de la sphère à créer
1547 if self._verbose_max:
1549 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1550 texte += "Rayon : {}".format(rayon)
1553 # 1. Création du point central
1554 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1555 nom_centre = "{}_centre".format(self.nom_solide)
1556 exec_nom (centre,nom_centre)
1557 if self.fonction_0 is None:
1558 self.fonction_0 = centre
1560 # 2. Création de la sphère en volume, de rayon médian
1561 Sphere_1 = model.addSphere(self.part_doc, model.selection("VERTEX", nom_centre), rayon)
1562 nom = "{}_Sphere_1".format(self.nom_solide)
1563 exec_nom (Sphere_1,nom)
1565 # 3. Création de la sphère en surface
1566 sphere = self._creation_face_surface ( nom, "sphere" )
1568 # 4. Intersection de la face sphérique avec le solide initial
1569 face = self._creation_face_inter ( sphere.name() )
1573 #=========================== Fin de la méthode ==================================
1575 #=========================== Début de la méthode =================================
1577 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1578 """Crée la face médiane entre deux autres - cas des tores
1581 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1582 :n_recur: niveau de récursivité
1585 :face: la face médiane
1588 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1589 blabla = "Dans {} :".format(nom_fonction)
1592 if self._verbose_max:
1593 print_tab (n_recur, blabla)
1594 print_tab (n_recur, "face_1 : ", caract_face_1)
1595 print_tab (n_recur, "face_2 : ", caract_face_2)
1597 # Caractéristiques des tores
1598 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 )
1600 # Contrôle de la validité de l'épaisseur (bidon)
1601 erreur = self._verif_epaisseur ( EP_MIN*10. )
1603 # Création de la face
1605 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1611 #=========================== Fin de la méthode ==================================
1613 #=========================== Début de la méthode =================================
1615 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1616 """Crée la face médiane entre deux autres - cas des tores
1618 Décodage des caractéristiques
1621 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1622 :n_recur: niveau de récursivité
1625 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1626 :axe_x, axe_y, axe_z: coordonnées de l'axe
1627 :rayon_1 : rayon principal
1628 :rayon_2 : rayon secondaire
1631 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1632 blabla = "Dans {} :".format(nom_fonction)
1635 if self._verbose_max:
1636 print_tab (n_recur, blabla)
1637 print_tab (n_recur, "face_1 : ", caract_face_1)
1638 print_tab (n_recur, "face_2 : ", caract_face_2)
1640 # Coordonnées du centre du tore
1641 coo_x = caract_face_1[2][1]
1642 coo_y = caract_face_1[2][2]
1643 coo_z = caract_face_1[2][3]
1644 # Coordonnées de l'axe
1645 axe_x = caract_face_1[2][4]
1646 axe_y = caract_face_1[2][5]
1647 axe_z = caract_face_1[2][6]
1649 rayon_1 = caract_face_2[2][7]
1650 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1652 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1654 #=========================== Fin de la méthode ==================================
1656 #=========================== Début de la méthode =================================
1658 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1659 """Crée la face médiane entre deux autres - cas des tores
1661 Création des objets de construction et de la face externe du tore support
1664 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1665 :axe_x, axe_y, axe_z: coordonnées de l'axe
1666 :rayon_1 : rayon principal
1667 :rayon_2 : rayon secondaire
1670 :face: la face externe du tore support
1673 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1674 blabla = "Dans {} :\n".format(nom_fonction)
1677 if self._verbose_max:
1679 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1680 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1681 texte += "Rayon principal : {}\n".format(rayon_1)
1682 texte += "Rayon secondaire : {}".format(rayon_2)
1685 # 1. Création du point central
1686 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1687 nom_centre = "{}_centre".format(self.nom_solide)
1688 exec_nom (centre,nom_centre)
1690 # 2. Création de l'axe
1691 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1692 nom_axe = "{}_axe".format(self.nom_solide)
1693 exec_nom (axe,nom_axe)
1695 # 3. Création du tore en volume, de rayon médian
1696 Tore_1 = model.addTorus(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon_1, rayon_2)
1697 nom = "{}_Tore_1".format(self.nom_solide)
1698 exec_nom (Tore_1,nom)
1700 # 4. Création du tore en surface
1701 tore = self._creation_face_surface ( nom, "tore" )
1703 # 5. Intersection de la face torique avec le solide initial
1704 face = self._creation_face_inter ( tore.name() )
1708 #=========================== Fin de la méthode ==================================
1710 #=========================== Début de la méthode =================================
1712 def _cree_face_mediane_cone ( self, caract_face_1, caract_face_2, n_recur ):
1713 """Crée la face médiane entre deux autres - cas des cones
1716 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1717 :n_recur: niveau de récursivité
1720 :face: la face médiane
1723 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1724 blabla = "Dans {} :".format(nom_fonction)
1727 if self._verbose_max:
1728 print_tab (n_recur, blabla)
1729 print_tab (n_recur, "face_1 : ", caract_face_1)
1730 print_tab (n_recur, "face_2 : ", caract_face_2)
1732 # Caractéristiques des cones
1733 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 )
1735 # Contrôle de la validité de l'épaisseur (bidon)
1736 erreur = self._verif_epaisseur ( EP_MIN*10. )
1738 # Création de la face
1740 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1746 #=========================== Fin de la méthode ==================================
1748 #=========================== Début de la méthode =================================
1750 def _cree_face_mediane_cone_0 ( self, caract_face_1, caract_face_2, n_recur ):
1751 """Crée la face médiane entre deux autres - cas des cones
1753 Décodage des caractéristiques
1756 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1757 :n_recur: niveau de récursivité
1760 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1761 :axe_x, axe_y, axe_z: coordonnées de l'axe
1762 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1763 :hauteur: hauteur du cone
1766 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1767 blabla = "Dans {} :".format(nom_fonction)
1770 if self._verbose_max:
1771 print_tab (n_recur, blabla)
1772 print_tab (n_recur, "face_1 : ", caract_face_1)
1773 print_tab (n_recur, "face_2 : ", caract_face_2)
1775 # Coordonnées du centre de la base
1776 coo_x = caract_face_1[2][1]
1777 coo_y = caract_face_1[2][2]
1778 coo_z = caract_face_1[2][3]
1779 # Coordonnées de l'axe
1780 axe_x = caract_face_1[2][4]
1781 axe_y = caract_face_1[2][5]
1782 axe_z = caract_face_1[2][6]
1784 rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1785 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1787 hauteur = caract_face_1[2][9]
1790 if self._verbose_max:
1791 print_tab (n_recur, "coo_x : ", coo_x)
1792 print_tab (n_recur, "coo_y : ", coo_y)
1793 print_tab (n_recur, "coo_z : ", coo_z)
1794 print_tab (n_recur, "axe_x : ", axe_x)
1795 print_tab (n_recur, "axe_y : ", axe_y)
1796 print_tab (n_recur, "axe_z : ", axe_z)
1797 print_tab (n_recur, "rayon_1 : ", rayon_1)
1798 print_tab (n_recur, "rayon_2 : ", rayon_2)
1799 print_tab (n_recur, "hauteur : ", hauteur)
1801 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1803 #=========================== Fin de la méthode ==================================
1805 #=========================== Début de la méthode =================================
1807 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1808 """Crée la face médiane entre deux autres - cas des cones
1810 Création des objets de construction et de la face externe du cone support
1813 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1814 :axe_x, axe_y, axe_z: coordonnées de l'axe
1815 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1816 :hauteur: hauteur du cone
1819 :face: la face externe du cone support
1821 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1822 blabla = "Dans {} :\n".format(nom_fonction)
1825 if self._verbose_max:
1827 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1828 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1829 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1830 texte += "Hauteur : {}".format(hauteur)
1833 # 1. Création du point central de la base, côté rayon_1
1834 centre_1 = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1835 nom_centre_1 = "{}_centre_1".format(self.nom_solide)
1836 exec_nom (centre_1,nom_centre_1)
1838 # 2. Création du point central, du côté de rayon_2
1839 centre_2 = model.addPoint(self.part_doc, coo_x+hauteur*axe_x, coo_y+hauteur*axe_y, coo_z+hauteur*axe_z)
1840 nom_centre_2 = "{}_centre_2".format(self.nom_solide)
1841 exec_nom (centre_2,nom_centre_2)
1843 # 3. Création de l'axe
1844 axe = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre_1), model.selection("VERTEX", nom_centre_2))
1845 nom_axe = "{}_axe".format(self.nom_solide)
1846 exec_nom (axe,nom_axe)
1848 # 4. Création d'un plan passant par le centre de la base et l'axe
1849 # 4.1. Création d'un vecteur perpendiculaire à l'axe
1851 if ( (abs(axe_x)+abs(axe_y)) < self._epsilon ):
1852 v_perp = model.addAxis(self.part_doc, coeff, 0., 0.)
1854 v_perp = model.addAxis(self.part_doc, -coeff*axe_y, coeff*axe_x, 0.)
1855 nom_v_perp = "{}_v_perp".format(self.nom_solide)
1856 exec_nom (v_perp,nom_v_perp)
1857 # 4.2. Création du plan
1858 plan = model.addPlane(self.part_doc, model.selection("EDGE",nom_v_perp), model.selection("VERTEX", nom_centre_1), True)
1859 nom_plan = "{}_plan".format(self.nom_solide)
1860 exec_nom (plan,nom_plan)
1863 nom_par_1 = "{}_R_1".format(self.nom_solide)
1864 param = model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1866 nom_par_2 = "{}_R_2".format(self.nom_solide)
1867 param = model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1869 nom_par_3 = "{}_H".format(self.nom_solide)
1870 param = model.addParameter(self.part_doc, "{}".format(nom_par_3), "{}".format(hauteur))
1873 # 6. Création de l'esquisse
1875 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1876 sketch.execute(True)
1878 # 6.1. Projection des centres et de l'axe
1879 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre_1), False)
1880 SketchProjection_1.execute(True)
1881 SketchPoint_1 = SketchProjection_1.createdFeature()
1882 SketchPoint_1.execute(True)
1883 sk_coo_x_1 = SketchAPI_Point(SketchPoint_1).coordinates().x()
1884 sk_coo_y_1 = SketchAPI_Point(SketchPoint_1).coordinates().y()
1886 SketchProjection_2 = sketch.addProjection(model.selection("VERTEX", nom_centre_2), False)
1887 SketchProjection_2.execute(True)
1888 SketchPoint_2 = SketchProjection_2.createdFeature()
1889 SketchPoint_2.execute(True)
1890 sk_coo_x_2 = SketchAPI_Point(SketchPoint_2).coordinates().x()
1891 sk_coo_y_2 = SketchAPI_Point(SketchPoint_2).coordinates().y()
1893 SketchProjection_3 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1894 SketchProjection_3.execute(True)
1895 SketchLine_0 = SketchProjection_3.createdFeature()
1896 SketchLine_0.execute(True)
1898 # 6.2. Lignes perpendiculaires à l'axe passant par les centres
1899 SketchLine_1 = sketch.addLine(sk_coo_x_1, sk_coo_y_1, sk_coo_x_1+rayon_1, sk_coo_y_1)
1900 SketchLine_1.execute(True)
1901 SketchLine_1.setAuxiliary(True)
1902 contrainte = sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.startPoint())
1903 contrainte.execute(True)
1904 contrainte = sketch.setPerpendicular(SketchLine_0.result(), SketchLine_1.result())
1905 contrainte.execute(True)
1906 contrainte = sketch.setLength(SketchLine_1.result(), nom_par_1)
1907 contrainte.execute(True)
1909 SketchLine_2 = sketch.addLine(sk_coo_x_2, sk_coo_y_2, sk_coo_x_2+rayon_2, sk_coo_y_2)
1910 SketchLine_2.execute(True)
1911 SketchLine_2.setAuxiliary(True)
1912 contrainte = sketch.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_2.startPoint())
1913 contrainte.execute(True)
1914 contrainte = sketch.setPerpendicular(SketchLine_0.result(), SketchLine_2.result())
1915 contrainte.execute(True)
1916 contrainte = sketch.setLength(SketchLine_2.result(), nom_par_2)
1917 contrainte.execute(True)
1919 # 6.3. Ligne joignant les extrémités des précédentes et point milieu
1920 SketchLine_3 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
1921 SketchLine_3.execute(True)
1922 contrainte = sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_1.endPoint())
1923 contrainte.execute(True)
1924 contrainte = sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_2.endPoint())
1925 contrainte.execute(True)
1926 SketchLine_3.setAuxiliary(True)
1927 SketchPoint_3 = sketch.addPoint(sk_coo_x_1, sk_coo_y_1)
1928 SketchPoint_3.execute(True)
1929 contrainte = sketch.setMiddlePoint(SketchLine_3.result(), SketchPoint_3.coordinates())
1930 contrainte.execute(True)
1932 # 6.4. Ligne support de la future révolution
1933 SketchLine_4 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
1934 SketchLine_4.execute(True)
1935 contrainte = sketch.setMiddlePoint(SketchLine_4.result(), SketchPoint_3.coordinates())
1936 contrainte.execute(True)
1937 contrainte = sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_4.result())
1938 contrainte.execute(True)
1939 contrainte = sketch.setLength(SketchLine_4.result(), "1.2*{}".format(nom_par_3))
1940 contrainte.execute(True)
1944 nom_sketch = "{}_esquisse".format(self.nom_solide)
1945 exec_nom (sketch,nom_sketch)
1947 # 7. Création du cone complet
1948 nom_cone = "{}_cone".format(self.nom_solide)
1949 self._cree_revolution ( nom_sketch, nom_centre_1, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_cone )
1951 # 8. Intersection de la face conique avec le solide initial
1952 face = self._creation_face_inter ( nom_cone )
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 ( self, objet, n_recur ):
2008 """Crée une longueur caractéristique de l'objet
2011 :objet: l'objet à traiter
2012 :n_recur: niveau de récursivité
2015 :l_caract: longueur caractéristique de l'objet
2018 nom_fonction = __name__ + "/_calcul_lg_caract"
2019 blabla = "Dans {} :".format(nom_fonction)
2021 if self._verbose_max:
2022 print_tab (n_recur, blabla)
2024 properties = model.getGeometryCalculation(self.part_doc,model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
2025 l_caract = properties[0]
2027 if self._verbose_max:
2028 print_tab (n_recur, "Longueur caractéristique : ", l_caract)
2032 #=========================== Fin de la méthode ==================================
2034 #=========================== Début de la méthode =================================
2036 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
2037 """Crée un volume de révolution
2040 :nom_sketch: nom de l'esquisse à révolutionner
2041 :nom_centre: nom du point associé au centre du volume de révolution
2042 :coo_x, coo_y, coo_z: coordonnées du centre du tore
2043 :axe_x, axe_y, axe_z: coordonnées de l'axe
2044 :rayon_1 : rayon principal
2045 :rayon_2 : rayon secondaire
2046 :nom_objet: nom de l'objet 2D créé
2049 nom_fonction = __name__ + "/_cree_revolution"
2050 blabla = "Dans {} :\n".format(nom_fonction)
2052 if self._verbose_max:
2054 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
2055 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
2058 # Création d'un point décalé par rapport au point central
2059 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
2060 nom_point = "{}_point".format(self.nom_solide)
2061 exec_nom (point,nom_point)
2063 # Création de l'axe de la rotation
2064 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
2065 nom_axe_r = "{}_axe_r".format(self.nom_solide)
2066 exec_nom (axe_r,nom_axe_r)
2068 # Création de l'objet complet
2069 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
2070 exec_nom (objet, nom_objet, (85, 0, 255))
2072 #=========================== Fin de la méthode ==================================
2074 #=========================== Début de la méthode =================================
2076 def _creation_face_surface ( self, nom_objet, suffixe ):
2077 """Crée la face qui est la surface externe d'un objet
2079 . Crée le groupe de la face externe
2080 . Transforme le groupe en face résultat
2083 :nom_objet: nom de l'objet 3D à traiter
2084 :suffixe: suffixe pour nommer l'objet 2D
2085 :nom_solide: nom du solide initial ; si None, on prend self.nom_solide_aux
2088 :objet_2d: l'objet 2D support de la face externe de l'objet 3D
2091 nom_fonction = __name__ + "/_creation_face_inter"
2092 blabla = "Dans {} :\n".format(nom_fonction)
2094 if self._verbose_max:
2097 # 1. Le groupe de la surface
2098 groupe = model.addGroup(self.part_doc, "Faces", [model.selection("FACE", "{}/Face_1".format(nom_objet))])
2099 nom = "{}_{}_groupe".format(self.nom_solide,suffixe)
2100 exec_nom (groupe, nom, (85, 0, 255))
2102 # 2. Création de la face en surface
2103 objet_2d = model.addGroupShape(self.part_doc, [model.selection("COMPOUND", nom)])
2104 nom = "{}_{}".format(self.nom_solide,suffixe)
2105 exec_nom (objet_2d, nom, (85, 0, 255))
2109 #=========================== Fin de la méthode ==================================
2111 #=========================== Début de la méthode =================================
2113 def _creation_face_inter ( self, nom_objet, nom_solide=None ):
2114 """Crée la face par intersection entre l'objet initial et une face complète
2116 . Repère la face principale de l'objet support
2117 . Réalise l'intersection avec le solide initial
2120 :nom_objet: nom de l'objet 2D créé
2121 :nom_solide: nom du solide initial ; si None, on prend self.nom_solide_aux
2124 :face: la face externe de l'objet support intersecté avec le solide initial
2127 nom_fonction = __name__ + "/_creation_face_inter"
2128 blabla = "Dans {} :\n".format(nom_fonction)
2130 if self._verbose_max:
2133 if nom_solide is None:
2134 nom_solide = self.nom_solide_aux
2136 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_objet)], keepSubResults = True)
2141 #=========================== Fin de la méthode ==================================
2143 #=========================== Début de la méthode =================================
2145 def face_mediane_solide (self, solide, n_recur=0):
2146 """Calcul de la face médiane pour un solide
2149 :solide: solide SHAPER à traiter
2150 :n_recur: niveau de récursivité
2153 :erreur: code d'erreur
2154 :message: message d'erreur
2157 nom_fonction = __name__ + "/face_mediane_solide"
2158 blabla = "Dans {} :".format(nom_fonction)
2160 if self._verbose_max:
2161 print_tab (n_recur, blabla, saut_av=True)
2163 print_tab (n_recur, "Traitement du solide ", solide.name())
2172 # 2. Calcul des caractéristiques géométriques des faces
2174 tb_caract = self._calcul_caract_faces ( solide, n_recur )
2176 # 3. Tri des faces en fonction de leurs caractéristiques géométriques
2178 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract, n_recur )
2182 # 4. Création de la face médiane
2184 erreur, face = self._cree_face_mediane ( solide, caract_face_1, caract_face_2, n_recur )
2185 if ( erreur or ( face is None ) ):
2188 # 6. Exportation step
2190 if self._export_step:
2191 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2192 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2193 export.execute(True)
2200 if ( erreur and self._verbose_max ):
2201 print (blabla, message)
2203 return erreur, message
2205 #=========================== Fin de la méthode ==================================
2207 #=========================== Début de la méthode =================================
2209 def _traitement_objet (self, solide, n_recur=0):
2210 """Traitement d'un objet
2213 :solide: solide SHAPER à traiter
2214 :n_recur: niveau de récursivité
2217 :erreur: code d'erreur
2218 :message: message d'erreur
2221 nom_fonction = __name__ + "/_traitement_objet"
2222 blabla = "Dans {} :".format(nom_fonction)
2224 if self._verbose_max:
2225 print_tab (n_recur, blabla, saut_av=True)
2226 texte = "solide = {} ".format(solide.name())
2227 print_tab (n_recur, texte, solide)
2229 # 1. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2230 # Attention à ne pas recréer le répertoire à chaque fois
2231 if self._export_step:
2233 if self.rep_step is None:
2235 if self._verbose_max:
2236 print_tab (n_recur, "Préparation de l'export STEP")
2238 if self.ficcao is None:
2239 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2241 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2242 if os.path.isdir(self.rep_step):
2243 l_aux = os.listdir(self.rep_step)
2244 for nomfic in l_aux:
2245 os.remove(os.path.join(self.rep_step,nomfic))
2247 os.mkdir(self.rep_step)
2249 if self._verbose_max:
2250 print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2252 # 2. Calcul réel de la face médiane
2254 erreur, message = self.face_mediane_solide (solide, n_recur)
2256 return erreur, message
2258 #=========================== Fin de la méthode ==================================
2260 #=========================== Début de la méthode =================================
2262 def surf_fic_cao (self, ficcao, nom_objet=None):
2263 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2266 :ficcao: fichier de l'objet à traiter
2267 :nom_objet: un nom à donner à l'objet à traiter
2270 :erreur: code d'erreur
2271 :message: message d'erreur
2274 nom_fonction = __name__ + "/surf_fic_cao"
2275 blabla = "Dans {} :".format(nom_fonction)
2277 if self._verbose_max:
2287 if self.affiche_aide_globale:
2290 # 1. Définition de la pièce
2292 self.part_doc = model.activeDocument()
2293 if ( self.part_doc.kind() == "PartSet" ):
2294 part = model.addPart(self.part_doc)
2295 self.part_doc = part.document()
2297 # 2. Import de la CAO
2299 self.ficcao = ficcao
2300 print ("Traitement du fichier {}".format(ficcao))
2302 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2306 # 3. Calcul des surfaces
2308 erreur, message = self.surf_objet_shaper ( objet )
2315 if ( erreur and self._verbose_max ):
2316 print (blabla, message)
2318 return erreur, message
2320 #=========================== Fin de la méthode ==================================
2322 #=========================== Début de la méthode =================================
2324 def surf_objet_shaper (self, objet):
2325 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2328 :objet: objet à traiter
2331 :erreur: code d'erreur
2332 :message: message d'erreur
2335 nom_fonction = __name__ + "/surf_objet_shaper"
2336 blabla = "Dans {} :".format(nom_fonction)
2338 if self._verbose_max:
2346 if self.affiche_aide_globale:
2349 # 1. Acquisition de la liste des noms des sous-objets solides
2351 self.d_statut_so = dict()
2352 self.l_noms_so = list()
2353 self.l_faces_m = list()
2355 _ = self._nom_sous_objets (objet, True)
2356 if self._verbose_max:
2357 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2359 # 2. Les faces médianes
2361 erreur, message = self._surf_objet_shaper_0 ( objet )
2365 # 3. Gestion des faces créées
2367 self._surf_objet_shaper_1 ( )
2369 # 4. Futur message pour le résultat
2371 if ( self._export_step and not erreur ):
2372 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2376 return erreur, message
2378 #=========================== Fin de la méthode ==================================
2380 #=========================== Début de la méthode =================================
2382 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2383 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2386 :objet: objet à traiter
2387 :n_recur: niveau de récursivité
2390 :erreur: code d'erreur
2391 :message: message d'erreur
2394 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2395 blabla = "Dans {} :".format(nom_fonction)
2397 if self._verbose_max:
2398 print_tab (n_recur, blabla)
2399 print_tab (n_recur, "n_recur = ", n_recur)
2406 # 1. Au premier passage, il faut récupérer la pièce SHAPER et garder la référence au résultat principal
2408 if ( n_recur == 0 ):
2409 self.part_doc = model.activeDocument()
2410 objet_0 = objet.result()
2411 self.objet_principal = objet_0
2412 objet_bis = objet.defaultResult().shape()
2413 if self._verbose_max:
2414 print_tab (0, "Examen de l'objet initial ", objet.result().name(), saut_av=True)
2415 print_tab (0, "Type python : ", type(objet))
2416 print_tab (0, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2419 if self._verbose_max:
2420 print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2421 print_tab (n_recur, "Type python : ", type(objet))
2422 print_tab (n_recur, "shapeType : ", objet.shapeType())
2424 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2426 nb_sub_results = objet_0.numberOfSubs()
2428 if self._verbose_max:
2429 print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType(), saut_av=True)
2430 print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2432 for n_sobj in range(nb_sub_results):
2434 # 2.1. Exploration récursive de l'arborescence
2436 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2443 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2445 if ( objet_0.shapeType() == "SOLID" ):
2446 erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2450 # 3. Futur message pour le résultat
2452 if self._export_step:
2453 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2457 return erreur, message
2459 #=========================== Fin de la méthode ==================================
2461 #=========================== Début de la méthode =================================
2463 def _surf_objet_shaper_1 (self, n_recur=0):
2464 """Gestion des surfaces médianes créées
2467 :n_recur: niveau de récursivité
2470 :erreur: code d'erreur
2471 :message: message d'erreur
2474 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2475 blabla = "Dans {} :\n".format(nom_fonction)
2477 if self._verbose_max:
2478 print_tab (n_recur, blabla)
2480 # 1. Informations sur les faces à problème
2482 if self.faces_pb_nb:
2483 if ( self.faces_pb_nb == 1 ):
2484 texte = "1 face pose"
2486 texte = "{} faces posent".format(self.faces_pb_nb)
2487 print_tab (n_recur, "{} problème.".format(texte), self.faces_pb_msg, saut_av=True)
2489 # 2. Si plus d'une face a été créée
2490 if ( len(self.l_faces_m) > 1 ):
2492 # 2.1. Partition du paquet de faces
2494 if self._verbose_max:
2495 print_tab (n_recur, "Partitionnnement des faces créées.")
2497 # 2.1.1. Pour une raison mystérieuse, il faut commencer par les faces entières, puis mettre les sous-faces éventuelles
2499 for (face,_) in self.l_faces_m:
2500 if not face.result().numberOfSubs():
2501 d_faces[face.name()] = [face.name()]
2502 for (face,_) in self.l_faces_m:
2503 nb_sub_results = face.result().numberOfSubs()
2506 for n_sobj in range(nb_sub_results):
2507 laux.append(face.result().subResult(n_sobj).name())
2508 d_faces[face.name()] = laux
2511 for _, laux in d_faces.items():
2512 for s_face_n in laux:
2513 l_objets.append(model.selection("FACE", s_face_n))
2515 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2516 nom = "{}_M".format(self.objet_principal.name())
2517 exec_nom (Partition_1,nom)
2520 for face_n, laux in d_faces.items():
2521 Partition_1.result().subResult(iaux).setName("{}".format(face_n))
2522 if ( len(laux) > 1 ):
2523 for jaux, s_face_n in enumerate(laux):
2524 Partition_1.result().subResult(iaux).subResult(jaux).setName("{}_M".format(s_face_n))
2526 couleur_objet (Partition_1, n_recur, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
2528 # 2.2. Récupération des faces individuelles
2530 if self._verbose_max:
2531 print_tab (n_recur, "Récupération des faces individuelles.")
2534 for iaux, (face,_) in enumerate(self.l_faces_m):
2535 l_objets.append(face.result())
2537 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2538 exec_nom (Recover_1)
2539 for iaux, (face,_) in enumerate(self.l_faces_m):
2540 Recover_1.results()[iaux].setName("{}".format(face.name()))
2541 Recover_1.results()[iaux].setColor(0, 170, 0)
2542 nb_sub_results = Recover_1.results()[iaux].numberOfSubs()
2543 for n_sobj in range(nb_sub_results):
2544 Recover_1.results()[iaux].subResult(n_sobj).setName("{}_{}".format(face.name(),n_sobj))
2545 Recover_1.results()[iaux].subResult(n_sobj).setColor(0, 170, 0)
2547 # 3. Mise en dossier
2549 if self._verbose_max:
2550 print_tab (n_recur, "Mise en dossier.")
2552 for (face,fonction_0) in self.l_faces_m:
2553 if fonction_0 is not None:
2554 nom = face.name()[:-2]
2555 if self._verbose_max:
2556 print ( "Dossier {} de {} à {}".format(nom,fonction_0.name(),face.name()))
2557 dossier = model.addFolder(self.part_doc, fonction_0, face)
2558 dossier.setName(nom)
2560 if ( len(self.l_faces_m) > 1 ):
2562 nom = self.objet_principal.name()
2563 if self._verbose_max:
2564 print ( "Dossier {} de {} à {}".format(nom,Partition_1.name(),Recover_1.name()))
2565 dossier = model.addFolder(self.part_doc, Partition_1, Recover_1)
2566 dossier.setName(nom)
2568 #=========================== Fin de la méthode ==================================
2570 #=========================== Début de la méthode =================================
2572 def surf_solide_shaper (self, solide, n_recur):
2573 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2576 :solide: solide SHAPER à traiter
2577 :n_recur: numéro de la récurrence
2580 :erreur: code d'erreur
2581 :message: message d'erreur
2584 nom_fonction = __name__ + "/surf_solide_shaper"
2585 blabla = "Dans {} :".format(nom_fonction)
2587 if self._verbose_max:
2588 print_tab (n_recur, blabla, saut_av=True)
2595 self.nom_solide = solide.name()
2596 if self._verbose_max:
2597 print_tab (n_recur, "solide : ", self.nom_solide)
2599 # 1. Isolement du solide
2600 solide_aux, recover = self._isole_solide ( solide, n_recur )
2602 # 2. Traitement de l'objet correspondant
2603 erreur, message = self._traitement_objet ( solide_aux, n_recur=n_recur )
2605 if ( erreur and self._verbose_max ):
2606 print (blabla, message)
2608 # 3. Neutralisation des erreurs dues à l'épaisseur
2609 if ( erreur in (-2,-1,2) ):
2615 # 4. Mise en forme de l'objet principal récupéré
2616 if ( recover is not None ):
2617 _ = self._nom_sous_objets (recover, False)
2621 return erreur, message
2623 #=========================== Fin de la méthode ==================================
2625 #========================== Fin de la classe ====================================